Tracker['record_statistics']; if ($statsEnabled == "0") { $notification = new Notification(Piwik::translate('General_StatisticsAreNotRecorded')); $notification->context = Notification::CONTEXT_INFO; Notification\Manager::notify('ControllerAdmin_StatsAreNotRecorded', $notification); } } private static function notifyAnyInvalidLicense() { if (!Marketplace::isMarketplaceEnabled()) { return; } if (Piwik::isUserIsAnonymous()) { return; } if (!Piwik::isUserHasSomeAdminAccess()) { return; } if (Development::isEnabled()) { return; } $expired = StaticContainer::get('Piwik\Plugins\Marketplace\Plugins\InvalidLicenses'); $messageLicenseMissing = $expired->getMessageNoLicense(); if (!empty($messageLicenseMissing)) { $notification = new Notification($messageLicenseMissing); $notification->raw = true; $notification->context = Notification::CONTEXT_ERROR; $notification->title = Piwik::translate('Marketplace_LicenseMissing'); Notification\Manager::notify('ControllerAdmin_LicenseMissingWarning', $notification); } $messageExceeded = $expired->getMessageExceededLicenses(); if (!empty($messageExceeded)) { $notification = new Notification($messageExceeded); $notification->raw = true; $notification->context = Notification::CONTEXT_WARNING; $notification->title = Piwik::translate('Marketplace_LicenseExceeded'); Notification\Manager::notify('ControllerAdmin_LicenseExceededWarning', $notification); } $messageExpired = $expired->getMessageExpiredLicenses(); if (!empty($messageExpired)) { $notification = new Notification($messageExpired); $notification->raw = true; $notification->context = Notification::CONTEXT_WARNING; $notification->title = Piwik::translate('Marketplace_LicenseExpired'); Notification\Manager::notify('ControllerAdmin_LicenseExpiredWarning', $notification); } } private static function notifyAnyInvalidPlugin() { if (!Piwik::hasUserSuperUserAccess()) { return; } $missingPlugins = \Piwik\Plugin\Manager::getInstance()->getMissingPlugins(); if (empty($missingPlugins)) { return; } $invalidPluginsWarning = Piwik::translate('CoreAdminHome_InvalidPluginsWarning', [ self::getPiwikVersion(), '' . implode('', $missingPlugins) . '', ]); if (CorePluginsAdmin::isPluginsAdminEnabled()) { $pluginsLink = Url::getCurrentQueryStringWithParametersModified([ 'module' => 'CorePluginsAdmin', 'action' => 'plugins', ]); $invalidPluginsWarning .= '
' . Piwik::translate('CoreAdminHome_InvalidPluginsYouCanUninstall', [ '', '', ]); } else { $invalidPluginsWarning .= '
' . Piwik::translate('CoreAdminHome_InvalidPluginsAdminDisabled'); } $notification = new Notification($invalidPluginsWarning); $notification->raw = true; $notification->context = Notification::CONTEXT_WARNING; $notification->title = Piwik::translate('General_Warning'); Notification\Manager::notify('ControllerAdmin_InvalidPluginsWarning', $notification); } /** * Calls {@link setBasicVariablesNoneAdminView()} and {@link setBasicVariablesAdminView()} * using the supplied view. * * @param View $view * @param string $viewType If 'admin', the admin variables are set as well as basic ones. */ protected function setBasicVariablesViewAs($view, $viewType = 'admin') { $this->setBasicVariablesNoneAdminView($view); if ($viewType === 'admin') { self::setBasicVariablesAdminView($view); } } private static function notifyIfURLIsNotSecure() { $isURLSecure = ProxyHttp::isHttps(); if ($isURLSecure) { return; } if (!Piwik::hasUserSuperUserAccess()) { return; } if (Url::isLocalHost(Url::getCurrentHost())) { return; } if (Development::isEnabled()) { return; } $message = Piwik::translate('General_CurrentlyUsingUnsecureHttp'); $message .= " "; $message .= Piwik::translate( 'General_ReadThisToLearnMore', [Url::getExternalLinkTag('https://matomo.org/faq/how-to/faq_91/'), ''] ); $notification = new Notification($message); $notification->context = Notification::CONTEXT_WARNING; $notification->raw = true; Notification\Manager::notify('ControllerAdmin_HttpIsUsed', $notification); } private static function notifyIfDevelopmentModeOnButNotInstalledThroughGit() { if (!Piwik::hasUserSuperUserAccess()) { return; } if (!Development::isEnabled()) { return; } if (SettingsPiwik::isGitDeployment()) { return; } $message = Piwik::translate('General_WarningDevelopmentModeOnButNotGitInstalled'); $notification = new Notification($message); $notification->context = Notification::CONTEXT_WARNING; $notification->raw = true; $notification->flags = Notification::FLAG_CLEAR; Notification\Manager::notify('ControllerAdmin_DevelopmentModeOn', $notification); } /** * @ignore */ public static function displayWarningIfConfigFileNotWritable() { try { PiwikConfig::getInstance()->checkConfigIsWritable(); } catch (MissingFilePermissionException $exception) { $notification = new Notification($exception->getMessage()); $notification->raw = true; $notification->context = Notification::CONTEXT_WARNING; Notification\Manager::notify('ControllerAdmin_ConfigNotWriteable', $notification); } } private static function notifyIfEAcceleratorIsUsed() { $isEacceleratorUsed = ini_get('eaccelerator.enable'); if (empty($isEacceleratorUsed)) { return; } $message = sprintf( "You are using the PHP accelerator & optimizer eAccelerator which is known to be not compatible with Matomo. We have disabled eAccelerator, which might affect the performance of Matomo. Read the %srelated ticket%s for more information and how to fix this problem.", '', '' ); $notification = new Notification($message); $notification->context = Notification::CONTEXT_WARNING; $notification->raw = true; Notification\Manager::notify('ControllerAdmin_EacceleratorIsUsed', $notification); } /** * PHP Version required by the next major Matomo version * @return string */ private static function getNextRequiredMinimumPHP() { return self::NEXT_REQUIRED_MINIMUM_PHP; } private static function isUsingPhpVersionCompatibleWithNextPiwik($phpVersion = PHP_VERSION) { return version_compare($phpVersion, self::getNextRequiredMinimumPHP(), '>='); } private static function notifyWhenPhpVersionIsNotCompatibleWithNextMajorPiwik() { if (defined('PIWIK_TEST_MODE')) { // to avoid changing every admin UI test return; } if (!Piwik::hasUserSuperUserAccess()) { return; } if (self::isUsingPhpVersionCompatibleWithNextPiwik()) { return; } $youMustUpgradePHP = Piwik::translate('General_YouMustUpgradePhpVersionToReceiveNextMajorMatomo'); $message = Piwik::translate('General_MatomoCannotBeUpgradedToNextMajorBecausePhpIsTooOld') . ' ' . sprintf(Piwik::translate('General_PleaseUpgradeYourPhpVersionForNextMajorMatomo'), self::getNextRequiredMinimumPHP()) ; $notification = new Notification($message); $notification->title = $youMustUpgradePHP; $notification->priority = Notification::PRIORITY_LOW; $notification->context = Notification::CONTEXT_WARNING; $notification->type = Notification::TYPE_TRANSIENT; $notification->flags = Notification::FLAG_NO_CLEAR; NotificationManager::notify('PHPVersionTooOldForNewestPiwikCheck', $notification); } private static function getNextRequiredMinimumDatabaseVersion(string $databaseType, string $databaseVersion): ?string { $databaseType = self::getEffectiveDatabaseType($databaseType, $databaseVersion); if ($databaseType === 'mysql') { return self::NEXT_REQUIRED_MINIMUM_MYSQL; } if ($databaseType === 'mariadb') { return self::NEXT_REQUIRED_MINIMUM_MARIADB; } return null; } private static function isUsingDatabaseVersionCompatibleWithNextPiwik(string $databaseType, string $databaseVersion): bool { $requiredVersion = self::getNextRequiredMinimumDatabaseVersion($databaseType, $databaseVersion); if ($requiredVersion === null) { return true; } return version_compare(self::getComparableDatabaseVersion($databaseVersion), $requiredVersion, '>='); } private static function getEffectiveDatabaseType(string $databaseType, string $databaseVersion): string { if (stripos($databaseVersion, 'mariadb') !== false) { return 'mariadb'; } return strtolower($databaseType); } private static function getComparableDatabaseVersion(string $databaseVersion): string { if ( stripos($databaseVersion, 'mariadb') !== false && preg_match('/5\.5\.5-(\d+(?:\.\d+){0,2})-MariaDB/i', $databaseVersion, $matches) ) { return $matches[1]; } if (preg_match('/\d+(?:\.\d+){0,2}/', $databaseVersion, $matches)) { return $matches[0]; } return $databaseVersion; } private static function notifyWhenDatabaseVersionIsNotCompatibleWithNextMajorPiwik(): void { if (defined('PIWIK_TEST_MODE')) { // to avoid changing every admin UI test return; } if (!Piwik::hasUserSuperUserAccess()) { return; } $databaseType = Schema::getInstance()->getDatabaseType(); $databaseVersion = Schema::getInstance()->getVersion(); if (self::isUsingDatabaseVersionCompatibleWithNextPiwik($databaseType, $databaseVersion)) { return; } $requiredVersion = self::getNextRequiredMinimumDatabaseVersion($databaseType, $databaseVersion); $databaseType = self::getEffectiveDatabaseType($databaseType, $databaseVersion) === 'mariadb' ? 'MariaDB' : 'MySQL'; $message = Piwik::translate('General_MatomoCannotBeUpgradedToNextMajorBecauseDatabaseIsTooOld') . ' ' . Piwik::translate( 'General_PleaseUpgradeYourDatabaseVersionForNextMajorMatomo', [$databaseType, $requiredVersion] ); $notification = new Notification($message); $notification->title = Piwik::translate('General_YouMustUpgradeDatabaseVersionToReceiveNextMajorMatomo'); $notification->priority = Notification::PRIORITY_LOW; $notification->context = Notification::CONTEXT_WARNING; $notification->type = Notification::TYPE_TRANSIENT; $notification->flags = Notification::FLAG_NO_CLEAR; NotificationManager::notify('DatabaseVersionTooOldForNewestPiwikCheck', $notification); } private static function notifyWhenPhpVersionIsEOL() { if (defined('PIWIK_TEST_MODE')) { // to avoid changing every admin UI test return; } $notifyPhpIsEOL = Piwik::hasUserSuperUserAccess() && self::isPhpVersionEOL(); if (!$notifyPhpIsEOL) { return; } $deprecatedMajorPhpVersion = PHP_MAJOR_VERSION . '.' . PHP_MINOR_VERSION; $message = ''; if (version_compare(PHP_VERSION, self::getNextRequiredMinimumPHP(), '<')) { $message = Piwik::translate( 'General_WarningPiwikWillStopSupportingPHPVersion', [$deprecatedMajorPhpVersion, self::getNextRequiredMinimumPHP()] ) . '
'; } $message .= Piwik::translate('General_WarningPhpVersionXIsTooOld', $deprecatedMajorPhpVersion); $notification = new Notification($message); $notification->raw = true; $notification->title = Piwik::translate('General_Warning'); $notification->priority = Notification::PRIORITY_LOW; $notification->context = Notification::CONTEXT_WARNING; $notification->type = Notification::TYPE_TRANSIENT; $notification->flags = Notification::FLAG_NO_CLEAR; NotificationManager::notify('PHPVersionCheck', $notification); } private static function notifyWhenDatabaseVersionIsEOL(): void { if (defined('PIWIK_TEST_MODE')) { // to avoid changing every admin UI test return; } $isEOL = Piwik::hasUserSuperUserAccess() && Schema::getInstance()->hasReachedEOL(); if (!$isEOL) { return; } $databaseVersion = Schema::getInstance()->getVersion(); $message = Piwik::translate('General_WarningDatabaseVersionXIsTooOld', [Schema::getInstance()->getDatabaseType(), $databaseVersion]); $notification = new Notification($message); $notification->raw = true; $notification->title = Piwik::translate('General_Warning'); $notification->priority = Notification::PRIORITY_LOW; $notification->context = Notification::CONTEXT_WARNING; $notification->type = Notification::TYPE_TRANSIENT; $notification->flags = Notification::FLAG_NO_CLEAR; NotificationManager::notify('DatabaseVersionCheck', $notification); } private static function notifyWhenDebugOnDemandIsEnabled($trackerSetting) { if ( !Development::isEnabled() && Piwik::hasUserSuperUserAccess() && TrackerConfig::getConfigValue($trackerSetting) ) { $message = Piwik::translate('General_WarningDebugOnDemandEnabled'); $message = sprintf( $message, '"' . $trackerSetting . '"', '"[Tracker] ' . $trackerSetting . '"', '"0"', '"config/config.ini.php"' ); $notification = new Notification($message); $notification->title = Piwik::translate('General_Warning'); $notification->priority = Notification::PRIORITY_LOW; $notification->context = Notification::CONTEXT_WARNING; $notification->type = Notification::TYPE_TRANSIENT; $notification->flags = Notification::FLAG_NO_CLEAR; NotificationManager::notify('Tracker' . $trackerSetting, $notification); } } /** * Assigns view properties that would be useful to views that render admin pages. * * Assigns the following variables: * * - **statisticsNotRecorded** - Set to true if the `[Tracker] record_statistics` INI * config is `0`. If not `0`, this variable will not be defined. * - **topMenu** - The result of `MenuTop::getInstance()->getMenu()`. * - **enableFrames** - The value of the `[General] enable_framed_pages` INI config option. If * true, {@link Piwik\View::setXFrameOptions()} is called on the view. * - **isSuperUser** - Whether the current user is a superuser or not. * - **usingOldGeoIPPlugin** - Whether this Piwik install is currently using the old GeoIP * plugin or not. * - **invalidPluginsWarning** - Set if some of the plugins to load (determined by INI configuration) * are invalid or missing. * - **phpVersion** - The current PHP version. * - **phpIsNewEnough** - Whether the current PHP version is new enough to run Piwik. * - **adminMenu** - The result of `MenuAdmin::getInstance()->getMenu()`. * * @api */ public static function setBasicVariablesAdminView(View $view) { self::notifyWhenTrackingStatisticsDisabled(); self::notifyIfEAcceleratorIsUsed(); self::notifyIfURLIsNotSecure(); self::notifyIfDevelopmentModeOnButNotInstalledThroughGit(); $view->topMenu = MenuTop::getInstance()->getMenu(); $view->isDataPurgeSettingsEnabled = self::isDataPurgeSettingsEnabled(); $enableFrames = PiwikConfig::getInstance()->General['enable_framed_settings']; $view->enableFrames = $enableFrames; if (!$enableFrames) { $view->setXFrameOptions('sameorigin'); } $view->isSuperUser = Piwik::hasUserSuperUserAccess(); self::notifyAnyInvalidLicense(); self::notifyAnyInvalidPlugin(); self::notifyWhenPhpVersionIsEOL(); self::notifyWhenPhpVersionIsNotCompatibleWithNextMajorPiwik(); self::notifyWhenDatabaseVersionIsNotCompatibleWithNextMajorPiwik(); self::notifyWhenDatabaseVersionIsEOL(); self::notifyWhenDebugOnDemandIsEnabled('debug'); self::notifyWhenDebugOnDemandIsEnabled('debug_on_demand'); /** * Posted when rendering an admin page and notifications about any warnings or errors should be triggered. * You can use it for example when you have a plugin that needs to be configured in order to work and the * plugin has not been configured yet. It can be also used to cancel / remove other notifications by calling * eg `Notification\Manager::cancel($notificationId)`. * * **Example** * * public function onTriggerAdminNotifications(Piwik\Widget\WidgetsList $list) * { * if ($pluginFooIsNotConfigured) { * $notification = new Notification('The plugin foo has not been configured yet'); * $notification->context = Notification::CONTEXT_WARNING; * Notification\Manager::notify('fooNotConfigured', $notification); * } * } * */ Piwik::postEvent('Controller.triggerAdminNotifications'); $view->adminMenu = MenuAdmin::getInstance()->getMenu(); $notifications = $view->notifications; if (empty($notifications)) { $view->notifications = NotificationManager::getAllNotificationsToDisplay(); NotificationManager::cancelAllNonPersistent(); } } public static function isDataPurgeSettingsEnabled() { return (bool) Config::getInstance()->General['enable_delete_old_data_settings_admin']; } protected static function getPiwikVersion() { return "Matomo " . Version::VERSION; } private static function isPhpVersionEOL() { $phpEOL = '8.0'; // End of security update for certain PHP versions as of https://www.php.net/supported-versions if (Date::today()->isLater(Date::factory('2025-12-31'))) { $phpEOL = '8.1'; } if (Date::today()->isLater(Date::factory('2026-12-31'))) { $phpEOL = '8.2'; } if (Date::today()->isLater(Date::factory('2027-12-31'))) { $phpEOL = '8.3'; } if (Date::today()->isLater(Date::factory('2028-12-31'))) { $phpEOL = '8.4'; } return version_compare(PHP_MAJOR_VERSION . '.' . PHP_MINOR_VERSION, $phpEOL, '<='); } }