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