diff options
author | Thomas Steur <tsteur@users.noreply.github.com> | 2016-11-15 04:03:59 +0300 |
---|---|---|
committer | Matthieu Aubry <mattab@users.noreply.github.com> | 2016-11-15 04:03:59 +0300 |
commit | 587cc39e0362719332d410b7a4d5ddcc68788eeb (patch) | |
tree | c982c369cdda542c3a4de08be11c893e5364838c /core | |
parent | 64314b26dbc6619d535002bdb79b9e55d1fc87db (diff) |
Update Marketplace to work with new API (#10799)
* starting to port marketplace to piwik 3
* updating tests
* fix translation key
* fix various issues
* use material select
* fix plugin upload
* deprecate license_homepage plugin metadata and link to a LICENSE[.md|.txt] file if found (#10756)
* deprecate license_homepage plugin metadata, and link to a LICENSE[.md|.txt] file if found
* Make license view HTML only without menu
* fix tests and update
* fix some links did not work
* we need to show warnings even when plugin is installed, not only when activated. otherwise it is not clear why something is not downloadable
* fix install was not working
* improved responsiveness of marketplace
* fix more tests
* fix search was shown when only a few plugins are there
* fix ui tests
* fix some translations
* fix tests and remove duplicated test
Diffstat (limited to 'core')
-rw-r--r-- | core/API/DocumentationGenerator.php | 2 | ||||
-rw-r--r-- | core/Http.php | 15 | ||||
-rw-r--r-- | core/Notification.php | 7 | ||||
-rw-r--r-- | core/Plugin.php | 2 | ||||
-rw-r--r-- | core/Plugin/ControllerAdmin.php | 47 | ||||
-rw-r--r-- | core/Plugin/Dependency.php | 81 | ||||
-rw-r--r-- | core/Plugin/Manager.php | 9 | ||||
-rw-r--r-- | core/Plugin/MetadataLoader.php | 37 | ||||
-rw-r--r-- | core/Plugin/ReleaseChannels.php | 12 | ||||
-rw-r--r-- | core/ProxyHttp.php | 12 | ||||
-rw-r--r-- | core/SettingsPiwik.php | 37 | ||||
-rwxr-xr-x | core/Twig.php | 26 | ||||
-rw-r--r-- | core/UpdateCheck.php | 7 | ||||
-rw-r--r-- | core/UpdateCheck/ReleaseChannel.php | 9 | ||||
-rw-r--r-- | core/Updates/3.0.0-b2.php | 24 | ||||
-rw-r--r-- | core/Updates/3.0.0-b3.php | 65 | ||||
-rw-r--r-- | core/View.php | 2 |
17 files changed, 342 insertions, 52 deletions
diff --git a/core/API/DocumentationGenerator.php b/core/API/DocumentationGenerator.php index 456e487f00..e738c6c4c8 100644 --- a/core/API/DocumentationGenerator.php +++ b/core/API/DocumentationGenerator.php @@ -285,6 +285,8 @@ class DocumentationGenerator 'addGoal', 'updateGoal', 'deleteGoal', + //Marketplace + 'deleteLicenseKey' ); if (in_array($methodName, $doNotPrintExampleForTheseMethods)) { diff --git a/core/Http.php b/core/Http.php index 7e7602c20e..373c4815d9 100644 --- a/core/Http.php +++ b/core/Http.php @@ -94,17 +94,24 @@ class Http $httpPassword = null) { // create output file - $file = null; + $file = self::ensureDestinationDirectoryExists($destinationPath); + + $acceptLanguage = $acceptLanguage ? 'Accept-Language: ' . $acceptLanguage : ''; + return self::sendHttpRequestBy(self::getTransportMethod(), $aUrl, $timeout, $userAgent, $destinationPath, $file, $followDepth, $acceptLanguage, $acceptInvalidSslCertificate = false, $byteRange, $getExtendedInfo, $httpMethod, $httpUsername, $httpPassword); + } + + public static function ensureDestinationDirectoryExists($destinationPath) + { if ($destinationPath) { - // Ensure destination directory exists Filesystem::mkdir(dirname($destinationPath)); if (($file = @fopen($destinationPath, 'wb')) === false || !is_resource($file)) { throw new Exception('Error while creating the file: ' . $destinationPath); } + + return $file; } - $acceptLanguage = $acceptLanguage ? 'Accept-Language: ' . $acceptLanguage : ''; - return self::sendHttpRequestBy(self::getTransportMethod(), $aUrl, $timeout, $userAgent, $destinationPath, $file, $followDepth, $acceptLanguage, $acceptInvalidSslCertificate = false, $byteRange, $getExtendedInfo, $httpMethod, $httpUsername, $httpPassword); + return null; } /** diff --git a/core/Notification.php b/core/Notification.php index b7c576eba0..7672263ab3 100644 --- a/core/Notification.php +++ b/core/Notification.php @@ -81,6 +81,13 @@ class Notification const FLAG_NO_CLEAR = 1; /** + * If this flag is applied, a close icon will be displayed. + * + * See {@link $flags}. + */ + const FLAG_CLEAR = 0; + + /** * Notifications of this type will be displayed for a few seconds and then faded out. */ const TYPE_TOAST = 'toast'; diff --git a/core/Plugin.php b/core/Plugin.php index 82ef4f2fec..949895b70e 100644 --- a/core/Plugin.php +++ b/core/Plugin.php @@ -42,7 +42,6 @@ require_once PIWIK_INCLUDE_PATH . '/core/Plugin/MetadataLoader.php'; * - **homepage**: The URL to the plugin's website. * - **authors**: A list of author arrays with keys for 'name', 'email' and 'homepage' * - **license**: The license the code uses (eg, GPL, MIT, etc.). - * - **license_homepage**: URL to website describing the license used. * - **version**: The plugin version (eg, 1.0.1). * - **theme**: `true` or `false`. If `true`, the plugin will be treated as a theme. * @@ -184,7 +183,6 @@ class Plugin * - 'author_homepage' => string // author homepage URL (or email "mailto:youremail@example.org") * - 'homepage' => string // plugin homepage URL * - 'license' => string // plugin license - * - 'license_homepage' => string // license homepage URL * - 'version' => string // plugin version number; examples and 3rd party plugins must not use Version::VERSION; 3rd party plugins must increment the version number with each plugin release * - 'theme' => bool // Whether this plugin is a theme (a theme is a plugin, but a plugin is not necessarily a theme) * diff --git a/core/Plugin/ControllerAdmin.php b/core/Plugin/ControllerAdmin.php index 092a963b8a..73bf47d32b 100644 --- a/core/Plugin/ControllerAdmin.php +++ b/core/Plugin/ControllerAdmin.php @@ -10,12 +10,14 @@ namespace Piwik\Plugin; use Piwik\Config as PiwikConfig; use Piwik\Config; +use Piwik\Container\StaticContainer; use Piwik\Development; use Piwik\Menu\MenuAdmin; use Piwik\Menu\MenuTop; use Piwik\Notification; use Piwik\Notification\Manager as NotificationManager; use Piwik\Piwik; +use Piwik\Plugins\Marketplace\Marketplace; use Piwik\Tracker\TrackerConfig; use Piwik\Url; use Piwik\Version; @@ -40,6 +42,50 @@ abstract class ControllerAdmin extends Controller } } + private static function notifyAnyInvalidLicense() + { + if (!Marketplace::isMarketplaceEnabled()) { + return; + } + + if (Piwik::isUserIsAnonymous()) { + return; + } + + if (!Piwik::isUserHasSomeAdminAccess()) { + 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() { $missingPlugins = \Piwik\Plugin\Manager::getInstance()->getMissingPlugins(); @@ -272,6 +318,7 @@ abstract class ControllerAdmin extends Controller $view->isSuperUser = Piwik::hasUserSuperUserAccess(); + self::notifyAnyInvalidLicense(); self::notifyAnyInvalidPlugin(); self::notifyWhenPhpVersionIsEOL(); self::notifyWhenPhpVersionIsNotCompatibleWithNextMajorPiwik(); diff --git a/core/Plugin/Dependency.php b/core/Plugin/Dependency.php index e1ccc1c92c..127d32eabf 100644 --- a/core/Plugin/Dependency.php +++ b/core/Plugin/Dependency.php @@ -8,7 +8,9 @@ */ namespace Piwik\Plugin; +use Composer\Semver\VersionParser; use Piwik\Plugin\Manager as PluginManager; +use Piwik\Plugins\Marketplace\Environment; use Piwik\Version; /** @@ -17,10 +19,18 @@ use Piwik\Version; class Dependency { private $piwikVersion; + private $phpVersion; public function __construct() { $this->setPiwikVersion(Version::VERSION); + $this->setPhpVersion(PHP_MAJOR_VERSION . '.' . PHP_MINOR_VERSION . '.' . PHP_RELEASE_VERSION); + } + + public function setEnvironment(Environment $environment) + { + $this->setPiwikVersion($environment->getPiwikVersion()); + $this->setPhpVersion($environment->getPhpVersion()); } public function getMissingDependencies($requires) @@ -50,40 +60,91 @@ class Dependency public function getMissingVersions($currentVersion, $requiredVersion) { - $currentVersion = trim($currentVersion); - $requiredVersions = explode(',', (string) $requiredVersion); + $currentVersion = trim($currentVersion); $missingVersions = array(); + if (empty($currentVersion)) { + if (!empty($requiredVersion)) { + $missingVersions[] = (string) $requiredVersion; + } + + return $missingVersions; + } + + $requiredVersion = $this->makeVersionBackwardsCompatibleIfNoComparisonDefined($requiredVersion); + + $version = new VersionParser(); + $constraintsExisting = $version->parseConstraints($currentVersion); + + $requiredVersions = explode(',', (string) $requiredVersion); + foreach ($requiredVersions as $required) { - $comparison = '>='; - $required = trim($required); + $required = trim($required); - if (preg_match('{^(<>|!=|>=?|<=?|==?)\s*(.*)}', $required, $matches)) { - $required = $matches[2]; - $comparison = trim($matches[1]); + if (empty($required)) { + continue; } - if (false === version_compare($currentVersion, $required, $comparison)) { - $missingVersions[] = $comparison . $required; + $required = $this->makeVersionBackwardsCompatibleIfNoComparisonDefined($required); + $constraintRequired = $version->parseConstraints($required); + + if (!$constraintRequired->matches($constraintsExisting)) { + $missingVersions[] = $required; } } return $missingVersions; } + private function makeVersionBackwardsCompatibleIfNoComparisonDefined($version) + { + if (!empty($version) && preg_match('/^(\d+)\.(\d+)/', $version)) { + // TODO: we should remove this from piwik 3. To stay BC we add >= if no >= is defined yet + $version = '>=' . $version; + } + + return $version; + } + public function setPiwikVersion($piwikVersion) { $this->piwikVersion = $piwikVersion; } + public function setPhpVersion($phpVersion) + { + $this->phpVersion = $phpVersion; + } + + public function hasDependencyToDisabledPlugin($requires) + { + if (empty($requires)) { + return false; + } + + foreach ($requires as $name => $requiredVersion) { + $nameLower = strtolower($name); + $isPluginRequire = !in_array($nameLower, array('piwik', 'php')); + if ($isPluginRequire) { + // we do not check version, only whether it's activated. Everything that is not piwik or php is assumed + // a plugin so far. + if (!PluginManager::getInstance()->isPluginActivated($name)) { + return true; + } + } + } + + return false; + } + private function getCurrentVersion($name) { switch (strtolower($name)) { case 'piwik': return $this->piwikVersion; case 'php': - return PHP_VERSION; + return $this->phpVersion; default: try { $pluginNames = PluginManager::getAllPluginsNames(); diff --git a/core/Plugin/Manager.php b/core/Plugin/Manager.php index 9455f06c0b..846de60086 100644 --- a/core/Plugin/Manager.php +++ b/core/Plugin/Manager.php @@ -658,7 +658,12 @@ class Manager || $name == self::DEFAULT_THEME; } - protected function isPluginThirdPartyAndBogus($pluginName) + /** + * @param $pluginName + * @return bool + * @ignore + */ + public function isPluginThirdPartyAndBogus($pluginName) { if ($this->isPluginBundledWithCore($pluginName)) { return false; @@ -915,7 +920,7 @@ class Manager public function isValidPluginName($pluginName) { - return (bool) preg_match('/^[a-zA-Z]([a-zA-Z0-9]*)$/D', $pluginName); + return (bool) preg_match('/^[a-zA-Z]([a-zA-Z0-9_]*)$/D', $pluginName); } /** diff --git a/core/Plugin/MetadataLoader.php b/core/Plugin/MetadataLoader.php index 5a6b2617e6..bde849ff7e 100644 --- a/core/Plugin/MetadataLoader.php +++ b/core/Plugin/MetadataLoader.php @@ -57,6 +57,12 @@ class MetadataLoader unset($plugin['description']); } + // look for a license file + $licenseFile = $this->getPathToLicenseFile(); + if(!empty($licenseFile)) { + $plugin['license_file'] = $licenseFile; + } + return array_merge( $defaults, $plugin @@ -78,7 +84,6 @@ class MetadataLoader 'homepage' => 'http://piwik.org/', 'authors' => array(array('name' => 'Piwik', 'homepage' => 'http://piwik.org/')), 'license' => 'GPL v3+', - 'license_homepage' => 'http://www.gnu.org/licenses/gpl.html', 'version' => Version::VERSION, 'theme' => false, 'require' => array() @@ -87,7 +92,7 @@ class MetadataLoader private function loadPluginInfoJson() { - $path = \Piwik\Plugin\Manager::getPluginsDirectory() . $this->pluginName . '/' . self::PLUGIN_JSON_FILENAME; + $path = $this->getPathToPluginFolder() . '/' . self::PLUGIN_JSON_FILENAME; return $this->loadJsonMetadata($path); } @@ -111,4 +116,32 @@ class MetadataLoader return $info; } + + /** + * @return string + */ + private function getPathToPluginFolder() + { + return \Piwik\Plugin\Manager::getPluginsDirectory() . $this->pluginName; + } + + /** + * @return null|string + */ + public function getPathToLicenseFile() + { + $prefixPath = $this->getPathToPluginFolder() . '/'; + $licenseFiles = array( + 'LICENSE', + 'LICENSE.md', + 'LICENSE.txt' + ); + foreach ($licenseFiles as $licenseFile) { + $pathToLicense = $prefixPath . $licenseFile; + if (is_file($pathToLicense) && is_readable($pathToLicense)) { + return $pathToLicense; + } + } + return null; + } } diff --git a/core/Plugin/ReleaseChannels.php b/core/Plugin/ReleaseChannels.php index f108a32cdf..08d95d9bb2 100644 --- a/core/Plugin/ReleaseChannels.php +++ b/core/Plugin/ReleaseChannels.php @@ -68,6 +68,18 @@ class ReleaseChannels return reset($channels); } + /** + * Sets the given release channel in config but does not save id. $config->forceSave() still needs to be called + * @internal tests only + * @param string $channel + */ + public function setActiveReleaseChannelId($channel) + { + $general = Config::getInstance()->General; + $general['release_channel'] = $channel; + Config::getInstance()->General = $general; + } + public function isValidReleaseChannelId($releaseChannelId) { $channel = $this->factory($releaseChannelId); diff --git a/core/ProxyHttp.php b/core/ProxyHttp.php index 790d62229d..bf3bbf43e3 100644 --- a/core/ProxyHttp.php +++ b/core/ProxyHttp.php @@ -60,9 +60,12 @@ class ProxyHttp * of the file will be served. * @param int|false $byteEnd The ending byte in the file to serve. If false, the data from $byteStart to the * end of the file will be served. + * @param string|false $filename By default the filename of $file is reused as Content-Disposition. If the + * file should be sent as a different filename to the client you can specify + * a custom filename here. */ public static function serverStaticFile($file, $contentType, $expireFarFutureDays = 100, $byteStart = false, - $byteEnd = false) + $byteEnd = false, $filename = false) { // if the file cannot be found return HTTP status code '404' if (!file_exists($file)) { @@ -78,7 +81,12 @@ class ProxyHttp // set some HTTP response headers self::overrideCacheControlHeaders('public'); Common::sendHeader('Vary: Accept-Encoding'); - Common::sendHeader('Content-Disposition: inline; filename=' . basename($file)); + + if (false === $filename) { + $filename = basename($file); + } + + Common::sendHeader('Content-Disposition: inline; filename=' . $filename); if ($expireFarFutureDays) { // Required by proxy caches potentially in between the browser and server to cache the request indeed diff --git a/core/SettingsPiwik.php b/core/SettingsPiwik.php index c0b2d8e177..52c4f3e16f 100644 --- a/core/SettingsPiwik.php +++ b/core/SettingsPiwik.php @@ -233,6 +233,43 @@ class SettingsPiwik } /** + * Detect whether user has enabled auto updates. Please note this config is a bit misleading. It is currently + * actually used for 2 things: To disable making any connections back to Piwik, and to actually disable the auto + * update of core and plugins. + * @return bool + */ + public static function isAutoUpdateEnabled() + { + return (bool) Config::getInstance()->General['enable_auto_update']; + } + + /** + * Detects whether an auto update can be made. An update is possible if the user is not on multiple servers and if + * automatic updates are actually enabled. If a user is running Piwik on multiple servers an update is not possible + * as it would be installed only on one server instead of all of them. Also if a user has disabled automatic updates + * we cannot perform any automatic updates. + * + * @return bool + */ + public static function isAutoUpdatePossible() + { + return !self::isMultiServerEnvironment() && self::isAutoUpdateEnabled(); + } + + /** + * Returns `true` if Piwik is running on more than one server. For example in a load balanced environment. In this + * case we should not make changes to the config and not install a plugin via the UI as it would be only executed + * on one server. + * @return bool + */ + public static function isMultiServerEnvironment() + { + $is = Config::getInstance()->General['multi_server_environment']; + + return !empty($is); + } + + /** * Returns `true` if segmentation is allowed for this user, `false` if otherwise. * * @return bool diff --git a/core/Twig.php b/core/Twig.php index 5ac84993f1..ce8085f23c 100755 --- a/core/Twig.php +++ b/core/Twig.php @@ -176,6 +176,9 @@ class Twig $this->addFilter_prettyDate(); $this->addFilter_safeDecodeRaw(); $this->addFilter_number(); + $this->addFilter_nonce(); + $this->addFilter_md5(); + $this->addFilter_onlyDomain(); $this->twig->addFilter(new Twig_SimpleFilter('implode', 'implode')); $this->twig->addFilter(new Twig_SimpleFilter('ucwords', 'ucwords')); $this->twig->addFilter(new Twig_SimpleFilter('lcfirst', 'lcfirst')); @@ -428,6 +431,29 @@ class Twig $this->twig->addFilter($formatter); } + protected function addFilter_nonce() + { + $nonce = new Twig_SimpleFilter('nonce', array('Piwik\\Nonce', 'getNonce')); + $this->twig->addFilter($nonce); + } + + private function addFilter_md5() + { + $md5 = new \Twig_SimpleFilter('md5', function ($value) { + return md5($value); + }); + $this->twig->addFilter($md5); + } + + private function addFilter_onlyDomain() + { + $domainOnly = new \Twig_SimpleFilter('domainOnly', function ($url) { + $parsed = parse_url($url); + return $parsed['scheme'] . '://' . $parsed['host']; + }); + $this->twig->addFilter($domainOnly); + } + protected function addFilter_truncate() { $truncateFilter = new Twig_SimpleFilter('truncate', function ($string, $size) { diff --git a/core/UpdateCheck.php b/core/UpdateCheck.php index e2ce130c4a..403fa90b36 100644 --- a/core/UpdateCheck.php +++ b/core/UpdateCheck.php @@ -21,11 +21,6 @@ class UpdateCheck const LATEST_VERSION = 'UpdateCheck_LatestVersion'; const SOCKET_TIMEOUT = 2; - private static function isAutoUpdateEnabled() - { - return (bool) Config::getInstance()->General['enable_auto_update']; - } - /** * Check for a newer version * @@ -34,7 +29,7 @@ class UpdateCheck */ public static function check($force = false, $interval = null) { - if (!self::isAutoUpdateEnabled()) { + if (!SettingsPiwik::isAutoUpdateEnabled()) { return; } diff --git a/core/UpdateCheck/ReleaseChannel.php b/core/UpdateCheck/ReleaseChannel.php index b398ea22c3..0744378623 100644 --- a/core/UpdateCheck/ReleaseChannel.php +++ b/core/UpdateCheck/ReleaseChannel.php @@ -34,6 +34,15 @@ abstract class ReleaseChannel abstract public function getName(); /** + * Whether only stable versions are wanted or also beta versions. + * @return bool + */ + public function doesPreferStable() + { + return true; + } + + /** * Get the latest available version number for this release channel. Eg '2.15.0-b4' or '2.15.0'. Should be * a semantic version number in format MAJOR.MINOR.PATCH (http://semver.org/). Returning an empty string in case * one cannot connect to the remote server can be acceptable. diff --git a/core/Updates/3.0.0-b2.php b/core/Updates/3.0.0-b2.php deleted file mode 100644 index 17c0fce85b..0000000000 --- a/core/Updates/3.0.0-b2.php +++ /dev/null @@ -1,24 +0,0 @@ -<?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\Updates; - -use Piwik\Db; -use Piwik\Plugins\Dashboard; -use Piwik\Updater; -use Piwik\Updater\Migration; -use Piwik\Updates; - -class Updates_3_0_0_b2 extends Updates -{ - public static function isMajorUpdate() - { - return true; - } -} diff --git a/core/Updates/3.0.0-b3.php b/core/Updates/3.0.0-b3.php new file mode 100644 index 0000000000..898f669eeb --- /dev/null +++ b/core/Updates/3.0.0-b3.php @@ -0,0 +1,65 @@ +<?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\Updates; + +use Piwik\Config; +use Piwik\Plugin; +use Piwik\Updater; +use Piwik\Updates as PiwikUpdates; +use Piwik\Updates; + +class Updates_3_0_0_b3 extends Updates +{ + private $marketplaceEnabledConfigSetting = 'enable_marketplace'; + + public static function isMajorUpdate() + { + return true; + } + + public function doUpdate(Updater $updater) + { + $general = $this->getConfig()->General; + + // need to check against int(0) value, as if the config setting is not set at all its value is null + if (isset($general[$this->marketplaceEnabledConfigSetting])) { + $isMarketplaceEnabled = 0 !== $general[$this->marketplaceEnabledConfigSetting]; + + $this->removeOldMarketplaceEnabledConfig(); + + if ($isMarketplaceEnabled) { + $pluginManager = Plugin\Manager::getInstance(); + $pluginName = 'Marketplace'; + + if (!$pluginManager->isPluginActivated($pluginName)) { + $pluginManager->activatePlugin($pluginName); + } + } + } + } + + private function getConfig() + { + return Config::getInstance(); + } + + private function removeOldMarketplaceEnabledConfig() + { + $config = $this->getConfig(); + $general = $config->General; + + if (array_key_exists($this->marketplaceEnabledConfigSetting, $general)) { + unset($general[$this->marketplaceEnabledConfigSetting]); + + $config->General = $general; + $config->forceSave(); + } + } +} diff --git a/core/View.php b/core/View.php index 0c9b379a67..06b6db5f4a 100644 --- a/core/View.php +++ b/core/View.php @@ -87,6 +87,7 @@ if (!defined('PIWIK_USER_PATH')) { * - **isPluginLoaded**: Returns true if the supplied plugin is loaded, false if otherwise. * `{% if isPluginLoaded('Goals') %}...{% endif %}` * - **areAdsForProfessionalServicesEnabled**: Returns true if it is ok to show some advertising in the UI for providers of Professional Support for Piwik (from Piwik 2.16.0) + * - **isMultiServerEnvironment**: Returns true if Piwik is used on more than one server (since Piwik 2.16.1) * * ### Examples * @@ -237,6 +238,7 @@ class View implements ViewInterface $this->latest_version_available = UpdateCheck::isNewestVersionAvailable(); $this->disableLink = Common::getRequestVar('disableLink', 0, 'int'); $this->isWidget = Common::getRequestVar('widget', 0, 'int'); + $this->isMultiServerEnvironment = SettingsPiwik::isMultiServerEnvironment(); $piwikAds = StaticContainer::get('Piwik\ProfessionalServices\Advertising'); $this->areAdsForProfessionalServicesEnabled = $piwikAds->areAdsForProfessionalServicesEnabled(); |