PluginProbe ʕ •ᴥ•ʔ
Matomo Analytics – Powerful, Privacy-First Insights for WordPress / 4.15.0
Matomo Analytics – Powerful, Privacy-First Insights for WordPress v4.15.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 / app / core / SettingsPiwik.php
matomo / app / core Last commit date
API 2 years ago Access 3 years ago Application 4 years ago Archive 3 years ago ArchiveProcessor 2 years ago Archiver 5 years ago AssetManager 3 years ago Auth 3 years ago Category 5 years ago Changes 3 years ago CliMulti 4 years ago Columns 3 years ago Concurrency 3 years ago Config 4 years ago Container 4 years ago CronArchive 3 years ago DataAccess 2 years ago DataFiles 5 years ago DataTable 2 years ago Db 3 years ago DeviceDetector 3 years ago Email 5 years ago Exception 3 years ago Http 4 years ago Intl 4 years ago Mail 3 years ago Measurable 5 years ago Menu 3 years ago Metrics 4 years ago Notification 4 years ago Period 4 years ago Plugin 2 years ago ProfessionalServices 4 years ago Report 5 years ago ReportRenderer 2 years ago Scheduler 4 years ago Segment 3 years ago Session 4 years ago Settings 3 years ago Tracker 3 years ago Translation 4 years ago UpdateCheck 5 years ago Updater 3 years ago Updates 3 years ago Validators 4 years ago View 4 years ago ViewDataTable 3 years ago Visualization 4 years ago Widget 5 years ago Access.php 4 years ago Archive.php 3 years ago ArchiveProcessor.php 2 years ago AssetManager.php 4 years ago Auth.php 5 years ago AuthResult.php 5 years ago BaseFactory.php 5 years ago Cache.php 5 years ago CacheId.php 5 years ago CliMulti.php 4 years ago Common.php 3 years ago Config.php 3 years ago Console.php 3 years ago Context.php 5 years ago Cookie.php 3 years ago CronArchive.php 3 years ago DataArray.php 4 years ago DataTable.php 2 years ago Date.php 3 years ago Db.php 4 years ago DbHelper.php 3 years ago Development.php 5 years ago ErrorHandler.php 5 years ago EventDispatcher.php 3 years ago ExceptionHandler.php 3 years ago FileIntegrity.php 3 years ago Filechecks.php 4 years ago Filesystem.php 3 years ago FrontController.php 3 years ago Http.php 3 years ago IP.php 4 years ago Log.php 4 years ago LogDeleter.php 4 years ago Mail.php 3 years ago Metrics.php 3 years ago NoAccessException.php 5 years ago Nonce.php 3 years ago Notification.php 5 years ago NumberFormatter.php 4 years ago Option.php 4 years ago Period.php 5 years ago Piwik.php 3 years ago Plugin.php 4 years ago Profiler.php 4 years ago ProxyHeaders.php 5 years ago ProxyHttp.php 3 years ago QuickForm2.php 5 years ago RankingQuery.php 3 years ago ReportRenderer.php 4 years ago Segment.php 3 years ago Sequence.php 5 years ago Session.php 3 years ago SettingsPiwik.php 3 years ago SettingsServer.php 5 years ago Singleton.php 5 years ago Site.php 3 years ago SiteContentDetector.php 2 years ago SupportedBrowser.php 3 years ago TCPDF.php 5 years ago Theme.php 5 years ago Timer.php 5 years ago Tracker.php 4 years ago Twig.php 4 years ago Unzip.php 5 years ago UpdateCheck.php 5 years ago Updater.php 4 years ago UpdaterErrorException.php 5 years ago Updates.php 5 years ago Url.php 2 years ago UrlHelper.php 3 years ago Version.php 2 years ago View.php 3 years ago bootstrap.php 3 years ago dispatch.php 5 years ago testMinimumPhpVersion.php 3 years ago
SettingsPiwik.php
521 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 *
8 */
9 namespace Piwik;
10
11 use Exception;
12 use Piwik\Cache as PiwikCache;
13 use Piwik\Config\GeneralConfig;
14 use Piwik\Container\StaticContainer;
15
16 /**
17 * Contains helper methods that can be used to get common Piwik settings.
18 *
19 */
20 class SettingsPiwik
21 {
22 public const OPTION_PIWIK_URL = 'piwikUrl';
23
24 /**
25 * Get salt from [General] section. Should ONLY be used as a seed to create hashes
26 *
27 * NOTE: Keep this salt secret! Never output anywhere or share it etc.
28 *
29 * @return string|null
30 */
31 public static function getSalt(): ?string
32 {
33 static $salt = null;
34 if (is_null($salt)) {
35 $salt = Config::getInstance()->General['salt'] ?? '';
36 }
37 return $salt;
38 }
39
40 /**
41 * Should Piwik check that the login & password have minimum length and valid characters?
42 *
43 * @return bool True if checks enabled; false otherwise
44 */
45 public static function isUserCredentialsSanityCheckEnabled(): bool
46 {
47 return Config::getInstance()->General['disable_checks_usernames_attributes'] == 0;
48 }
49
50 /**
51 * Should Piwik show the update notification to superusers only?
52 *
53 * @return bool True if show to superusers only; false otherwise
54 */
55 public static function isShowUpdateNotificationToSuperUsersOnlyEnabled(): bool
56 {
57 return Config::getInstance()->General['show_update_notification_to_superusers_only'] == 1;
58 }
59
60 /**
61 * Returns every stored segment to pre-process for each site during cron archiving.
62 *
63 * @return array The list of stored segments that apply to all sites.
64 */
65 public static function getKnownSegmentsToArchive(): array
66 {
67 $cacheId = 'KnownSegmentsToArchive';
68 $cache = PiwikCache::getTransientCache();
69 if ($cache->contains($cacheId)) {
70 return $cache->fetch($cacheId);
71 }
72
73 $segments = Config::getInstance()->Segments;
74 $segmentsToProcess = isset($segments['Segments']) ? $segments['Segments'] : array();
75
76 /**
77 * Triggered during the cron archiving process to collect segments that
78 * should be pre-processed for all websites. The archiving process will be launched
79 * for each of these segments when archiving data.
80 *
81 * This event can be used to add segments to be pre-processed. If your plugin depends
82 * on data from a specific segment, this event could be used to provide enhanced
83 * performance.
84 *
85 * _Note: If you just want to add a segment that is managed by the user, use the
86 * SegmentEditor API._
87 *
88 * **Example**
89 *
90 * Piwik::addAction('Segments.getKnownSegmentsToArchiveAllSites', function (&$segments) {
91 * $segments[] = 'country=jp;city=Tokyo';
92 * });
93 *
94 * @param array &$segmentsToProcess List of segment definitions, eg,
95 *
96 * array(
97 * 'browserCode=ff;resolution=800x600',
98 * 'country=jp;city=Tokyo'
99 * )
100 *
101 * Add segments to this array in your event handler.
102 */
103 Piwik::postEvent('Segments.getKnownSegmentsToArchiveAllSites', array(&$segmentsToProcess));
104
105 $segmentsToProcess = array_unique($segmentsToProcess);
106
107 $cache->save($cacheId, $segmentsToProcess);
108 return $segmentsToProcess;
109 }
110
111 /**
112 * Returns the list of stored segments to pre-process for an individual site when executing
113 * cron archiving.
114 *
115 * @param int $idSite The ID of the site to get stored segments for.
116 * @return string[] The list of stored segments that apply to the requested site.
117 */
118 public static function getKnownSegmentsToArchiveForSite($idSite): array
119 {
120 $cacheId = 'KnownSegmentsToArchiveForSite' . $idSite;
121 $cache = PiwikCache::getTransientCache();
122 if ($cache->contains($cacheId)) {
123 return $cache->fetch($cacheId);
124 }
125
126 $segments = array();
127 /**
128 * Triggered during the cron archiving process to collect segments that
129 * should be pre-processed for one specific site. The archiving process will be launched
130 * for each of these segments when archiving data for that one site.
131 *
132 * This event can be used to add segments to be pre-processed for one site.
133 *
134 * _Note: If you just want to add a segment that is managed by the user, you should use the
135 * SegmentEditor API._
136 *
137 * **Example**
138 *
139 * Piwik::addAction('Segments.getKnownSegmentsToArchiveForSite', function (&$segments, $idSite) {
140 * $segments[] = 'country=jp;city=Tokyo';
141 * });
142 *
143 * @param array &$segmentsToProcess List of segment definitions, eg,
144 *
145 * array(
146 * 'browserCode=ff;resolution=800x600',
147 * 'country=JP;city=Tokyo'
148 * )
149 *
150 * Add segments to this array in your event handler.
151 * @param int $idSite The ID of the site to get segments for.
152 */
153 Piwik::postEvent('Segments.getKnownSegmentsToArchiveForSite', array(&$segments, $idSite));
154
155 $segments = array_unique($segments);
156
157 $cache->save($cacheId, $segments);
158
159 return $segments;
160 }
161
162 /**
163 * Number of websites to show in the Website selector
164 *
165 * @return int
166 */
167 public static function getWebsitesCountToDisplay(): int
168 {
169 $count = max(Config::getInstance()->General['site_selector_max_sites'],
170 Config::getInstance()->General['autocomplete_min_sites']);
171 return (int)$count;
172 }
173
174 /**
175 * Returns the URL to this Piwik instance, eg. **http://demo.piwik.org/** or **http://example.org/piwik/**.
176 *
177 * @return string|false return false if no value is configured and we are in PHP CLI mode
178 * @api
179 */
180 public static function getPiwikUrl()
181 {
182 $url = Option::get(self::OPTION_PIWIK_URL);
183
184 $isPiwikCoreDispatching = defined('PIWIK_ENABLE_DISPATCH') && PIWIK_ENABLE_DISPATCH;
185 if (Common::isPhpCliMode()
186 // in case core:archive command is triggered (often with localhost domain)
187 || SettingsServer::isArchivePhpTriggered()
188 // When someone else than core is dispatching this request then we return the URL as it is read only
189 || !$isPiwikCoreDispatching
190 ) {
191 return $url;
192 }
193
194 $currentUrl = Common::sanitizeInputValue(Url::getCurrentUrlWithoutFileName());
195
196 // when script is called from /misc/cron/archive.php, Piwik URL is /index.php
197 $currentUrl = str_replace("/misc/cron", "", $currentUrl);
198
199 if (empty($url)
200 // if URL changes, always update the cache
201 || $currentUrl !== $url
202 ) {
203 $host = Url::getHostFromUrl($currentUrl);
204
205 if (strlen($currentUrl) >= strlen('http://a/')
206 && Url::isValidHost($host)
207 && !Url::isLocalHost($host)) {
208 self::overwritePiwikUrl($currentUrl);
209 }
210 $url = $currentUrl;
211 }
212
213 if (ProxyHttp::isHttps()) {
214 $url = str_replace("http://", "https://", $url);
215 }
216 return $url;
217 }
218
219 /**
220 * @return bool
221 */
222 public static function isMatomoInstalled(): bool
223 {
224 $config = Config::getInstance()->getLocalPath();
225 $exists = file_exists($config);
226
227 // Piwik is not installed if the config file is not found
228 if (!$exists) {
229 return false;
230 }
231
232 $general = Config::getInstance()->General;
233
234 $isInstallationInProgress = false;
235 if (array_key_exists('installation_in_progress', $general)) {
236 $isInstallationInProgress = (bool) $general['installation_in_progress'];
237 }
238 if ($isInstallationInProgress) {
239 return false;
240 }
241
242 // Check that the database section is really set, ie. file is not empty
243 if (empty(Config::getInstance()->database['username'])) {
244 return false;
245 }
246 return true;
247 }
248
249 /**
250 * Check if outgoing internet connections are enabled
251 * This is often disable in an intranet environment
252 *
253 * @return bool
254 */
255 public static function isInternetEnabled(): bool
256 {
257 return (bool) Config::getInstance()->General['enable_internet_features'];
258 }
259
260 /**
261 * Detect whether user has enabled auto updates. Please note this config is a bit misleading. It is currently
262 * actually used for 2 things: To disable making any connections back to Piwik, and to actually disable the auto
263 * update of core and plugins.
264 * @return bool
265 */
266 public static function isAutoUpdateEnabled(): bool
267 {
268 $enableAutoUpdate = (bool) Config::getInstance()->General['enable_auto_update'];
269 if(self::isInternetEnabled() === true && $enableAutoUpdate === true){
270 return true;
271 }
272
273 return false;
274 }
275
276 /**
277 * Detects whether an auto update can be made. An update is possible if the user is not on multiple servers and if
278 * automatic updates are actually enabled. If a user is running Piwik on multiple servers an update is not possible
279 * as it would be installed only on one server instead of all of them. Also if a user has disabled automatic updates
280 * we cannot perform any automatic updates.
281 *
282 * @return bool
283 */
284 public static function isAutoUpdatePossible(): bool
285 {
286 return !self::isMultiServerEnvironment() && self::isAutoUpdateEnabled();
287 }
288
289 /**
290 * Returns `true` if Piwik is running on more than one server. For example in a load balanced environment. In this
291 * case we should not make changes to the config and not install a plugin via the UI as it would be only executed
292 * on one server.
293 * @return bool
294 */
295 public static function isMultiServerEnvironment(): bool
296 {
297 $is = Config::getInstance()->General['multi_server_environment'];
298
299 return !empty($is);
300 }
301
302 /**
303 * Returns `true` if segmentation is allowed for this user, `false` if otherwise.
304 *
305 * @return bool
306 * @api
307 */
308 public static function isSegmentationEnabled(): bool
309 {
310 return !Piwik::isUserIsAnonymous()
311 || Config::getInstance()->General['anonymous_user_enable_use_segments_API'];
312 }
313
314 /**
315 * Returns true if unique visitors should be processed for the given period type.
316 *
317 * Unique visitor processing is controlled by the `[General] enable_processing_unique_visitors_...`
318 * INI config options. By default, unique visitors are processed only for day/week/month periods.
319 *
320 * @param string $periodLabel `"day"`, `"week"`, `"month"`, `"year"` or `"range"`
321 * @return bool
322 * @api
323 */
324 public static function isUniqueVisitorsEnabled(string $periodLabel): bool
325 {
326 $generalSettings = Config::getInstance()->General;
327
328 $settingName = "enable_processing_unique_visitors_$periodLabel";
329 $result = !empty($generalSettings[$settingName]) && $generalSettings[$settingName] == 1;
330
331 // check enable_processing_unique_visitors_year_and_range for backwards compatibility
332 if (($periodLabel === 'year' || $periodLabel === 'range')
333 && isset($generalSettings['enable_processing_unique_visitors_year_and_range'])
334 ) {
335 $result |= $generalSettings['enable_processing_unique_visitors_year_and_range'] == 1;
336 }
337
338 return $result;
339 }
340
341 /**
342 * If Piwik uses per-domain config file, make sure CustomLogo is unique
343 * @param string $path
344 * @return string
345 * @throws \DI\DependencyException
346 * @throws \DI\NotFoundException
347 * @throws Exception
348 */
349 public static function rewriteMiscUserPathWithInstanceId(string $path): string
350 {
351 $tmp = StaticContainer::get('path.misc.user');
352 $path = self::rewritePathAppendPiwikInstanceId($path, $tmp);
353 return $path;
354 }
355
356 /**
357 * Returns true if the Piwik server appears to be working.
358 *
359 * If the Piwik server is in an error state (eg. some directories are not writable and Piwik displays error message),
360 * or if the Piwik server is "offline",
361 * this will return false..
362 *
363 * @param string $piwikServerUrl
364 * @param bool $acceptInvalidSSLCertificates
365 * @return void
366 * @throws Exception
367 */
368 public static function checkPiwikServerWorking(string $piwikServerUrl, bool $acceptInvalidSSLCertificates = false): void
369 {
370 // Now testing if the webserver is running
371 try {
372 $fetched = Http::sendHttpRequestBy('curl',
373 $piwikServerUrl,
374 $timeout = 45,
375 $userAgent = null,
376 $destinationPath = null,
377 $file = null,
378 $followDepth = 0,
379 $acceptLanguage = false,
380 $acceptInvalidSSLCertificates
381 );
382 } catch (Exception $e) {
383 $fetched = "ERROR fetching: " . $e->getMessage();
384 }
385 // this will match when Piwik not installed yet, or favicon not customised
386 $expectedStringAlt = 'plugins/CoreHome/images/favicon.png';
387
388 // this will match when Piwik is installed and favicon has been customised
389 $expectedString = 'misc/user/';
390
391 // see checkPiwikIsNotInstalled()
392 $expectedStringAlreadyInstalled = 'piwik-is-already-installed';
393
394 $expectedStringNotFound = strpos($fetched, $expectedString) === false
395 && strpos($fetched, $expectedStringAlt) === false
396 && strpos($fetched, $expectedStringAlreadyInstalled) === false;
397
398 $hasError = false !== strpos($fetched, PAGE_TITLE_WHEN_ERROR);
399
400 if ($hasError || $expectedStringNotFound) {
401 throw new Exception("\nMatomo should be running at: "
402 . $piwikServerUrl
403 . " but this URL returned an unexpected response: '"
404 . $fetched . "'\n\n");
405 }
406 }
407
408 /**
409 * Returns true if Piwik is deployed using git
410 * FAQ: http://piwik.org/faq/how-to-install/faq_18271/
411 *
412 * @return bool
413 */
414 public static function isGitDeployment(): bool
415 {
416 return file_exists(PIWIK_INCLUDE_PATH . '/.git/HEAD');
417 }
418
419 /**
420 * @return string
421 */
422 public static function getCurrentGitBranch(): string
423 {
424 $file = PIWIK_INCLUDE_PATH . '/.git/HEAD';
425 if (!file_exists($file)) {
426 return '';
427 }
428 $firstLineOfGitHead = file($file);
429 if (empty($firstLineOfGitHead)) {
430 return '';
431 }
432 $firstLineOfGitHead = $firstLineOfGitHead[0];
433 $parts = explode('/', $firstLineOfGitHead);
434 if (empty($parts[2])) {
435 return '';
436 }
437 $currentGitBranch = trim($parts[2]);
438 return $currentGitBranch;
439 }
440
441 /**
442 * @param string $pathToRewrite
443 * @param string $leadingPathToAppendHostnameTo
444 * @return string
445 * @throws Exception
446 */
447 protected static function rewritePathAppendPiwikInstanceId(string $pathToRewrite, string $leadingPathToAppendHostnameTo): string
448 {
449 $instanceId = self::getPiwikInstanceId();
450 if (empty($instanceId)) {
451 return $pathToRewrite;
452 }
453
454 if (($posTmp = strrpos($pathToRewrite, $leadingPathToAppendHostnameTo)) === false) {
455 throw new Exception("The path $pathToRewrite was expected to contain the string $leadingPathToAppendHostnameTo");
456 }
457
458 $tmpToReplace = $leadingPathToAppendHostnameTo . $instanceId . '/';
459
460 // replace only the latest occurrence (in case path contains twice /tmp)
461 $pathToRewrite = substr_replace($pathToRewrite, $tmpToReplace, $posTmp, strlen($leadingPathToAppendHostnameTo));
462 return $pathToRewrite;
463 }
464
465 /**
466 * @throws Exception
467 * @return string|false return string or false if not set
468 */
469 public static function getPiwikInstanceId()
470 {
471 // until Matomo is installed, we use hostname as instance_id
472 if (!self::isMatomoInstalled() && Common::isPhpCliMode()) {
473 // enterprise:install use case
474 return Config::getHostname();
475 }
476
477 // config.ini.php not ready yet, instance_id will not be set
478 if (!Config::getInstance()->existsLocalConfig()) {
479 return false;
480 }
481
482 $instanceId = GeneralConfig::getConfigValue('instance_id');
483 if (!empty($instanceId)) {
484 return $instanceId;
485 }
486
487 // do not rewrite the path as Matomo uses the standard config.ini.php file
488 return false;
489 }
490
491 /**
492 * @param string $currentUrl
493 */
494 public static function overwritePiwikUrl(string $currentUrl): void
495 {
496 Option::set(self::OPTION_PIWIK_URL, $currentUrl, $autoLoad = true);
497 }
498
499 /**
500 * @return bool
501 */
502 public static function isHttpsForced(): bool
503 {
504 if (!self::isMatomoInstalled()) {
505 // Only enable this feature after Piwik is already installed
506 return false;
507 }
508 return Config::getInstance()->General['force_ssl'] == 1;
509 }
510
511 /**
512 * Note: this config settig is also checked in the InterSites plugin
513 *
514 * @return bool
515 */
516 public static function isSameFingerprintAcrossWebsites(): bool
517 {
518 return (bool)Config::getInstance()->Tracker['enable_fingerprinting_across_websites'];
519 }
520 }
521