| <?php |
|
|
| |
| |
| |
| |
| |
| |
|
|
| namespace Piwik\Plugin; |
|
|
| use Piwik\Config as PiwikConfig; |
| use Piwik\Config; |
| use Piwik\Container\StaticContainer; |
| use Piwik\Date; |
| use Piwik\Db\Schema; |
| use Piwik\Development; |
| use Piwik\Exception\MissingFilePermissionException; |
| use Piwik\Menu\MenuAdmin; |
| use Piwik\Menu\MenuTop; |
| use Piwik\Notification; |
| use Piwik\Notification\Manager as NotificationManager; |
| use Piwik\Piwik; |
| use Piwik\Plugins\CorePluginsAdmin\CorePluginsAdmin; |
| use Piwik\Plugins\Marketplace\Marketplace; |
| use Piwik\Tracker\TrackerConfig; |
| use Piwik\Url; |
| use Piwik\Version; |
| use Piwik\View; |
| use Piwik\ProxyHttp; |
| use Piwik\SettingsPiwik; |
|
|
| |
| |
| |
| |
| |
| |
| abstract class ControllerAdmin extends Controller |
| { |
| private const NEXT_REQUIRED_MINIMUM_PHP = '8.1'; |
| private const NEXT_REQUIRED_MINIMUM_MYSQL = '8.0'; |
| private const NEXT_REQUIRED_MINIMUM_MARIADB = '10.6'; |
|
|
| private static function notifyWhenTrackingStatisticsDisabled() |
| { |
| $statsEnabled = PiwikConfig::getInstance()->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(), |
| '<strong>' . implode('</strong>, <wbr><strong>', $missingPlugins) . '</strong>', |
| ]); |
|
|
| if (CorePluginsAdmin::isPluginsAdminEnabled()) { |
| $pluginsLink = Url::getCurrentQueryStringWithParametersModified([ |
| 'module' => 'CorePluginsAdmin', 'action' => 'plugins', |
| ]); |
| $invalidPluginsWarning .= '<br/>' . Piwik::translate('CoreAdminHome_InvalidPluginsYouCanUninstall', [ |
| '<a href="' . $pluginsLink . '">', |
| '</a>', |
| ]); |
| } else { |
| $invalidPluginsWarning .= '<br/>' . 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); |
| } |
|
|
| |
| |
| |
| |
| |
| |
| |
| 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/'), '</a>'] |
| ); |
|
|
| $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); |
| } |
|
|
| |
| |
| |
| 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.", |
| '<a rel="noreferrer noopener" target="_blank" href="https://github.com/matomo-org/matomo/issues/4439">', |
| '</a>' |
| ); |
|
|
| $notification = new Notification($message); |
| $notification->context = Notification::CONTEXT_WARNING; |
| $notification->raw = true; |
| Notification\Manager::notify('ControllerAdmin_EacceleratorIsUsed', $notification); |
| } |
|
|
| |
| |
| |
| |
| 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')) { |
| 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')) { |
| 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')) { |
| 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()] |
| ) . '<br/>'; |
| } |
|
|
| $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')) { |
| 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); |
| } |
| } |
|
|
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| 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'); |
|
|
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| 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'; |
|
|
| |
| 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, '<='); |
| } |
| } |
|
|