Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
30 changes: 11 additions & 19 deletions API.php
Original file line number Diff line number Diff line change
Expand Up @@ -10,36 +10,31 @@
namespace Piwik\Plugins\OpenApiDocs;

use Piwik\Piwik;
use Piwik\Plugins\OpenApiDocs\Generation\PluginListProvider;
use Piwik\Plugin\Manager;
use Piwik\Plugins\OpenApiDocs\Specs\SpecGenerator;
use Piwik\Plugins\OpenApiDocs\Specs\PathResolver;

/**
* Provides Reporting API endpoints for reading OpenAPI plugin configuration and specifications.
*
* Exposes endpoints to return the configured plugin whitelist, read pre-generated spec files,
* Exposes endpoints to return the effective plugin list for spec generation, read pre-generated spec files,
* or generate plugin OpenAPI specifications on demand.
*
* @method static \Piwik\Plugins\OpenApiDocs\API getInstance()
*/
class API extends \Piwik\Plugin\API
{
/**
* Returns the plugin names configured for OpenApiDocs spec generation.
* Returns the plugin names used for OpenApiDocs spec generation.
*
* @return array<int, string> The configured whitelist of plugin names from
* `config/plugins.php`.
* @return array<int, string>
*/
public function getPluginWhitelist(): array
public function getAllowedPlugins(): array
{
Piwik::checkUserHasSomeViewAccess();

$pluginWhitelist = $this->loadPluginWhitelist();
if (!is_array($pluginWhitelist)) {
throw new \Exception('OpenApiDocs plugin whitelist config is invalid.');
}

return $pluginWhitelist;
return $this->getPluginListProvider()->getAllowedPlugins();
}

/**
Expand Down Expand Up @@ -88,14 +83,6 @@ protected function getSpecFilePath(string $pluginName): string
return $this->getSpecPathResolver()->getSpecFilePath($pluginName);
}

/**
* @return mixed
*/
protected function loadPluginWhitelist()
{
return require __DIR__ . '/config/plugins.php';
}

protected function isSpecFileReadable(string $filePath): bool
{
return is_file($filePath) && is_readable($filePath);
Expand Down Expand Up @@ -127,6 +114,11 @@ protected function getSpecPathResolver(): PathResolver
return new PathResolver();
}

protected function getPluginListProvider(): PluginListProvider
{
return new PluginListProvider();
}

/**
* Generates an OpenAPI specification for one or more plugins and returns it immediately.
*
Expand Down
73 changes: 73 additions & 0 deletions Generation/PluginListProvider.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,73 @@
<?php

/**
* Matomo - free/libre analytics platform
*
* @link https://matomo.org
* @license https://www.gnu.org/licenses/gpl-3.0.html GPL v3 or later
*/

declare(strict_types=1);

namespace Piwik\Plugins\OpenApiDocs\Generation;

use Piwik\Piwik;
use Piwik\Plugin\Manager;

class PluginListProvider
{
/**
* @var Manager
*/
private $pluginManager;

public function __construct(?Manager $pluginManager = null)
{
$this->pluginManager = $pluginManager ?? Manager::getInstance();
}

/**
* @return string[]
*/
public function getAllowedPlugins(): array
{
$pluginNames = array_values($this->pluginManager->getActivatedPlugins());

$this->dispatchUpdatePluginListEvent($pluginNames);

$pluginNames = array_values(array_unique($pluginNames));

return array_values(array_filter($pluginNames, function ($pluginName): bool {
return is_string($pluginName) && $this->shouldIncludeEventProvidedPlugin($pluginName);
}));
}

private function shouldIncludeEventProvidedPlugin(string $pluginName): bool
{
if (!$this->pluginManager->isPluginInFilesystem($pluginName)) {
return false;
}
return $this->pluginHasApiFile($pluginName);
}

protected function pluginHasApiFile(string $pluginName): bool
{
return is_file(Manager::getPluginDirectory($pluginName) . '/API.php');
}

/**
* @param string[] $pluginNames
*/
private function dispatchUpdatePluginListEvent(array &$pluginNames): void
{
$this->postEvent('OpenApiDocs.updatePluginList', [&$pluginNames]);
}

/**
* @param array<int, mixed> $params
*/
protected function postEvent(string $eventName, array $params): void
{
Piwik::postEvent($eventName, $params);
}
}
16 changes: 13 additions & 3 deletions Tasks.php
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,7 @@

use Piwik\Config;
use Piwik\Log\LoggerInterface;
use Piwik\Plugins\OpenApiDocs\Generation\PluginListProvider;
use Piwik\Plugins\OpenApiDocs\Generation\SpecGenerationService;

class Tasks extends \Piwik\Plugin\Tasks
Expand All @@ -27,10 +28,19 @@ class Tasks extends \Piwik\Plugin\Tasks
*/
private $logger;

public function __construct(SpecGenerationService $specGenerationService, LoggerInterface $logger)
{
/**
* @var PluginListProvider
*/
private $pluginListProvider;

public function __construct(
SpecGenerationService $specGenerationService,
LoggerInterface $logger,
?PluginListProvider $pluginListProvider = null
) {
$this->specGenerationService = $specGenerationService;
$this->logger = $logger;
$this->pluginListProvider = $pluginListProvider ?? new PluginListProvider();
}

public function schedule()
Expand All @@ -42,7 +52,7 @@ public function schedule()

public function generateConfiguredPluginSpecs(): void
{
$pluginNames = require __DIR__ . '/config/plugins.php';
Comment thread
lachiebol marked this conversation as resolved.
$pluginNames = $this->pluginListProvider->getAllowedPlugins();

foreach ($pluginNames as $pluginName) {
try {
Expand Down
74 changes: 0 additions & 74 deletions config/plugins.php

This file was deleted.

27 changes: 9 additions & 18 deletions tests/Unit/APITest.php
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,7 @@
use Piwik\Access;
use Piwik\Container\StaticContainer;
use Piwik\Plugins\OpenApiDocs\API;
use Piwik\Plugins\OpenApiDocs\Generation\PluginListProvider;
use Piwik\Plugins\OpenApiDocs\Specs\PathResolver;
use Piwik\Tests\Framework\Mock\FakeAccess;

Expand Down Expand Up @@ -61,29 +62,19 @@ public function testGetOpenApiSpecReturnsDecodedJsonForPlugin()
$this->assertSame($expectedSpec, $result);
}

public function testGetPluginWhitelistReturnsConfigValuesInOrder()
public function testGetAllowedPluginsReturnsProviderValues(): void
{
$expectedWhitelist = ['RollUpReporting', 'Login', 'ActivityLog'];
$provider = $this->createMock(PluginListProvider::class);
$provider->expects($this->once())
->method('getAllowedPlugins')
->willReturn(['Login', 'ActivityLog']);

$api = $this->getMockBuilder(API::class)
->onlyMethods(['loadPluginWhitelist'])
->onlyMethods(['getPluginListProvider'])
->getMock();
$api->method('loadPluginWhitelist')->willReturn($expectedWhitelist);
$api->method('getPluginListProvider')->willReturn($provider);

$this->assertSame($expectedWhitelist, $api->getPluginWhitelist());
}

public function testGetPluginWhitelistThrowsExceptionWhenConfigIsInvalid()
{
$api = $this->getMockBuilder(API::class)
->onlyMethods(['loadPluginWhitelist'])
->getMock();
$api->method('loadPluginWhitelist')->willReturn('invalid');

$this->expectException(\Exception::class);
$this->expectExceptionMessage('OpenApiDocs plugin whitelist config is invalid.');

$api->getPluginWhitelist();
$this->assertSame(['Login', 'ActivityLog'], $api->getAllowedPlugins());
}

public function testGetOpenApiSpecThrowsExceptionWhenFileMissing()
Expand Down
Loading
Loading