PluginProbe ʕ •ᴥ•ʔ
Matomo Analytics – Powerful, Privacy-First Insights for WordPress / 5.8.2
Matomo Analytics – Powerful, Privacy-First Insights for WordPress v5.8.2
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 / Plugin / ControllerAdmin.php
matomo / app / core / Plugin Last commit date
ConsoleCommand 2 years ago Dimension 3 months ago API.php 6 months ago AggregatedMetric.php 2 years ago ArchivedMetric.php 1 year ago Archiver.php 6 months ago Categories.php 2 years ago ComponentFactory.php 3 months ago ComputedMetric.php 1 year ago ConsoleCommand.php 3 months ago Controller.php 3 months ago ControllerAdmin.php 3 months ago Dependency.php 1 year ago LogTablesProvider.php 2 years ago Manager.php 3 months ago Menu.php 3 months ago MetadataLoader.php 1 year ago Metric.php 3 months ago PluginException.php 1 year ago ProcessedMetric.php 3 months ago ReleaseChannels.php 3 months ago Report.php 3 months ago ReportsProvider.php 2 years ago RequestProcessors.php 4 months ago Segment.php 3 months ago SettingsProvider.php 3 months ago Tasks.php 3 months ago ThemeStyles.php 6 months ago ViewDataTable.php 3 months ago Visualization.php 1 year ago WidgetsProvider.php 3 months ago
ControllerAdmin.php
367 lines
1 <?php
2
3 /**
4 * Matomo - free/libre analytics platform
5 *
6 * @link https://matomo.org
7 * @license https://www.gnu.org/licenses/gpl-3.0.html GPL v3 or later
8 */
9 namespace Piwik\Plugin;
10
11 use Piwik\Config as PiwikConfig;
12 use Piwik\Config;
13 use Piwik\Container\StaticContainer;
14 use Piwik\Date;
15 use Piwik\Db\Schema;
16 use Piwik\Development;
17 use Piwik\Exception\MissingFilePermissionException;
18 use Piwik\Menu\MenuAdmin;
19 use Piwik\Menu\MenuTop;
20 use Piwik\Notification;
21 use Piwik\Notification\Manager as NotificationManager;
22 use Piwik\Piwik;
23 use Piwik\Plugins\Marketplace\Marketplace;
24 use Piwik\Tracker\TrackerConfig;
25 use Piwik\Url;
26 use Piwik\Version;
27 use Piwik\View;
28 use Piwik\ProxyHttp;
29 use Piwik\SettingsPiwik;
30 /**
31 * Base class of plugin controllers that provide administrative functionality.
32 *
33 * See {@link Controller} to learn more about Piwik controllers.
34 *
35 */
36 abstract class ControllerAdmin extends \Piwik\Plugin\Controller
37 {
38 private static function notifyWhenTrackingStatisticsDisabled()
39 {
40 $statsEnabled = PiwikConfig::getInstance()->Tracker['record_statistics'];
41 if ($statsEnabled == "0") {
42 $notification = new Notification(Piwik::translate('General_StatisticsAreNotRecorded'));
43 $notification->context = Notification::CONTEXT_INFO;
44 Notification\Manager::notify('ControllerAdmin_StatsAreNotRecorded', $notification);
45 }
46 }
47 private static function notifyAnyInvalidLicense()
48 {
49 if (!Marketplace::isMarketplaceEnabled()) {
50 return;
51 }
52 if (Piwik::isUserIsAnonymous()) {
53 return;
54 }
55 if (!Piwik::isUserHasSomeAdminAccess()) {
56 return;
57 }
58 if (Development::isEnabled()) {
59 return;
60 }
61 $expired = StaticContainer::get('Piwik\\Plugins\\Marketplace\\Plugins\\InvalidLicenses');
62 $messageLicenseMissing = $expired->getMessageNoLicense();
63 if (!empty($messageLicenseMissing)) {
64 $notification = new Notification($messageLicenseMissing);
65 $notification->raw = \true;
66 $notification->context = Notification::CONTEXT_ERROR;
67 $notification->title = Piwik::translate('Marketplace_LicenseMissing');
68 Notification\Manager::notify('ControllerAdmin_LicenseMissingWarning', $notification);
69 }
70 $messageExceeded = $expired->getMessageExceededLicenses();
71 if (!empty($messageExceeded)) {
72 $notification = new Notification($messageExceeded);
73 $notification->raw = \true;
74 $notification->context = Notification::CONTEXT_WARNING;
75 $notification->title = Piwik::translate('Marketplace_LicenseExceeded');
76 Notification\Manager::notify('ControllerAdmin_LicenseExceededWarning', $notification);
77 }
78 $messageExpired = $expired->getMessageExpiredLicenses();
79 if (!empty($messageExpired)) {
80 $notification = new Notification($messageExpired);
81 $notification->raw = \true;
82 $notification->context = Notification::CONTEXT_WARNING;
83 $notification->title = Piwik::translate('Marketplace_LicenseExpired');
84 Notification\Manager::notify('ControllerAdmin_LicenseExpiredWarning', $notification);
85 }
86 }
87 private static function notifyAnyInvalidPlugin()
88 {
89 if (!Piwik::hasUserSuperUserAccess()) {
90 return;
91 }
92 $missingPlugins = \Piwik\Plugin\Manager::getInstance()->getMissingPlugins();
93 if (empty($missingPlugins)) {
94 return;
95 }
96 $pluginsLink = Url::getCurrentQueryStringWithParametersModified(['module' => 'CorePluginsAdmin', 'action' => 'plugins']);
97 $invalidPluginsWarning = Piwik::translate('CoreAdminHome_InvalidPluginsWarning', [self::getPiwikVersion(), '<strong>' . implode('</strong>,&nbsp;<wbr><strong>', $missingPlugins) . '</strong>']) . "<br/>" . Piwik::translate('CoreAdminHome_InvalidPluginsYouCanUninstall', ['<a href="' . $pluginsLink . '"/>', '</a>']);
98 $notification = new Notification($invalidPluginsWarning);
99 $notification->raw = \true;
100 $notification->context = Notification::CONTEXT_WARNING;
101 $notification->title = Piwik::translate('General_Warning');
102 Notification\Manager::notify('ControllerAdmin_InvalidPluginsWarning', $notification);
103 }
104 /**
105 * Calls {@link setBasicVariablesView()} and {@link setBasicVariablesAdminView()}
106 * using the supplied view.
107 *
108 * @param View $view
109 * @param string $viewType If 'admin', the admin variables are set as well as basic ones.
110 */
111 protected function setBasicVariablesViewAs($view, $viewType = 'admin')
112 {
113 $this->setBasicVariablesNoneAdminView($view);
114 if ($viewType === 'admin') {
115 self::setBasicVariablesAdminView($view);
116 }
117 }
118 private static function notifyIfURLIsNotSecure()
119 {
120 $isURLSecure = ProxyHttp::isHttps();
121 if ($isURLSecure) {
122 return;
123 }
124 if (!Piwik::hasUserSuperUserAccess()) {
125 return;
126 }
127 if (Url::isLocalHost(Url::getCurrentHost())) {
128 return;
129 }
130 if (Development::isEnabled()) {
131 return;
132 }
133 $message = Piwik::translate('General_CurrentlyUsingUnsecureHttp');
134 $message .= " ";
135 $message .= Piwik::translate('General_ReadThisToLearnMore', [Url::getExternalLinkTag('https://matomo.org/faq/how-to/faq_91/'), '</a>']);
136 $notification = new Notification($message);
137 $notification->context = Notification::CONTEXT_WARNING;
138 $notification->raw = \true;
139 Notification\Manager::notify('ControllerAdmin_HttpIsUsed', $notification);
140 }
141 private static function notifyIfDevelopmentModeOnButNotInstalledThroughGit()
142 {
143 if (!Piwik::hasUserSuperUserAccess()) {
144 return;
145 }
146 if (!Development::isEnabled()) {
147 return;
148 }
149 if (SettingsPiwik::isGitDeployment()) {
150 return;
151 }
152 $message = Piwik::translate('General_WarningDevelopmentModeOnButNotGitInstalled');
153 $notification = new Notification($message);
154 $notification->context = Notification::CONTEXT_WARNING;
155 $notification->raw = \true;
156 $notification->flags = Notification::FLAG_CLEAR;
157 Notification\Manager::notify('ControllerAdmin_DevelopmentModeOn', $notification);
158 }
159 /**
160 * @ignore
161 */
162 public static function displayWarningIfConfigFileNotWritable()
163 {
164 try {
165 PiwikConfig::getInstance()->checkConfigIsWritable();
166 } catch (MissingFilePermissionException $exception) {
167 $notification = new Notification($exception->getMessage());
168 $notification->raw = \true;
169 $notification->context = Notification::CONTEXT_WARNING;
170 Notification\Manager::notify('ControllerAdmin_ConfigNotWriteable', $notification);
171 }
172 }
173 private static function notifyIfEAcceleratorIsUsed()
174 {
175 $isEacceleratorUsed = ini_get('eaccelerator.enable');
176 if (empty($isEacceleratorUsed)) {
177 return;
178 }
179 $message = sprintf("You are using the PHP accelerator & optimizer eAccelerator which is known to be not compatible with Matomo.\n We have disabled eAccelerator, which might affect the performance of Matomo.\n 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>');
180 $notification = new Notification($message);
181 $notification->context = Notification::CONTEXT_WARNING;
182 $notification->raw = \true;
183 Notification\Manager::notify('ControllerAdmin_EacceleratorIsUsed', $notification);
184 }
185 /**
186 * PHP Version required by the next major Matomo version
187 * @return string
188 */
189 private static function getNextRequiredMinimumPHP()
190 {
191 return '7.2';
192 }
193 private static function isUsingPhpVersionCompatibleWithNextPiwik()
194 {
195 return version_compare(\PHP_VERSION, self::getNextRequiredMinimumPHP(), '>=');
196 }
197 private static function notifyWhenPhpVersionIsNotCompatibleWithNextMajorPiwik()
198 {
199 if (self::isUsingPhpVersionCompatibleWithNextPiwik()) {
200 return;
201 }
202 $youMustUpgradePHP = Piwik::translate('General_YouMustUpgradePhpVersionToReceiveLatestPiwik');
203 $message = Piwik::translate('General_PiwikCannotBeUpgradedBecausePhpIsTooOld') . ' ' . sprintf(Piwik::translate('General_PleaseUpgradeYourPhpVersionSoYourPiwikDataStaysSecure'), self::getNextRequiredMinimumPHP());
204 $notification = new Notification($message);
205 $notification->title = $youMustUpgradePHP;
206 $notification->priority = Notification::PRIORITY_LOW;
207 $notification->context = Notification::CONTEXT_WARNING;
208 $notification->type = Notification::TYPE_TRANSIENT;
209 $notification->flags = Notification::FLAG_NO_CLEAR;
210 NotificationManager::notify('PHPVersionTooOldForNewestPiwikCheck', $notification);
211 }
212 private static function notifyWhenPhpVersionIsEOL()
213 {
214 if (defined('PIWIK_TEST_MODE')) {
215 // to avoid changing every admin UI test
216 return;
217 }
218 $notifyPhpIsEOL = Piwik::hasUserSuperUserAccess() && self::isPhpVersionEOL();
219 if (!$notifyPhpIsEOL) {
220 return;
221 }
222 $deprecatedMajorPhpVersion = \PHP_MAJOR_VERSION . '.' . \PHP_MINOR_VERSION;
223 $message = '';
224 if (version_compare(\PHP_VERSION, self::getNextRequiredMinimumPHP(), '<')) {
225 $message = Piwik::translate('General_WarningPiwikWillStopSupportingPHPVersion', [$deprecatedMajorPhpVersion, self::getNextRequiredMinimumPHP()]) . '<br/>';
226 }
227 $message .= Piwik::translate('General_WarningPhpVersionXIsTooOld', $deprecatedMajorPhpVersion);
228 $notification = new Notification($message);
229 $notification->raw = \true;
230 $notification->title = Piwik::translate('General_Warning');
231 $notification->priority = Notification::PRIORITY_LOW;
232 $notification->context = Notification::CONTEXT_WARNING;
233 $notification->type = Notification::TYPE_TRANSIENT;
234 $notification->flags = Notification::FLAG_NO_CLEAR;
235 NotificationManager::notify('PHPVersionCheck', $notification);
236 }
237 private static function notifyWhenDatabaseVersionIsEOL() : void
238 {
239 if (defined('PIWIK_TEST_MODE')) {
240 // to avoid changing every admin UI test
241 return;
242 }
243 $isEOL = Piwik::hasUserSuperUserAccess() && Schema::getInstance()->hasReachedEOL();
244 if (!$isEOL) {
245 return;
246 }
247 $databaseVersion = Schema::getInstance()->getVersion();
248 $message = Piwik::translate('General_WarningDatabaseVersionXIsTooOld', [Schema::getInstance()->getDatabaseType(), $databaseVersion]);
249 $notification = new Notification($message);
250 $notification->raw = \true;
251 $notification->title = Piwik::translate('General_Warning');
252 $notification->priority = Notification::PRIORITY_LOW;
253 $notification->context = Notification::CONTEXT_WARNING;
254 $notification->type = Notification::TYPE_TRANSIENT;
255 $notification->flags = Notification::FLAG_NO_CLEAR;
256 NotificationManager::notify('DatabaseVersionCheck', $notification);
257 }
258 private static function notifyWhenDebugOnDemandIsEnabled($trackerSetting)
259 {
260 if (!Development::isEnabled() && Piwik::hasUserSuperUserAccess() && TrackerConfig::getConfigValue($trackerSetting)) {
261 $message = Piwik::translate('General_WarningDebugOnDemandEnabled');
262 $message = sprintf($message, '"' . $trackerSetting . '"', '"[Tracker] ' . $trackerSetting . '"', '"0"', '"config/config.ini.php"');
263 $notification = new Notification($message);
264 $notification->title = Piwik::translate('General_Warning');
265 $notification->priority = Notification::PRIORITY_LOW;
266 $notification->context = Notification::CONTEXT_WARNING;
267 $notification->type = Notification::TYPE_TRANSIENT;
268 $notification->flags = Notification::FLAG_NO_CLEAR;
269 NotificationManager::notify('Tracker' . $trackerSetting, $notification);
270 }
271 }
272 /**
273 * Assigns view properties that would be useful to views that render admin pages.
274 *
275 * Assigns the following variables:
276 *
277 * - **statisticsNotRecorded** - Set to true if the `[Tracker] record_statistics` INI
278 * config is `0`. If not `0`, this variable will not be defined.
279 * - **topMenu** - The result of `MenuTop::getInstance()->getMenu()`.
280 * - **enableFrames** - The value of the `[General] enable_framed_pages` INI config option. If
281 * true, {@link Piwik\View::setXFrameOptions()} is called on the view.
282 * - **isSuperUser** - Whether the current user is a superuser or not.
283 * - **usingOldGeoIPPlugin** - Whether this Piwik install is currently using the old GeoIP
284 * plugin or not.
285 * - **invalidPluginsWarning** - Set if some of the plugins to load (determined by INI configuration)
286 * are invalid or missing.
287 * - **phpVersion** - The current PHP version.
288 * - **phpIsNewEnough** - Whether the current PHP version is new enough to run Piwik.
289 * - **adminMenu** - The result of `MenuAdmin::getInstance()->getMenu()`.
290 *
291 * @api
292 */
293 public static function setBasicVariablesAdminView(View $view)
294 {
295 self::notifyWhenTrackingStatisticsDisabled();
296 self::notifyIfEAcceleratorIsUsed();
297 self::notifyIfURLIsNotSecure();
298 self::notifyIfDevelopmentModeOnButNotInstalledThroughGit();
299 $view->topMenu = MenuTop::getInstance()->getMenu();
300 $view->isDataPurgeSettingsEnabled = self::isDataPurgeSettingsEnabled();
301 $enableFrames = PiwikConfig::getInstance()->General['enable_framed_settings'];
302 $view->enableFrames = $enableFrames;
303 if (!$enableFrames) {
304 $view->setXFrameOptions('sameorigin');
305 }
306 $view->isSuperUser = Piwik::hasUserSuperUserAccess();
307 self::notifyAnyInvalidLicense();
308 self::notifyAnyInvalidPlugin();
309 self::notifyWhenPhpVersionIsEOL();
310 self::notifyWhenPhpVersionIsNotCompatibleWithNextMajorPiwik();
311 self::notifyWhenDatabaseVersionIsEOL();
312 self::notifyWhenDebugOnDemandIsEnabled('debug');
313 self::notifyWhenDebugOnDemandIsEnabled('debug_on_demand');
314 /**
315 * Posted when rendering an admin page and notifications about any warnings or errors should be triggered.
316 * You can use it for example when you have a plugin that needs to be configured in order to work and the
317 * plugin has not been configured yet. It can be also used to cancel / remove other notifications by calling
318 * eg `Notification\Manager::cancel($notificationId)`.
319 *
320 * **Example**
321 *
322 * public function onTriggerAdminNotifications(Piwik\Widget\WidgetsList $list)
323 * {
324 * if ($pluginFooIsNotConfigured) {
325 * $notification = new Notification('The plugin foo has not been configured yet');
326 * $notification->context = Notification::CONTEXT_WARNING;
327 * Notification\Manager::notify('fooNotConfigured', $notification);
328 * }
329 * }
330 *
331 */
332 Piwik::postEvent('Controller.triggerAdminNotifications');
333 $view->adminMenu = MenuAdmin::getInstance()->getMenu();
334 $notifications = $view->notifications;
335 if (empty($notifications)) {
336 $view->notifications = NotificationManager::getAllNotificationsToDisplay();
337 NotificationManager::cancelAllNonPersistent();
338 }
339 }
340 public static function isDataPurgeSettingsEnabled()
341 {
342 return (bool) Config::getInstance()->General['enable_delete_old_data_settings_admin'];
343 }
344 protected static function getPiwikVersion()
345 {
346 return "Matomo " . Version::VERSION;
347 }
348 private static function isPhpVersionEOL()
349 {
350 $phpEOL = '8.0';
351 // End of security update for certain PHP versions as of https://www.php.net/supported-versions
352 if (Date::today()->isLater(Date::factory('2025-12-31'))) {
353 $phpEOL = '8.1';
354 }
355 if (Date::today()->isLater(Date::factory('2026-12-31'))) {
356 $phpEOL = '8.2';
357 }
358 if (Date::today()->isLater(Date::factory('2027-12-31'))) {
359 $phpEOL = '8.3';
360 }
361 if (Date::today()->isLater(Date::factory('2028-12-31'))) {
362 $phpEOL = '8.4';
363 }
364 return version_compare(\PHP_MAJOR_VERSION . '.' . \PHP_MINOR_VERSION, $phpEOL, '<=');
365 }
366 }
367