PluginProbe ʕ •ᴥ•ʔ
Matomo Analytics – Powerful, Privacy-First Insights for WordPress / 5.0.3
Matomo Analytics – Powerful, Privacy-First Insights for WordPress v5.0.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 / app / core / Config.php
matomo / app / core Last commit date
API 2 years ago Access 2 years ago Application 2 years ago Archive 2 years ago ArchiveProcessor 2 years ago Archiver 2 years ago AssetManager 2 years ago Auth 2 years ago Category 2 years ago Changes 2 years ago CliMulti 2 years ago Columns 2 years ago Concurrency 2 years ago Config 2 years ago Container 2 years ago CronArchive 2 years ago DataAccess 2 years ago DataFiles 2 years ago DataTable 2 years ago Db 2 years ago DeviceDetector 2 years ago Email 2 years ago Exception 2 years ago Http 2 years ago Intl 2 years ago Log 2 years ago Mail 2 years ago Measurable 2 years ago Menu 2 years ago Metrics 2 years ago Notification 2 years ago Period 2 years ago Plugin 2 years ago ProfessionalServices 2 years ago Report 2 years ago ReportRenderer 2 years ago Scheduler 2 years ago Segment 2 years ago Session 2 years ago Settings 2 years ago Tracker 2 years ago Translation 2 years ago Twig 2 years ago UpdateCheck 2 years ago Updater 2 years ago Updates 2 years ago Validators 2 years ago View 2 years ago ViewDataTable 2 years ago Visualization 2 years ago Widget 2 years ago .htaccess 2 years ago Access.php 2 years ago Archive.php 2 years ago ArchiveProcessor.php 2 years ago AssetManager.php 2 years ago Auth.php 2 years ago AuthResult.php 2 years ago BaseFactory.php 2 years ago Cache.php 2 years ago CacheId.php 2 years ago CliMulti.php 2 years ago Common.php 2 years ago Config.php 2 years ago Console.php 2 years ago Context.php 2 years ago Cookie.php 2 years ago CronArchive.php 2 years ago DI.php 2 years ago DataArray.php 2 years ago DataTable.php 2 years ago Date.php 2 years ago Db.php 2 years ago DbHelper.php 2 years ago Development.php 2 years ago ErrorHandler.php 2 years ago EventDispatcher.php 2 years ago ExceptionHandler.php 2 years ago FileIntegrity.php 2 years ago Filechecks.php 2 years ago Filesystem.php 2 years ago FrontController.php 2 years ago Http.php 2 years ago IP.php 2 years ago Log.php 2 years ago LogDeleter.php 2 years ago Mail.php 2 years ago Metrics.php 2 years ago NoAccessException.php 2 years ago Nonce.php 2 years ago Notification.php 2 years ago NumberFormatter.php 2 years ago Option.php 2 years ago Period.php 2 years ago Piwik.php 2 years ago Plugin.php 2 years ago Profiler.php 2 years ago ProxyHeaders.php 2 years ago ProxyHttp.php 2 years ago QuickForm2.php 2 years ago RankingQuery.php 2 years ago ReportRenderer.php 2 years ago Request.php 2 years ago Segment.php 2 years ago Sequence.php 2 years ago Session.php 2 years ago SettingsPiwik.php 2 years ago SettingsServer.php 2 years ago Singleton.php 2 years ago Site.php 2 years ago SiteContentDetector.php 2 years ago SupportedBrowser.php 2 years ago TCPDF.php 2 years ago Theme.php 2 years ago Timer.php 2 years ago Tracker.php 2 years ago Twig.php 2 years ago Unzip.php 2 years ago UpdateCheck.php 2 years ago Updater.php 2 years ago UpdaterErrorException.php 2 years ago Updates.php 2 years ago Url.php 2 years ago UrlHelper.php 2 years ago Version.php 2 years ago View.php 2 years ago bootstrap.php 2 years ago dispatch.php 2 years ago testMinimumPhpVersion.php 2 years ago
Config.php
422 lines
1 <?php
2
3 /**
4 * Matomo - free/libre analytics platform
5 *
6 * @link https://matomo.org
7 * @license http://www.gnu.org/licenses/gpl-3.0.html GPL v3 or later
8 *
9 */
10 namespace Piwik;
11
12 use Exception;
13 use Piwik\Application\Kernel\GlobalSettingsProvider;
14 use Piwik\Container\StaticContainer;
15 use Piwik\Exception\MissingFilePermissionException;
16 use Piwik\Plugins\CoreAdminHome\Controller;
17 use Piwik\Plugins\CorePluginsAdmin\CorePluginsAdmin;
18 use Piwik\ProfessionalServices\Advertising;
19 use Piwik\Log\LoggerInterface;
20 /**
21 * Singleton that provides read & write access to Piwik's INI configuration.
22 *
23 * This class reads and writes to the `config/config.ini.php` file. If config
24 * options are missing from that file, this class will look for their default
25 * values in `config/global.ini.php`.
26 *
27 * ### Examples
28 *
29 * **Getting a value:**
30 *
31 * // read the minimum_memory_limit option under the [General] section
32 * $minValue = Config::getInstance()->General['minimum_memory_limit'];
33 *
34 * **Setting a value:**
35 *
36 * // set the minimum_memory_limit option
37 * Config::getInstance()->General['minimum_memory_limit'] = 256;
38 * Config::getInstance()->forceSave();
39 *
40 * **Setting an entire section:**
41 *
42 * Config::getInstance()->MySection = array('myoption' => 1);
43 * Config::getInstance()->forceSave();
44 */
45 class Config
46 {
47 const DEFAULT_LOCAL_CONFIG_PATH = '/config/config.ini.php';
48 const DEFAULT_COMMON_CONFIG_PATH = '/config/common.config.ini.php';
49 const DEFAULT_GLOBAL_CONFIG_PATH = '/config/global.ini.php';
50 /**
51 * @var boolean
52 */
53 protected $doNotWriteConfigInTests = false;
54 /**
55 * @var GlobalSettingsProvider
56 */
57 protected $settings;
58 /**
59 * @return Config
60 */
61 public static function getInstance()
62 {
63 return StaticContainer::get('Piwik\\Config');
64 }
65 public function __construct(GlobalSettingsProvider $settings)
66 {
67 $this->settings = $settings;
68 }
69 /**
70 * Returns the path to the local config file used by this instance.
71 *
72 * @return string
73 */
74 public function getLocalPath()
75 {
76 return $this->settings->getPathLocal();
77 }
78 /**
79 * Returns the path to the global config file used by this instance.
80 *
81 * @return string
82 */
83 public function getGlobalPath()
84 {
85 return $this->settings->getPathGlobal();
86 }
87 /**
88 * Returns the path to the common config file used by this instance.
89 *
90 * @return string
91 */
92 public function getCommonPath()
93 {
94 return $this->settings->getPathCommon();
95 }
96 /**
97 * Returns absolute path to the global configuration file
98 *
99 * @return string
100 */
101 public static function getGlobalConfigPath()
102 {
103 return PIWIK_DOCUMENT_ROOT . self::DEFAULT_GLOBAL_CONFIG_PATH;
104 }
105 /**
106 * Returns absolute path to the common configuration file.
107 *
108 * @return string
109 */
110 public static function getCommonConfigPath()
111 {
112 return PIWIK_USER_PATH . self::DEFAULT_COMMON_CONFIG_PATH;
113 }
114 /**
115 * Returns default absolute path to the local configuration file.
116 *
117 * @return string
118 */
119 public static function getDefaultLocalConfigPath()
120 {
121 return PIWIK_USER_PATH . self::DEFAULT_LOCAL_CONFIG_PATH;
122 }
123 /**
124 * Returns absolute path to the local configuration file
125 *
126 * @return string
127 */
128 public static function getLocalConfigPath()
129 {
130 if (!empty($GLOBALS['CONFIG_INI_PATH_RESOLVER']) && is_callable($GLOBALS['CONFIG_INI_PATH_RESOLVER'])) {
131 return call_user_func($GLOBALS['CONFIG_INI_PATH_RESOLVER']);
132 }
133 $path = self::getByDomainConfigPath();
134 if ($path) {
135 return $path;
136 }
137 return self::getDefaultLocalConfigPath();
138 }
139 private static function getLocalConfigInfoForHostname($hostname)
140 {
141 if (!$hostname) {
142 return array();
143 }
144 // Remove any port number to get actual hostname
145 $hostname = \Piwik\Url::getHostSanitized($hostname);
146 $standardConfigName = 'config.ini.php';
147 $perHostFilename = $hostname . '.' . $standardConfigName;
148 $pathDomainConfig = PIWIK_USER_PATH . '/config/' . $perHostFilename;
149 $pathDomainMiscUser = PIWIK_USER_PATH . '/misc/user/' . $hostname . '/' . $standardConfigName;
150 $locations = array(array('file' => $perHostFilename, 'path' => $pathDomainConfig), array('file' => $standardConfigName, 'path' => $pathDomainMiscUser));
151 return $locations;
152 }
153 public function getConfigHostnameIfSet()
154 {
155 if ($this->getByDomainConfigPath() === false) {
156 return false;
157 }
158 return $this->getHostname();
159 }
160 public function getClientSideOptions()
161 {
162 $general = $this->General;
163 return array('action_url_category_delimiter' => $general['action_url_category_delimiter'], 'action_title_category_delimiter' => $general['action_title_category_delimiter'], 'are_ads_enabled' => Advertising::isAdsEnabledInConfig($general), 'autocomplete_min_sites' => $general['autocomplete_min_sites'], 'datatable_export_range_as_day' => $general['datatable_export_range_as_day'], 'datatable_row_limits' => $this->getDatatableRowLimits(), 'enable_general_settings_admin' => Controller::isGeneralSettingsAdminEnabled(), 'enable_plugins_admin' => CorePluginsAdmin::isPluginsAdminEnabled());
164 }
165 /**
166 * @param $general
167 * @return mixed
168 */
169 private function getDatatableRowLimits()
170 {
171 $limits = $this->General['datatable_row_limits'];
172 $limits = explode(",", $limits);
173 $limits = array_map('trim', $limits);
174 return $limits;
175 }
176 public static function getByDomainConfigPath()
177 {
178 $host = self::getHostname();
179 $hostConfigs = self::getLocalConfigInfoForHostname($host);
180 foreach ($hostConfigs as $hostConfig) {
181 if (\Piwik\Filesystem::isValidFilename($hostConfig['file']) && file_exists($hostConfig['path'])) {
182 return $hostConfig['path'];
183 }
184 }
185 return false;
186 }
187 /**
188 * Returns the hostname of the current request (without port number)
189 * @param bool $checkIfTrusted Check trusted requires config which is maybe not ready yet,
190 * make sure the config is ready when you call with true
191 *
192 * @return string
193 */
194 public static function getHostname($checkIfTrusted = false)
195 {
196 $host = \Piwik\Url::getHost($checkIfTrusted);
197 // Remove any port number to get actual hostname
198 $host = \Piwik\Url::getHostSanitized($host);
199 return $host;
200 }
201 /**
202 * If set, Piwik will use the hostname config no matter if it exists or not. Useful for instance if you want to
203 * create a new hostname config:
204 *
205 * $config = Config::getInstance();
206 * $config->forceUsageOfHostnameConfig('piwik.example.com');
207 * $config->save();
208 *
209 * @param string $hostname eg piwik.example.com
210 * @param string $preferredPath If there are different paths for the config that can be used, eg /config/* and /misc/user/*,
211 * and a preferred path is given, then the config path must contain the preferred path.
212 * @return string
213 * @throws \Exception In case the domain contains not allowed characters
214 * @internal
215 */
216 public function forceUsageOfLocalHostnameConfig($hostname, $preferredPath = null)
217 {
218 $hostConfigs = self::getLocalConfigInfoForHostname($hostname);
219 $fileNames = '';
220 foreach ($hostConfigs as $hostConfig) {
221 if (count($hostConfigs) > 1 && $preferredPath && strpos($hostConfig['path'], $preferredPath) === false) {
222 continue;
223 }
224 $filename = $hostConfig['file'];
225 $fileNames .= $filename . ' ';
226 if (\Piwik\Filesystem::isValidFilename($filename)) {
227 $pathLocal = $hostConfig['path'];
228 try {
229 $this->reload($pathLocal);
230 } catch (Exception $ex) {
231 // pass (not required for local file to exist at this point)
232 }
233 return $pathLocal;
234 }
235 }
236 throw new Exception('Matomo domain is not a valid looking hostname (' . trim($fileNames) . ').');
237 }
238 /**
239 * Returns `true` if the local configuration file is writable.
240 *
241 * @return bool
242 */
243 public function isFileWritable()
244 {
245 return is_writable($this->settings->getPathLocal());
246 }
247 /**
248 * Reloads config data from disk.
249 *
250 * @throws \Exception if the global config file is not found and this is a tracker request, or
251 * if the local config file is not found and this is NOT a tracker request.
252 */
253 protected function reload($pathLocal = null, $pathGlobal = null, $pathCommon = null)
254 {
255 $this->settings->reload($pathGlobal, $pathLocal, $pathCommon);
256 }
257 public function existsLocalConfig()
258 {
259 return is_readable($this->getLocalPath());
260 }
261 public function deleteLocalConfig()
262 {
263 $configLocal = $this->getLocalPath();
264 if (file_exists($configLocal)) {
265 @unlink($configLocal);
266 }
267 }
268 /**
269 * Returns a configuration value or section by name.
270 *
271 * @param string $name The value or section name.
272 * @return string|array The requested value requested. Returned by reference.
273 * @throws Exception If the value requested not found in either `config.ini.php` or
274 * `global.ini.php`.
275 * @api
276 */
277 public function &__get($name)
278 {
279 $section =& $this->settings->getIniFileChain()->get($name);
280 return $section;
281 }
282 /**
283 * @api
284 */
285 public function getFromGlobalConfig($name)
286 {
287 return $this->settings->getIniFileChain()->getFrom($this->getGlobalPath(), $name);
288 }
289 /**
290 * @api
291 */
292 public function getFromCommonConfig($name)
293 {
294 return $this->settings->getIniFileChain()->getFrom($this->getCommonPath(), $name);
295 }
296 /**
297 * @api
298 */
299 public function getFromLocalConfig($name)
300 {
301 return $this->settings->getIniFileChain()->getFrom($this->getLocalPath(), $name);
302 }
303 /**
304 * Sets a configuration value or section.
305 *
306 * @param string $name This section name or value name to set.
307 * @param mixed $value
308 * @api
309 */
310 public function __set($name, $value)
311 {
312 $this->settings->getIniFileChain()->set($name, $value);
313 }
314 /**
315 * Dump config
316 *
317 * @return string|null
318 * @throws \Exception
319 */
320 public function dumpConfig()
321 {
322 $chain = $this->settings->getIniFileChain();
323 $header = "; <?php exit; ?> DO NOT REMOVE THIS LINE\n";
324 $header .= "; file automatically generated or modified by Matomo; you can manually override the default values in global.ini.php by redefining them in this file.\n";
325 return $chain->dumpChanges($header);
326 }
327 /**
328 * Write user configuration file
329 *
330 * @throws \Exception if config file not writable
331 */
332 protected function writeConfig()
333 {
334 $output = $this->dumpConfig();
335 if ($output !== null && $output !== false) {
336 $localPath = $this->getLocalPath();
337 if ($this->doNotWriteConfigInTests) {
338 // simulate whether it would be successful
339 $success = is_writable($localPath);
340 } else {
341 $success = @file_put_contents($localPath, $output, LOCK_EX);
342 }
343 if ($success === false) {
344 throw $this->getConfigNotWritableException();
345 }
346 if (!$this->sanityCheck($localPath, $output)) {
347 // If sanity check fails, try to write the contents once more before logging the issue.
348 if (@file_put_contents($localPath, $output, LOCK_EX) === false || !$this->sanityCheck($localPath, $output, true)) {
349 StaticContainer::get(LoggerInterface::class)->info("The configuration file {$localPath} did not write correctly.");
350 }
351 }
352 $this->settings->getIniFileChain()->deleteConfigCache();
353 /**
354 * Triggered when a INI config file is changed on disk.
355 *
356 * @param string $localPath Absolute path to the changed file on the server.
357 */
358 \Piwik\Piwik::postEvent('Core.configFileChanged', [$localPath]);
359 }
360 }
361 /**
362 * Writes the current configuration to the **config.ini.php** file. Only writes options whose
363 * values are different from the default.
364 *
365 * @api
366 */
367 public function forceSave()
368 {
369 $this->writeConfig();
370 }
371 /**
372 * @throws \Exception
373 */
374 public function getConfigNotWritableException()
375 {
376 $path = "config/" . basename($this->getLocalPath());
377 return new MissingFilePermissionException(\Piwik\Piwik::translate('General_ConfigFileIsNotWritable', array("(" . $path . ")", "")));
378 }
379 /**
380 * Convenience method for setting settings in a single section. Will set them in a new array first
381 * to be compatible with certain PHP versions.
382 *
383 * @param string $sectionName Section name.
384 * @param string $name The setting name.
385 * @param mixed $value The setting value to set.
386 */
387 public static function setSetting($sectionName, $name, $value)
388 {
389 $section = self::getInstance()->{$sectionName};
390 $section[$name] = $value;
391 self::getInstance()->{$sectionName} = $section;
392 }
393 /**
394 * Sanity check a config file by checking contents
395 *
396 * @param string $localPath
397 * @param string $expectedContent
398 * @param bool $notify
399 * @return bool
400 */
401 public function sanityCheck(string $localPath, string $expectedContent, bool $notify = false) : bool
402 {
403 clearstatcache(true, $localPath);
404 if (function_exists('opcache_invalidate')) {
405 @opcache_invalidate($localPath, $force = true);
406 }
407 $content = @file_get_contents($localPath);
408 if (trim($content) !== trim($expectedContent)) {
409 if ($notify) {
410 /**
411 * Triggered when the INI config file was not written correctly with the expected content.
412 *
413 * @param string $localPath Absolute path to the changed file on the server.
414 */
415 \Piwik\Piwik::postEvent('Core.configFileSanityCheckFailed', [$localPath]);
416 }
417 return false;
418 }
419 return true;
420 }
421 }
422