Skip to content

Commit

Permalink
Support multiple plugin paths (matomo-org#14051)
Browse files Browse the repository at this point in the history
* do not hard code plugins directory

* remove method that is not needed for now

* use plugins directory in more places

* some work on supporting multiple plugin directories

* use more unique name

* couple fixes

* and another fix

* sort plugins

* adjust languagesmanager

* adjust more usages

* Update Manager.php

* adding a plugin to test

* more tests

* make sure plugin resources can be located in custom directory

* adding more tests

* rewrite image paths

* handle more cases

* add tests

* make sure to load plugin

* trying to fix test

* trying it this way

* load plugin

* fix ui test?

* testing if tests succeed this way

* another test

* load custom dir plugin

* load plugin in ui fixture

* change the update statement

* remove update script

* delete column

* fix ui test

* make it work for tests

* fix some tests

* Fix merge.
  • Loading branch information
tsteur authored and diosmosis committed Mar 14, 2019
1 parent d7c9327 commit 6395855
Show file tree
Hide file tree
Showing 67 changed files with 887 additions and 110 deletions.
3 changes: 2 additions & 1 deletion CHANGELOG.md
Expand Up @@ -7,14 +7,15 @@ The Product Changelog at **[matomo.org/changelog](https://matomo.org/changelog)*
## Matomo 3.9.0

### Breaking Changes

* `Referrers.getKeywordsForPageUrl` and `Referrers.getKeywordsForPageTitle` APIs have been deprecated and will be removed in Matomo 4.0.0
* By default, Matomo [application logs](https://matomo.org/faq/troubleshooting/faq_115/) will now be logged in `tmp/logs/matomo.log` instead of `tmp/logs/piwik.log`. This log file path can be edited in your config/config.ini.php in the INI setting `logger_file_path`.

### New Features
* It is now possible to locate plugins in a custom directory by setting an environment variable `MATOMO_PLUGIN_DIRS` or a `$GLOBALS['MATOMO_PLUGIN_DIRS']` variable in `$MATOMO_ROOT/bootstrap.php`.
* It is now possible to use monolog's FingersCrossedHandler which buffers all logs and logs all of them in case of warning or error.

### New APIs
* New API methods `Piwik\Plugin\Manager::getPluginsDirectories()` and `Piwik\Plugin\Manager::getPluginDirectory($pluginName)` have been added as it is now possible to locate Matomo plugins in different directories and it should be no longer assumed a plugin is located in the "/plugins" directory.
* A new tracker method `disableQueueRequest` has been added to disable queued requests which may be useful when logs are imported.
* The event `LanguageManager.getAvailableLanguages` has been deprecated. Use `LanguagesManager.getAvailableLanguages` instead.

Expand Down
2 changes: 1 addition & 1 deletion core/API/Proxy.php
Expand Up @@ -442,7 +442,7 @@ private function getRequestParametersArray($requiredParameters, $parametersReque
private function includeApiFile($fileName)
{
$module = self::getModuleNameFromClassName($fileName);
$path = Manager::getPluginsDirectory() . $module . '/API.php';
$path = Manager::getPluginDirectory($module) . '/API.php';

if (is_readable($path)) {
require_once $path; // prefixed by PIWIK_INCLUDE_PATH
Expand Down
19 changes: 18 additions & 1 deletion core/AssetManager/UIAsset/OnDiskUIAsset.php
Expand Up @@ -10,6 +10,7 @@

use Exception;
use Piwik\AssetManager\UIAsset;
use Piwik\Common;
use Piwik\Filesystem;

class OnDiskUIAsset extends UIAsset
Expand All @@ -24,14 +25,27 @@ class OnDiskUIAsset extends UIAsset
*/
private $relativeLocation;

/**
* @var string
*/
private $relativeRootDir;

/**
* @param string $baseDirectory
* @param string $fileLocation
*/
public function __construct($baseDirectory, $fileLocation)
public function __construct($baseDirectory, $fileLocation, $relativeRootDir = '')
{
$this->baseDirectory = $baseDirectory;
$this->relativeLocation = $fileLocation;

if (!empty($relativeRootDir)
&& is_string($relativeRootDir)
&& !Common::stringEndsWith($relativeRootDir, '/')) {
$relativeRootDir .= '/';
}

$this->relativeRootDir = $relativeRootDir;
}

public function getAbsoluteLocation()
Expand All @@ -41,6 +55,9 @@ public function getAbsoluteLocation()

public function getRelativeLocation()
{
if (isset($this->relativeRootDir)) {
return $this->relativeRootDir . $this->relativeLocation;
}
return $this->relativeLocation;
}

Expand Down
33 changes: 32 additions & 1 deletion core/AssetManager/UIAssetFetcher.php
Expand Up @@ -9,6 +9,7 @@
namespace Piwik\AssetManager;

use Piwik\AssetManager\UIAsset\OnDiskUIAsset;
use Piwik\Plugin\Manager;
use Piwik\Theme;

abstract class UIAssetFetcher
Expand Down Expand Up @@ -89,9 +90,39 @@ private function initCatalog()

private function populateCatalog()
{
$pluginBaseDir = Manager::getPluginsDirectory();
$pluginWebDirectories = Manager::getAlternativeWebRootDirectories();
$matomoRootDir = $this->getBaseDirectory();

foreach ($this->fileLocations as $fileLocation) {
$fileAbsolute = $matomoRootDir . '/' . $fileLocation;

$newUIAsset = new OnDiskUIAsset($this->getBaseDirectory(), $fileLocation);
$this->catalog->addUIAsset($newUIAsset);
if ($newUIAsset->exists()) {
$this->catalog->addUIAsset($newUIAsset);
continue;
}

$found = false;

if (strpos($fileAbsolute, $pluginBaseDir) === 0) {
// we iterate over all custom plugin directories only for plugin files, not libs files (not needed there)
foreach ($pluginWebDirectories as $pluginDirectory => $relative) {
$fileTest = str_replace($pluginBaseDir, $pluginDirectory, $fileAbsolute);
$newFileRelative = str_replace($pluginDirectory, '', $fileTest);
$testAsset = new OnDiskUIAsset($pluginDirectory, $newFileRelative, $relative);
if ($testAsset->exists()) {
$this->catalog->addUIAsset($testAsset);
$found = true;
break;
}
}
}

if (!$found) {
// we add it anyway so it'll trigger an error about the missing file
$this->catalog->addUIAsset($newUIAsset);
}
}
}

Expand Down
36 changes: 32 additions & 4 deletions core/AssetManager/UIAssetMerger/StylesheetUIAssetMerger.php
Expand Up @@ -15,6 +15,7 @@
use Piwik\Common;
use Piwik\Exception\StylesheetLessCompileException;
use Piwik\Piwik;
use Piwik\Plugin\Manager;

class StylesheetUIAssetMerger extends UIAssetMerger
{
Expand Down Expand Up @@ -191,8 +192,9 @@ private function rewriteCssImportPaths($content, $pathsRewriter)
private function getCssPathsRewriter($uiAsset)
{
$baseDirectory = dirname($uiAsset->getRelativeLocation());
$webDirs = Manager::getAlternativeWebRootDirectories();

return function ($matches) use ($baseDirectory) {
return function ($matches) use ($baseDirectory, $webDirs) {
$absolutePath = PIWIK_DOCUMENT_ROOT . "/$baseDirectory/" . $matches[2];

// Allow to import extension less file
Expand All @@ -201,13 +203,39 @@ private function getCssPathsRewriter($uiAsset)
}

// Prevent from rewriting full path
$absolutePath = realpath($absolutePath);
if ($absolutePath) {
$absolutePathReal = realpath($absolutePath);
if ($absolutePathReal) {
$relativePath = $baseDirectory . "/" . $matches[2];
$relativePath = str_replace('\\', '/', $relativePath);
$publicPath = $matches[1] . $relativePath;
} else {
$publicPath = $matches[1] . $matches[2];
foreach ($webDirs as $absPath => $relativePath) {
if (strpos($baseDirectory, $relativePath) === 0) {
if (strpos($matches[2], '.') === 0) {
// eg ../images/ok.png
$fileRelative = $baseDirectory . '/' . $matches[2];
$fileAbsolute = $absPath . str_replace($relativePath, '', $fileRelative);
if (file_exists($fileAbsolute)) {
return $matches[1] . $fileRelative;
}
} elseif (strpos($matches[2], 'plugins/') === 0) {
// eg plugins/Foo/images/ok.png
$fileRelative = substr($matches[2], strlen('plugins/'));
$fileAbsolute = $absPath . $fileRelative;
if (file_exists($fileAbsolute)) {
return $matches[1] . $relativePath . $fileRelative;
}
} elseif ($matches[1] === '@import "') {
$fileRelative = $baseDirectory . '/' . $matches[2];
$fileAbsolute = $absPath . str_replace($relativePath, '', $fileRelative);
if (file_exists($fileAbsolute)) {
return $matches[1] . $baseDirectory . '/' . $matches[2];
}
}
}
}

$publicPath = $matches[1] . $matches[2];
}

return $publicPath;
Expand Down
10 changes: 6 additions & 4 deletions core/Columns/Updater.php
Expand Up @@ -342,11 +342,13 @@ public function onNoUpdateAvailable($versionsThatWereChecked)

private static function getCurrentDimensionFileChanges()
{
$files = Filesystem::globr(Manager::getPluginsDirectory() . '*/Columns', '*.php');

$times = array();
foreach ($files as $file) {
$times[$file] = filemtime($file);
foreach (Manager::getPluginsDirectories() as $pluginsDir) {
$files = Filesystem::globr($pluginsDir . '*/Columns', '*.php');

foreach ($files as $file) {
$times[$file] = filemtime($file);
}
}

return $times;
Expand Down
4 changes: 2 additions & 2 deletions core/Container/ContainerFactory.php
Expand Up @@ -121,7 +121,7 @@ private function addEnvironmentConfig(ContainerBuilder $builder, $environment)
// add plugin environment configs
$plugins = $this->pluginList->getActivatedPlugins();
foreach ($plugins as $plugin) {
$baseDir = Manager::getPluginsDirectory() . $plugin;
$baseDir = Manager::getPluginDirectory($plugin);

$environmentFile = $baseDir . '/config/' . $environment . '.php';
if (file_exists($environmentFile)) {
Expand All @@ -135,7 +135,7 @@ private function addPluginConfigs(ContainerBuilder $builder)
$plugins = $this->pluginList->getActivatedPlugins();

foreach ($plugins as $plugin) {
$baseDir = Manager::getPluginsDirectory() . $plugin;
$baseDir = Manager::getPluginDirectory($plugin);

$file = $baseDir . '/config/config.php';
if (file_exists($file)) {
Expand Down
9 changes: 5 additions & 4 deletions core/Plugin.php
Expand Up @@ -355,9 +355,9 @@ public function findComponent($componentName, $expectedSubclass)

$cacheId = 'Plugin' . $this->pluginName . $componentName . $expectedSubclass;

$pluginsDir = Manager::getPluginsDirectory();
$pluginsDir = Manager::getPluginDirectory($this->pluginName);

$componentFile = sprintf('%s%s/%s.php', $pluginsDir, $this->pluginName, $componentName);
$componentFile = sprintf('%s/%s.php', $pluginsDir, $componentName);

if ($this->cache->contains($cacheId)) {
$classname = $this->cache->fetch($cacheId);
Expand Down Expand Up @@ -537,8 +537,9 @@ private function doFindMultipleComponents($directoryWithinPlugin, $expectedSubcl
{
$components = array();

$pluginsDir = Manager::getPluginsDirectory();
$baseDir = $pluginsDir . $this->pluginName . '/' . $directoryWithinPlugin;
$pluginsDir = Manager::getPluginDirectory($this->pluginName);
$baseDir = $pluginsDir . '/' . $directoryWithinPlugin;

$files = Filesystem::globr($baseDir, '*.php');

foreach ($files as $file) {
Expand Down
5 changes: 5 additions & 0 deletions core/Plugin/ArchivedMetric.php
Expand Up @@ -64,6 +64,11 @@ public function __construct(Dimension $dimension, $aggregation = false)
$this->aggregation = $aggregation;
}

public function getAggregation()
{
return $this->aggregation;
}

public function setDimension($dimension)
{
$this->dimension = $dimension;
Expand Down

0 comments on commit 6395855

Please sign in to comment.