diff options
author | Stefan Giehl <stefan@piwik.org> | 2018-07-10 22:44:52 +0300 |
---|---|---|
committer | GitHub <noreply@github.com> | 2018-07-10 22:44:52 +0300 |
commit | 4b88aa24c9c85c45340ca854c812c21014d86dc2 (patch) | |
tree | e1f279d3d4faa5d3ac00a523dff360e9abec3fe0 | |
parent | a4c01fe919de7c5696e3c06d2c066085e08ec255 (diff) |
Disables some more feature if internet features are disabled (#13076)
* Disable GeoIP update tasks if no internet connection available
* Show GeoLocation Auto Updater UI only with enabled internet connection
* Throw exception if Marketplace is used without enabled internet features
* Hide Marketplace menu entry if internet is disabled
* Implements new plugin class method requiresInternetConnection, to automatically unloaded plugins if required
* Improve how plugins not working without internet connection are shown in plugin list
* Adds UI test
* typo 'whether'
-rw-r--r-- | CHANGELOG.md | 1 | ||||
-rw-r--r-- | core/Exception/PluginRequiresInternetException.php | 20 | ||||
-rw-r--r-- | core/FrontController.php | 5 | ||||
-rw-r--r-- | core/Plugin.php | 16 | ||||
-rw-r--r-- | core/Plugin/Manager.php | 23 | ||||
-rw-r--r-- | plugins/CorePluginsAdmin/lang/en.json | 1 | ||||
-rw-r--r-- | plugins/GeoIp2/GeoIP2AutoUpdater.php | 6 | ||||
-rw-r--r-- | plugins/Marketplace/Marketplace.php | 5 | ||||
-rw-r--r-- | plugins/MobileMessaging/MobileMessaging.php | 5 | ||||
-rw-r--r-- | plugins/UserCountry/Controller.php | 3 | ||||
-rw-r--r-- | plugins/UserCountry/GeoIPAutoUpdater.php | 6 | ||||
-rw-r--r-- | plugins/UserCountry/templates/adminIndex.twig | 86 | ||||
-rw-r--r-- | tests/UI/expected-screenshots/UIIntegrationTest_admin_plugins_no_internet.png | 3 | ||||
-rw-r--r-- | tests/UI/specs/UIIntegration_spec.js | 14 |
14 files changed, 151 insertions, 43 deletions
diff --git a/CHANGELOG.md b/CHANGELOG.md index 278701d8ae..0d9e4a5ae5 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -9,6 +9,7 @@ The Product Changelog at **[matomo.org/changelog](https://matomo.org/changelog)* ### New APIs * Added new event `API.addGlossaryItems` which lets you add items to the glossary. +* Plugin classes can overwrite the method `requiresInternetConnection` to define if they should be automatically unloaded if no internet connection is available (enable_internet_features = 0) ### Breaking Changes * Changed some menu items to use translation keys instead (see [PR #12885](https://github.com/matomo-org/matomo/pull/12885)). diff --git a/core/Exception/PluginRequiresInternetException.php b/core/Exception/PluginRequiresInternetException.php new file mode 100644 index 0000000000..b4a32a9452 --- /dev/null +++ b/core/Exception/PluginRequiresInternetException.php @@ -0,0 +1,20 @@ +<?php +/** + * Piwik - free/libre analytics platform + * + * @link http://piwik.org + * @license http://www.gnu.org/licenses/gpl-3.0.html GPL v3 or later + */ + +namespace Piwik\Exception; + +/** + * Exception thrown when the requested plugin requires internet connection, but internet features are disabled in the config file + */ +class PluginRequiresInternetException extends \Exception +{ + public function __construct($module) + { + parent::__construct("The plugin $module requires internet connection. Please check your config value for `enable_internet_features` if you want to use this feature."); + } +} diff --git a/core/FrontController.php b/core/FrontController.php index 2e0ff8e960..c7b75a84b6 100644 --- a/core/FrontController.php +++ b/core/FrontController.php @@ -15,6 +15,7 @@ use Piwik\Container\StaticContainer; use Piwik\Exception\AuthenticationFailedException; use Piwik\Exception\DatabaseSchemaIsNewerThanCodebaseException; use Piwik\Exception\PluginDeactivatedException; +use Piwik\Exception\PluginRequiresInternetException; use Piwik\Exception\StylesheetLessCompileException; use Piwik\Http\ControllerResolver; use Piwik\Http\Router; @@ -422,6 +423,10 @@ class FrontController extends Singleton list($module, $action) = Request::getRenamedModuleAndAction($module, $action); + if (!SettingsPiwik::isInternetEnabled() && \Piwik\Plugin\Manager::getInstance()->doesPluginRequireInternetConnection($module)) { + throw new PluginRequiresInternetException($module); + } + if (!\Piwik\Plugin\Manager::getInstance()->isPluginActivated($module)) { throw new PluginDeactivatedException($module); } diff --git a/core/Plugin.php b/core/Plugin.php index d0186ab87c..2579b2967d 100644 --- a/core/Plugin.php +++ b/core/Plugin.php @@ -244,6 +244,18 @@ class Plugin } /** + * Defines whether the whole plugin requires a working internet connection + * If set to true, the plugin will be automatically unloaded if `enable_internet_features` is 0, + * even if the plugin is activated + * + * @return bool + */ + public function requiresInternetConnection() + { + return false; + } + + /** * Installs the plugin. Derived classes should implement this class if the plugin * needs to: * @@ -435,6 +447,10 @@ class Plugin */ public function getMissingDependenciesAsString($piwikVersion = null) { + if ($this->requiresInternetConnection() && !SettingsPiwik::isInternetEnabled()) { + return Piwik::translate('CorePluginsAdmin_PluginRequiresInternet'); + } + if (empty($this->pluginInformation['require'])) { return ''; } diff --git a/core/Plugin/Manager.php b/core/Plugin/Manager.php index 122ba781cf..506e19bc9c 100644 --- a/core/Plugin/Manager.php +++ b/core/Plugin/Manager.php @@ -105,6 +105,12 @@ class Manager public function loadActivatedPlugins() { $pluginsToLoad = $this->getActivatedPluginsFromConfig(); + if (!SettingsPiwik::isInternetEnabled()) { + $pluginsToLoad = array_filter($pluginsToLoad, function($name) { + $plugin = Manager::makePluginClass($name); + return !$plugin->requiresInternetConnection(); + }); + } $this->loadPlugins($pluginsToLoad); } @@ -266,6 +272,19 @@ class Manager } /** + * Returns `true` if a plugin requires an working internet connection + * + * @param string $name Name of plugin, eg, `'Actions'`. + * @return bool + * @throws \Exception + */ + public function doesPluginRequireInternetConnection($name) + { + $plugin = $this->makePluginClass($name); + return $plugin->requiresInternetConnection(); + } + + /** * Checks whether the given plugin is activated, if not triggers an exception. * * @param string $pluginName @@ -597,6 +616,7 @@ class Manager $this->pluginList->getActivatedPlugins() ); $listPlugins = array_unique($listPlugins); + $internetFeaturesEnabled = SettingsPiwik::isInternetEnabled(); foreach ($listPlugins as $pluginName) { // Hide plugins that are never going to be used if ($this->isPluginBogus($pluginName)) { @@ -1120,7 +1140,8 @@ class Manager foreach ($plugins as $pluginName) { // if a plugin is listed in the config, but is not loaded, it does not exist in the folder - if (!$this->isPluginLoaded($pluginName) && !$this->isPluginBogus($pluginName) ) { + if (!$this->isPluginLoaded($pluginName) && !$this->isPluginBogus($pluginName) && + !($this->doesPluginRequireInternetConnection($pluginName) && !SettingsPiwik::isInternetEnabled())) { $missingPlugins[] = $pluginName; } } diff --git a/plugins/CorePluginsAdmin/lang/en.json b/plugins/CorePluginsAdmin/lang/en.json index 34bb28be55..eab5ce5052 100644 --- a/plugins/CorePluginsAdmin/lang/en.json +++ b/plugins/CorePluginsAdmin/lang/en.json @@ -49,6 +49,7 @@ "NotDownloadable": "Not downloadable", "PluginNotDownloadable": "The plugin is not downloadable.", "PluginNotDownloadablePaidReason": "Possible reasons are an expired or exceeded license.", + "PluginRequiresInternet": "This plugin requires a working internet connection. Please check your config value for `enable_internet_features` if you want to use this feature.", "PluginActivated": "Plugin activated", "Status": "Status", "SuccessfullyActicated": "You have successfully activated <strong>%s<\/strong>.", diff --git a/plugins/GeoIp2/GeoIP2AutoUpdater.php b/plugins/GeoIp2/GeoIP2AutoUpdater.php index 458609aee9..4c91a8f864 100644 --- a/plugins/GeoIp2/GeoIP2AutoUpdater.php +++ b/plugins/GeoIp2/GeoIP2AutoUpdater.php @@ -27,6 +27,7 @@ use Piwik\Scheduler\Task; use Piwik\Scheduler\Timetable; use Piwik\Scheduler\Schedule\Monthly; use Piwik\Scheduler\Schedule\Weekly; +use Piwik\SettingsPiwik; use Piwik\Unzip; /** @@ -63,6 +64,11 @@ class GeoIP2AutoUpdater extends Task */ public function __construct() { + if (!SettingsPiwik::isInternetEnabled()) { + // no automatic updates possible if no internet available + return; + } + $schedulePeriodStr = self::getSchedulePeriod(); // created the scheduledtime instance, also, since GeoIP 2 updates are done on tuesdays, diff --git a/plugins/Marketplace/Marketplace.php b/plugins/Marketplace/Marketplace.php index a5991a9f80..ae77971975 100644 --- a/plugins/Marketplace/Marketplace.php +++ b/plugins/Marketplace/Marketplace.php @@ -37,6 +37,11 @@ class Marketplace extends \Piwik\Plugin return true; } + public function requiresInternetConnection() + { + return true; + } + public function checkForUpdates() { $marketplace = StaticContainer::get('Piwik\Plugins\Marketplace\Api\Client'); diff --git a/plugins/MobileMessaging/MobileMessaging.php b/plugins/MobileMessaging/MobileMessaging.php index 04d5eef215..42783ea0e8 100644 --- a/plugins/MobileMessaging/MobileMessaging.php +++ b/plugins/MobileMessaging/MobileMessaging.php @@ -82,6 +82,11 @@ class MobileMessaging extends \Piwik\Plugin ); } + public function requiresInternetConnection() + { + return true; + } + /** * Get JavaScript files */ diff --git a/plugins/UserCountry/Controller.php b/plugins/UserCountry/Controller.php index 6097a5e0bf..bbb67d4020 100644 --- a/plugins/UserCountry/Controller.php +++ b/plugins/UserCountry/Controller.php @@ -19,6 +19,7 @@ use Piwik\Plugins\GeoIp2\GeoIP2AutoUpdater; use Piwik\Plugins\UserCountry\LocationProvider\GeoIp; use Piwik\Plugins\GeoIp2\LocationProvider\GeoIp2; use Piwik\Plugins\UserCountry\LocationProvider\DefaultProvider; +use Piwik\SettingsPiwik; use Piwik\View; /** @@ -79,6 +80,8 @@ class Controller extends \Piwik\Plugin\ControllerAdmin $view->showGeoIPUpdateSection = false; } + $view->isInternetEnabled = SettingsPiwik::isInternetEnabled(); + $this->setUpdaterManageVars($view); $this->setBasicVariablesView($view); $this->setBasicVariablesAdminView($view); diff --git a/plugins/UserCountry/GeoIPAutoUpdater.php b/plugins/UserCountry/GeoIPAutoUpdater.php index 53b299a5c6..4f62fc7ec1 100644 --- a/plugins/UserCountry/GeoIPAutoUpdater.php +++ b/plugins/UserCountry/GeoIPAutoUpdater.php @@ -26,6 +26,7 @@ use Piwik\Scheduler\Task; use Piwik\Scheduler\Timetable; use Piwik\Scheduler\Schedule\Monthly; use Piwik\Scheduler\Schedule\Weekly; +use Piwik\SettingsPiwik; use Piwik\Unzip; /** @@ -63,6 +64,11 @@ class GeoIPAutoUpdater extends Task */ public function __construct() { + if (!SettingsPiwik::isInternetEnabled()) { + // no automatic updates possible if no internet available + return; + } + $schedulePeriodStr = self::getSchedulePeriod(); // created the scheduledtime instance, also, since GeoIP updates are done on tuesdays, diff --git a/plugins/UserCountry/templates/adminIndex.twig b/plugins/UserCountry/templates/adminIndex.twig index e8f155342c..ea26230f5f 100644 --- a/plugins/UserCountry/templates/adminIndex.twig +++ b/plugins/UserCountry/templates/adminIndex.twig @@ -98,7 +98,7 @@ </div> </div> -{% if geoIPLegacyLocUrl is defined and geoIPLegacyLocUrl %} +{% if geoIPLegacyLocUrl is defined and geoIPLegacyLocUrl and isInternetEnabled %} {# The text in this part is not translatable on purpose, as it will be removed again soon #} <div piwik-content-block content-title="Automatic Updates for GeoIP Legacy"> @@ -127,54 +127,56 @@ </div> {% endif %} -<div piwik-content-block - content-title="{% if not geoIPDatabasesInstalled %}{{ 'UserCountry_GeoIPDatabases'|translate|e('html_attr') }}{% else %}{{ 'UserCountry_SetupAutomaticUpdatesOfGeoIP'|translate|e('html_attr') }}{% endif %}" - id="geoip-db-mangement"> - - <div piwik-location-provider-updater - geoip-database-installed="{% if geoIPDatabasesInstalled %}1{% else %}0{% endif %}"> - - {% if showGeoIPUpdateSection %} - {% if not geoIPDatabasesInstalled %} - <div ng-show="!locationUpdater.geoipDatabaseInstalled"> - <div ng-show="locationUpdater.showPiwikNotManagingInfo"> - <h3>{{ 'UserCountry_PiwikNotManagingGeoIPDBs'|translate|e('html_attr') }}</h3> - <div id="manage-geoip-dbs"> - <div class="row" id="geoipdb-screen1"> - <div class="geoipdb-column-1 col s6"> - <p>{{ 'UserCountry_IWantToDownloadFreeGeoIP'|translate|raw }}</p> - </div> - <div class="geoipdb-column-2 col s6"> - <p>{{ 'UserCountry_IPurchasedGeoIPDBs'|translate('<a href="http://www.maxmind.com/en/geolocation_landing?rId=piwik">','</a>')|raw }}</p> - </div> - <div class="geoipdb-column-1 col s6"> - <input type="button" class="btn" - ng-click="locationUpdater.startDownloadFreeGeoIp()" - value="{{ 'General_GetStarted'|translate }}..."/> - </div> - <div class="geoipdb-column-2 col s6"> - <input type="button" class="btn" - ng-click="locationUpdater.startAutomaticUpdateGeoIp()" - value="{{ 'General_GetStarted'|translate }}..." id="start-automatic-update-geoip"/> +{% if isInternetEnabled %} + <div piwik-content-block + content-title="{% if not geoIPDatabasesInstalled %}{{ 'UserCountry_GeoIPDatabases'|translate|e('html_attr') }}{% else %}{{ 'UserCountry_SetupAutomaticUpdatesOfGeoIP'|translate|e('html_attr') }}{% endif %}" + id="geoip-db-mangement"> + + <div piwik-location-provider-updater + geoip-database-installed="{% if geoIPDatabasesInstalled %}1{% else %}0{% endif %}"> + + {% if showGeoIPUpdateSection %} + {% if not geoIPDatabasesInstalled %} + <div ng-show="!locationUpdater.geoipDatabaseInstalled"> + <div ng-show="locationUpdater.showPiwikNotManagingInfo"> + <h3>{{ 'UserCountry_PiwikNotManagingGeoIPDBs'|translate|e('html_attr') }}</h3> + <div id="manage-geoip-dbs"> + <div class="row" id="geoipdb-screen1"> + <div class="geoipdb-column-1 col s6"> + <p>{{ 'UserCountry_IWantToDownloadFreeGeoIP'|translate|raw }}</p> + </div> + <div class="geoipdb-column-2 col s6"> + <p>{{ 'UserCountry_IPurchasedGeoIPDBs'|translate('<a href="http://www.maxmind.com/en/geolocation_landing?rId=piwik">','</a>')|raw }}</p> + </div> + <div class="geoipdb-column-1 col s6"> + <input type="button" class="btn" + ng-click="locationUpdater.startDownloadFreeGeoIp()" + value="{{ 'General_GetStarted'|translate }}..."/> + </div> + <div class="geoipdb-column-2 col s6"> + <input type="button" class="btn" + ng-click="locationUpdater.startAutomaticUpdateGeoIp()" + value="{{ 'General_GetStarted'|translate }}..." id="start-automatic-update-geoip"/> + </div> </div> </div> </div> - </div> - <div id="geoipdb-screen2-download" ng-show="locationUpdater.showFreeDownload"> - <div piwik-progressbar - label="{{ ('UserCountry_DownloadingDb'|translate('<a href="'~geoLiteUrl~'">'~geoLiteFilename~'</a>') ~ '...')|json_encode }}" - progress="locationUpdater.progressFreeDownload"> + <div id="geoipdb-screen2-download" ng-show="locationUpdater.showFreeDownload"> + <div piwik-progressbar + label="{{ ('UserCountry_DownloadingDb'|translate('<a href="'~geoLiteUrl~'">'~geoLiteFilename~'</a>') ~ '...')|json_encode }}" + progress="locationUpdater.progressFreeDownload"> + </div> </div> </div> - </div> - {% endif %} + {% endif %} - {% include "@UserCountry/_updaterManage.twig" %} - {% else %} - <p class="form-description">{{ 'UserCountry_CannotSetupGeoIPAutoUpdating'|translate }}</p> - {% endif %} + {% include "@UserCountry/_updaterManage.twig" %} + {% else %} + <p class="form-description">{{ 'UserCountry_CannotSetupGeoIPAutoUpdating'|translate }}</p> + {% endif %} + </div> </div> -</div> +{% endif %} {% endblock %} diff --git a/tests/UI/expected-screenshots/UIIntegrationTest_admin_plugins_no_internet.png b/tests/UI/expected-screenshots/UIIntegrationTest_admin_plugins_no_internet.png new file mode 100644 index 0000000000..a39c085936 --- /dev/null +++ b/tests/UI/expected-screenshots/UIIntegrationTest_admin_plugins_no_internet.png @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:5c91ea1df0d14cedc89eb0a76aac1a08a0619657b0b8353b68d9ece8a186b826 +size 1026600 diff --git a/tests/UI/specs/UIIntegration_spec.js b/tests/UI/specs/UIIntegration_spec.js index 4321882870..2100dfad4a 100644 --- a/tests/UI/specs/UIIntegration_spec.js +++ b/tests/UI/specs/UIIntegration_spec.js @@ -33,6 +33,9 @@ describe("UIIntegrationTest", function () { // TODO: Rename to Piwik? if (testEnvironment.configOverride.database) { delete testEnvironment.configOverride.database; } + if (testEnvironment.configOverride.General) { + delete testEnvironment.configOverride.General; + } testEnvironment.testUseMockAuth = 1; testEnvironment.save(); }); @@ -551,6 +554,17 @@ describe("UIIntegrationTest", function () { // TODO: Rename to Piwik? }, done); }); + it('should load the plugins admin page correctly', function (done) { + testEnvironment.overrideConfig('General', { + enable_internet_features: 0 + }); + testEnvironment.save(); + + expect.screenshot('admin_plugins_no_internet').to.be.captureSelector('.pageWrap', function (page) { + page.load("?" + generalParams + "&module=CorePluginsAdmin&action=plugins"); + }, done); + }); + it('should load the config file page correctly', function (done) { expect.screenshot('admin_diagnostics_configfile').to.be.captureSelector('.pageWrap', function (page) { page.load("?" + generalParams + "&module=Diagnostics&action=configfile"); |