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