PluginProbe ʕ •ᴥ•ʔ
Matomo Analytics – Powerful, Privacy-First Insights for WordPress / 5.1.3
Matomo Analytics – Powerful, Privacy-First Insights for WordPress v5.1.3
5.13.0 5.12.1 5.12.0 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 / Settings.php
matomo / classes / WpMatomo Last commit date
Admin 1 year ago Commands 2 years ago Db 2 years ago Ecommerce 2 years ago Report 2 years ago Site 2 years ago TrackingCode 1 year ago Updater 4 years ago User 2 years ago Workarounds 2 years ago WpStatistics 2 years ago views 4 years ago API.php 2 years ago Access.php 4 years ago AjaxTracker.php 1 year ago Annotations.php 4 years ago Bootstrap.php 2 years ago Capabilities.php 4 years ago Compatibility.php 2 years ago Email.php 2 years ago ErrorNotice.php 2 years ago Installer.php 2 years ago Logger.php 2 years ago OptOut.php 4 years ago Paths.php 2 years ago PluginAdminOverrides.php 2 years ago PrivacyBadge.php 4 years ago RedirectOnActivation.php 4 years ago Referral.php 2 years ago Roles.php 4 years ago ScheduledTasks.php 1 year ago Settings.php 1 year ago Site.php 3 years ago TrackingCode.php 1 year ago Uninstaller.php 2 years ago Updater.php 2 years ago User.php 4 years ago
Settings.php
491 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 * Code Based on
9 * @author Andr&eacute; Br&auml;kling
10 * https://github.com/braekling/matomo
11 *
12 */
13
14 namespace WpMatomo;
15
16 use Piwik\CliMulti\Process;
17 use WpMatomo\Admin\CookieConsent;
18 use WpMatomo\Admin\TrackingSettings;
19
20 if ( ! defined( 'ABSPATH' ) ) {
21 exit; // if accessed directly
22 }
23
24 class Settings {
25 const OPTION_PREFIX = 'matomo-';
26 const GLOBAL_OPTION_PREFIX = 'matomo_global-';
27 const OPTION = 'matomo-option';
28 const OPTION_GLOBAL = 'matomo-global-option';
29 const OPTION_KEY_CAPS_ACCESS = 'caps_access';
30 const OPTION_KEY_STEALTH = 'caps_tracking';
31 const OPTION_LAST_TRACKING_SETTINGS_CHANGE = 'last_tracking_settings_update';
32 const OPTION_LAST_TRACKING_CODE_UPDATE = 'last_tracking_code_update';
33 const SHOW_GET_STARTED_PAGE = 'show_get_started_page';
34 const DELETE_ALL_DATA_ON_UNINSTALL = 'delete_all_data_uninstall';
35 const SITE_CURRENCY = 'site_currency';
36 const NETWORK_CONFIG_OPTIONS = 'config_options';
37 const DISABLE_ASYNC_ARCHIVING_OPTION_NAME = 'matomo_disable_async_archiving';
38
39 public static $is_doing_action_tracking_related = false;
40 /**
41 * @internal tests only
42 * @var bool
43 */
44 public $force_disable_addhandler = false;
45
46 /**
47 * Tests only
48 *
49 * @ignore
50 * @var bool
51 */
52 private $assume_is_network_enabled_in_tests = false;
53
54 /**
55 * Register default configuration set
56 *
57 * (public for tests)
58 *
59 * @var array
60 */
61 public $default_global_settings = [
62 // Plugin settings
63 'last_settings_update' => 0,
64 self::OPTION_LAST_TRACKING_SETTINGS_CHANGE => 0,
65 self::OPTION_KEY_STEALTH => [],
66 self::OPTION_KEY_CAPS_ACCESS => [],
67 self::NETWORK_CONFIG_OPTIONS => [],
68 self::DELETE_ALL_DATA_ON_UNINSTALL => true,
69 self::SITE_CURRENCY => 'USD',
70 // User settings: Stats configuration
71 // User settings: Tracking configuration
72 'track_mode' => 'disabled',
73 'track_js_endpoint' => 'default',
74 'track_api_endpoint' => 'default',
75 'track_codeposition' => 'footer',
76 'track_noscript' => false,
77 'track_content' => 'disabled',
78 'track_ecommerce' => true,
79 'track_search' => false,
80 'track_404' => false,
81 'tagmanger_container_ids' => [],
82 'add_post_annotations' => [],
83 'add_customvars_box' => false,
84 'js_manually' => '',
85 'noscript_manually' => '',
86 'add_download_extensions' => '',
87 'set_download_extensions' => '',
88 'set_link_classes' => '',
89 'set_download_classes' => '',
90 'core_version' => '',
91 'version_history' => [],
92 'mail_history' => [],
93 'disable_cookies' => false,
94 'cookie_consent' => CookieConsent::REQUIRE_NONE,
95 'force_post' => false,
96 'limit_cookies' => false,
97 'limit_cookies_visitor' => 34186669, // Matomo default 13 months
98 'limit_cookies_session' => 1800, // Matomo default 30 minutes
99 'limit_cookies_referral' => 15778463, // Matomo default 6 months
100 'track_admin' => false,
101 'track_across' => false,
102 'track_across_alias' => false,
103 'track_crossdomain_linking' => false,
104 'track_feed' => false,
105 'track_feed_addcampaign' => false,
106 'track_feed_campaign' => 'feed',
107 'track_heartbeat' => 0,
108 'track_user_id' => 'disabled',
109 'track_datacfasync' => false,
110 'track_jserrors' => false,
111 'force_protocol' => 'disabled',
112 'maxmind_license_key' => '',
113 self::SHOW_GET_STARTED_PAGE => 1,
114 self::DISABLE_ASYNC_ARCHIVING_OPTION_NAME => false,
115 ];
116
117 /**
118 * Settings stored per blog
119 *
120 * @var array
121 */
122 private $default_blog_settings = [
123 'noscript_code' => '',
124 'tracking_code' => '',
125 self::OPTION_LAST_TRACKING_CODE_UPDATE => 0,
126 ];
127
128 private $global_settings = [];
129 private $blog_settings = [];
130
131 private $settings_changed = [];
132
133 /**
134 * @var Logger
135 */
136 private $logger;
137
138 /**
139 * Constructor class to prepare settings manager
140 *
141 */
142 public function __construct() {
143 $this->logger = new Logger();
144
145 $this->init_settings();
146 }
147
148 public function init_settings() {
149 $this->settings_changed = [];
150 $this->global_settings = [];
151 $this->blog_settings = [];
152
153 if ( $this->is_network_enabled() ) {
154 $global_settings = get_site_option( self::OPTION_GLOBAL, [] );
155 } else {
156 $global_settings = get_option( self::OPTION_GLOBAL, [] );
157 }
158
159 if ( ! empty( $global_settings ) && is_array( $global_settings ) ) {
160 $this->global_settings = $global_settings;
161 }
162
163 $settings = get_option( self::OPTION, [] );
164
165 if ( ! empty( $settings ) && is_array( $settings ) ) {
166 $this->blog_settings = $settings;
167 }
168 }
169
170 public function get_customised_global_settings() {
171 $custom_settings = [];
172
173 foreach ( $this->global_settings as $key => $val ) {
174 if ( isset( $this->default_global_settings[ $key ] )
175 // phpcs:ignore WordPress.PHP.StrictComparisons.LooseComparison
176 && $this->default_global_settings[ $key ] != $val ) {
177 $custom_settings[ $key ] = $val;
178 }
179 }
180
181 return $custom_settings;
182 }
183
184 public function uninstall() {
185 Uninstaller::uninstall_options( self::OPTION_PREFIX );
186 Uninstaller::uninstall_options( self::GLOBAL_OPTION_PREFIX );
187 Uninstaller::uninstall_site_meta( self::GLOBAL_OPTION_PREFIX );
188 $this->init_settings();
189 }
190
191 public function is_multisite() {
192 return function_exists( 'is_multisite' ) && is_multisite();
193 }
194
195 /**
196 * @api
197 */
198 public function is_network_enabled() {
199 if ( $this->assume_is_network_enabled_in_tests ) {
200 return true;
201 }
202
203 if ( ! function_exists( 'is_plugin_active_for_network' ) ) {
204 require_once ABSPATH . 'wp-admin/includes/plugin.php';
205 }
206
207 return is_plugin_active_for_network( 'matomo/matomo.php' );
208 }
209
210 /**
211 * Save all settings as WordPress options
212 */
213 public function save() {
214 if ( empty( $this->settings_changed ) ) {
215 $this->logger->log( 'No settings changed yet' );
216
217 return;
218 }
219
220 $this->logger->log( 'Save settings' );
221
222 if ( $this->is_network_enabled() ) {
223 update_site_option( self::OPTION_GLOBAL, $this->global_settings );
224 } else {
225 update_option( self::OPTION_GLOBAL, $this->global_settings );
226 }
227
228 update_option( self::OPTION, $this->blog_settings );
229
230 $keys_changed = array_values( array_unique( $this->settings_changed ) );
231 $this->settings_changed = [];
232
233 foreach ( $keys_changed as $key_changed ) {
234 do_action( 'matomo_setting_change_' . $key_changed );
235 }
236 }
237
238 /**
239 * Get a global option's value
240 *
241 * @param string $key
242 * option key
243 *
244 * @return string|array option value
245 * @api
246 */
247 public function get_global_option( $key ) {
248 if ( isset( $this->global_settings[ $key ] ) ) {
249 return $this->global_settings[ $key ];
250 }
251
252 if ( isset( $this->default_global_settings[ $key ] ) ) {
253 return $this->default_global_settings[ $key ];
254 }
255 }
256
257 /**
258 * Get an option's value related to a specific blog
259 *
260 * @param string $key option key
261 *
262 * @return string|array
263 * @api
264 */
265 public function get_option( $key ) {
266 if ( isset( $this->blog_settings[ $key ] ) ) {
267 return $this->blog_settings[ $key ];
268 }
269
270 if ( isset( $this->default_blog_settings[ $key ] ) ) {
271 return $this->default_blog_settings[ $key ];
272 }
273 }
274
275 private function convert_type( $value, $type ) {
276 if ( 'array' === $type && empty( $value ) ) {
277 $value = []; // prevent eg converting '' to array('')
278 } else {
279 settype( $value, $type );
280 }
281
282 return $value;
283 }
284
285 /**
286 * Set a global option's value
287 *
288 * @param string $key option key
289 * @param string|array $value new option value
290 */
291 public function set_global_option( $key, $value ) {
292 if ( isset( $this->default_global_settings[ $key ] ) ) {
293 $type = gettype( $this->default_global_settings[ $key ] );
294 $value = $this->convert_type( $value, $type );
295 }
296
297 if ( ! isset( $this->global_settings[ $key ] )
298 || $this->global_settings[ $key ] !== $value ) {
299 $this->settings_changed[] = $key;
300 $this->logger->log( 'Changed global option ' . $key . ': ' . ( is_array( $value ) ? wp_json_encode( $value ) : $value ) );
301
302 $this->global_settings[ $key ] = $value;
303 }
304 }
305
306 /**
307 * Set an option's value related to a specific blog
308 *
309 * @param string $key option key
310 * @param string $value new option value
311 */
312 public function set_option( $key, $value ) {
313 if ( isset( $this->default_blog_settings[ $key ] ) ) {
314 $type = gettype( $this->default_blog_settings[ $key ] );
315 $value = $this->convert_type( $value, $type );
316 }
317
318 if ( ! isset( $this->blog_settings[ $key ] )
319 || $this->blog_settings[ $key ] !== $value ) {
320 $this->settings_changed[] = $key;
321 $this->logger->log( 'Changed option ' . $key . ': ' . $value );
322 $this->blog_settings[ $key ] = $value;
323 }
324 }
325
326 /**
327 * @param array $values
328 *
329 * @api
330 */
331 public function apply_tracking_related_changes( $values ) {
332 $this->set_global_option( self::OPTION_LAST_TRACKING_SETTINGS_CHANGE, time() );
333
334 $this->apply_changes( $values );
335
336 if ( ! self::$is_doing_action_tracking_related ) {
337 // prevent recurison if any plugin was listening to this event and calling this method again
338 self::$is_doing_action_tracking_related = true;
339 do_action( 'matomo_tracking_settings_changed', $this, $values );
340 self::$is_doing_action_tracking_related = false;
341 }
342 }
343
344 public function should_disable_addhandler() {
345 if ( $this->force_disable_addhandler ) {
346 return true;
347 }
348
349 return defined( 'MATOMO_DISABLE_ADDHANDLER' ) && MATOMO_DISABLE_ADDHANDLER;
350 }
351
352 /**
353 * Apply new configuration
354 *
355 * @param array $settings
356 * new configuration set
357 *
358 * @api
359 */
360 public function apply_changes( $settings ) {
361 $this->logger->log( 'Apply changed settings:' );
362 foreach ( $this->default_global_settings as $key => $val ) {
363 if ( isset( $settings[ $key ] ) ) {
364 $this->set_global_option( $key, $settings[ $key ] );
365 }
366 }
367 foreach ( $this->default_blog_settings as $key => $val ) {
368 if ( isset( $settings[ $key ] ) ) {
369 $this->set_option( $key, $settings[ $key ] );
370 }
371 }
372 $this->set_global_option( 'last_settings_update', time() );
373
374 if ( $this->should_save_tracking_code_across_sites() ) {
375 // special case for when the same tracking code needs to be used across all instances
376 $this->set_global_option( 'js_manually', $this->get_option( 'tracking_code' ) );
377 $this->set_global_option( 'noscript_manually', $this->get_option( 'noscript_code' ) );
378 }
379
380 $this->save();
381 }
382
383 private function should_save_tracking_code_across_sites() {
384 return $this->is_network_enabled()
385 && $this->get_global_option( 'track_mode' ) === TrackingSettings::TRACK_MODE_MANUALLY;
386 }
387
388 public function get_js_tracking_code() {
389 if ( $this->should_save_tracking_code_across_sites() ) {
390 return $this->get_global_option( 'js_manually' );
391 }
392
393 return $this->get_option( 'tracking_code' );
394 }
395
396 public function get_noscript_tracking_code() {
397 if ( $this->should_save_tracking_code_across_sites() ) {
398 return $this->get_global_option( 'noscript_manually' );
399 }
400
401 return $this->get_option( 'noscript_code' );
402 }
403
404 public function is_cross_domain_linking_enabled() {
405 return $this->get_global_option( 'track_crossdomain_linking' );
406 }
407
408 public function should_delete_all_data_on_uninstall() {
409 if ( defined( 'MATOMO_REMOVE_ALL_DATA' ) ) {
410 return (bool) MATOMO_REMOVE_ALL_DATA;
411 }
412
413 return (bool) $this->get_global_option( self::DELETE_ALL_DATA_ON_UNINSTALL );
414 }
415
416 /**
417 * Check if feed tracking is enabled
418 *
419 * @return boolean Is feed tracking enabled?
420 */
421 public function is_track_feed() {
422 return $this->get_global_option( 'track_feed' );
423 }
424
425 /**
426 * Check if admin tracking is enabled
427 *
428 * @return boolean Is admin tracking enabled?
429 */
430 public function is_admin_tracking_enabled() {
431 return $this->get_global_option( 'track_admin' ) && is_admin();
432 }
433
434 public function is_current_tracking_code() {
435 $last_tracking_code_update = $this->get_option( self::OPTION_LAST_TRACKING_CODE_UPDATE );
436 $last_tracking_settings_update = $this->get_global_option( self::OPTION_LAST_TRACKING_SETTINGS_CHANGE );
437
438 return $last_tracking_code_update && $last_tracking_code_update > $last_tracking_settings_update;
439 }
440
441 /**
442 * Check if feed permalinks get a campaign parameter
443 *
444 * @return boolean Add campaign parameter to feed permalinks?
445 */
446 public function is_add_feed_campaign() {
447 return $this->get_global_option( 'track_feed_addcampaign' );
448 }
449
450 public function is_tracking_enabled() {
451 return $this->get_global_option( 'track_mode' ) !== 'disabled';
452 }
453
454 /**
455 * Check if noscript code insertion is enabled
456 *
457 * @return boolean Insert noscript code?
458 */
459 public function is_add_no_script_code() {
460 return $this->get_global_option( 'track_noscript' );
461 }
462
463 public function get_tracking_code_position() {
464 return $this->get_global_option( 'track_codeposition' );
465 }
466
467 public function track_404_enabled() {
468 return $this->get_global_option( 'track_404' );
469 }
470
471 public function track_user_id_enabled() {
472 return $this->get_global_option( 'track_user_id' ) !== 'disabled';
473 }
474
475 public function track_search_enabled() {
476 return ( is_search() && $this->get_global_option( 'track_search' ) );
477 }
478
479 public function set_assume_is_network_enabled_in_tests( $network_enabled = true ) {
480 $this->assume_is_network_enabled_in_tests = $network_enabled;
481 }
482
483 public function is_async_archiving_supported() {
484 return Process::isSupported() && ( ! defined( 'MATOMO_SUPPORT_ASYNC_ARCHIVING' ) || MATOMO_SUPPORT_ASYNC_ARCHIVING );
485 }
486
487 public function is_async_archiving_disabled_by_option() {
488 return (bool) $this->get_global_option( self::DISABLE_ASYNC_ARCHIVING_OPTION_NAME );
489 }
490 }
491