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