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