Skip to content

Commit dd13be5

Browse files
authored
Added ability to add documentation for inactive plugins, PG-4593 (#23)
* inactive plugins now can have generated specs * changelog * Added guards for cloud plugins * Added extra plugins and made const
1 parent 5cfce34 commit dd13be5

5 files changed

Lines changed: 46 additions & 21 deletions

File tree

Annotations/AnnotationGenerator.php

Lines changed: 29 additions & 18 deletions
Original file line numberDiff line numberDiff line change
@@ -15,6 +15,7 @@
1515
use Matomo\Dependencies\OpenApiDocs\phpDocumentor\Reflection\DocBlock\Tags\Param;
1616
use Matomo\Dependencies\OpenApiDocs\phpDocumentor\Reflection\DocBlock\Tags\TagWithType;
1717
use Matomo\Dependencies\OpenApiDocs\phpDocumentor\Reflection\DocBlockFactory;
18+
use Piwik\Exception\PluginNotFoundException;
1819
use Piwik\API\DocumentationGenerator;
1920
use Piwik\API\NoDefaultValue;
2021
use Piwik\API\Proxy;
@@ -98,13 +99,20 @@ public function __construct(DocumentationGenerator $generator)
9899
*
99100
* @return string[]|array[] The collection of all the lines which make up the generated annotations for the public API
100101
* endpoints defined by the plugin.
101-
* @throws \Piwik\Exception\PluginDeactivatedException If the plugin is not activated. It should be loaded.
102+
* @throws PluginNotFoundException If the plugin is not present in the filesystem.
102103
* @throws \Throwable
103104
*/
104105
public function generatePluginApiAnnotations(string $pluginName, bool $writeToFile = false): array
105106
{
106107
BaseValidator::check('plugin', $pluginName, [new NotEmpty()]);
107-
Manager::getInstance()->checkIsPluginActivated($pluginName);
108+
109+
if (in_array($pluginName, OpenApiDocs::PLUGIN_BLOCKLIST, true)) {
110+
throw new \RuntimeException('OpenAPI doc generation is blocked for ' . $pluginName . '.');
111+
}
112+
113+
if (!Manager::getInstance()->isPluginInFilesystem($pluginName)) {
114+
throw new PluginNotFoundException($pluginName);
115+
}
108116

109117
$rules = require $this->currentPluginDir . '/Annotations/config.php';
110118
$pluginAnnotationDir = $this->currentPluginDir . OpenApiDocs::GENERATED_ANNOTATIONS_PATH;
@@ -1180,24 +1188,27 @@ protected function determineResponses(array $rules, string $plugin, string $meth
11801188
$responseSchema = !empty($responseInfo['type']) ? $this->buildSchemaObjectArray($responseInfo['type']) : [];
11811189

11821190
$mediaTypes = [];
1183-
// This simply reuses the example URLs used by the current documentation, but some endpoints don't work because authentication is required
1184-
$exampleUrls = $this->getApplicableDemoExampleUrls($plugin, $method, $paramsData);
1185-
foreach ($exampleUrls as $type => $url) {
1186-
$exampleValue = $this->getExampleIfAvailable($url);
1187-
// If the example lookup failed, try making the same request locally using a local token.
1188-
if (empty($exampleValue)) {
1189-
$exampleValue = $this->getExampleIfAvailable($url, true);
1190-
}
1191-
if (strlen($exampleValue) > self::EXAMPLE_CHAR_LIMIT) {
1192-
$exampleValue = $this->cutExampleCloseToCharLimit($exampleValue, $type);
1193-
}
1191+
$exampleUrls = [];
1192+
if (Manager::getInstance()->isPluginActivated($plugin)) {
1193+
// Only fetch live examples for activated plugins since their endpoints can be executed safely.
1194+
$exampleUrls = $this->getApplicableDemoExampleUrls($plugin, $method, $paramsData);
1195+
foreach ($exampleUrls as $type => $url) {
1196+
$exampleValue = $this->getExampleIfAvailable($url);
1197+
// If the example lookup failed, try making the same request locally using a local token.
1198+
if (empty($exampleValue)) {
1199+
$exampleValue = $this->getExampleIfAvailable($url, true);
1200+
}
1201+
if (strlen($exampleValue) > self::EXAMPLE_CHAR_LIMIT) {
1202+
$exampleValue = $this->cutExampleCloseToCharLimit($exampleValue, $type);
1203+
}
11941204

1195-
// Skip if there was no example response
1196-
if (empty($exampleValue)) {
1197-
continue;
1198-
}
1205+
// Skip if there was no example response
1206+
if (empty($exampleValue)) {
1207+
continue;
1208+
}
11991209

1200-
$mediaTypes[] = $this->buildMediaTypePropertiesArray($type, $exampleValue, $responseSchema);
1210+
$mediaTypes[] = $this->buildMediaTypePropertiesArray($type, $exampleValue, $responseSchema);
1211+
}
12011212
}
12021213

12031214
// Check if any example files exist even though there aren't any example URLs

Annotations/ApiMethodInfoExtractor.php

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -11,6 +11,7 @@
1111

1212
namespace Piwik\Plugins\OpenApiDocs\Annotations;
1313

14+
use Piwik\Exception\PluginNotFoundException;
1415
use Piwik\API\Proxy;
1516
use Piwik\API\Request;
1617
use Piwik\Plugin\Manager;
@@ -42,7 +43,9 @@ public function extractMethodInfo(string $pluginName, bool $writeToFile = false)
4243
$methodInfoArray = [];
4344
foreach ($pluginNames as $plugin) {
4445
BaseValidator::check('pluginName', $plugin, [new NotEmpty()]);
45-
Manager::getInstance()->checkIsPluginActivated($plugin);
46+
if (!Manager::getInstance()->isPluginInFilesystem($plugin)) {
47+
throw new PluginNotFoundException($plugin);
48+
}
4649

4750
$className = Request::getClassNameAPI($plugin);
4851

CHANGELOG.md

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,7 @@
33
5.0.2-b1 - 2026-03-16
44
- Added support for string literal union types
55
- Added API endpoint to retrieve static matomo swagger file
6+
- Added support for deactivated plugins
67

78
5.0.1-b1 - 2026-02-16
89
- Added class and function level docs

OpenApiDocs.php

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -18,6 +18,7 @@ class OpenApiDocs extends \Piwik\Plugin
1818
public const EXAMPLE_RESPONSES_PATH = '/tmp/responses/';
1919
public const GENERATED_SPECS_PATH = '/tmp/specs/';
2020
public const AVAILABLE_PROPERTY_TYPES = ['string', 'number', 'integer', 'boolean', 'array', 'object', 'null'];
21+
public const PLUGIN_BLOCKLIST = ['Billing', 'Cloud', 'ConnectAccounts', 'CDN', 'ProxySite'];
2122

2223
public function registerEvents()
2324
{

Specs/SpecGenerator.php

Lines changed: 11 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -12,6 +12,7 @@
1212
use Matomo\Dependencies\OpenApiDocs\OpenApi\Annotations\OpenApi;
1313
use Matomo\Dependencies\OpenApiDocs\OpenApi\Generator;
1414
use Piwik\Container\StaticContainer;
15+
use Piwik\Exception\PluginNotFoundException;
1516
use Piwik\Log\LoggerInterface;
1617
use Piwik\Log\NullLogger;
1718
use Piwik\Plugin\Manager;
@@ -45,6 +46,12 @@ public function generatePluginDoc(string $pluginName, string $format = 'json', s
4546
{
4647
BaseValidator::check('plugin', $pluginName, [new NotEmpty()]);
4748

49+
foreach (explode(',', $pluginName) as $currentPluginName) {
50+
if (in_array($currentPluginName, OpenApiDocs::PLUGIN_BLOCKLIST, true)) {
51+
throw new \RuntimeException('OpenAPI doc generation is blocked for ' . $currentPluginName . '.');
52+
}
53+
}
54+
4855
return $this->generateSpec(explode(',', $pluginName), $format, $version, $writeToFile);
4956
}
5057

@@ -59,7 +66,7 @@ public function generatePluginDoc(string $pluginName, string $format = 'json', s
5966
* @return string
6067
* @throws \Piwik\Exception\DI\DependencyException
6168
* @throws \Piwik\Exception\DI\NotFoundException
62-
* @throws \Piwik\Exception\PluginDeactivatedException
69+
* @throws PluginNotFoundException
6370
* @throws \Exception
6471
*/
6572
public function generateSpec(array $pluginNames, string $format = 'json', string $version = OpenApiDocs::DEFAULT_SPEC_VERSION, bool $writeToFile = false): string
@@ -70,7 +77,9 @@ public function generateSpec(array $pluginNames, string $format = 'json', string
7077
$pluginDirs = [];
7178
foreach ($pluginNames as $pluginName) {
7279
BaseValidator::check('pluginName', $pluginName, [new NotEmpty()]);
73-
Manager::getInstance()->checkIsPluginActivated($pluginName);
80+
if (!Manager::getInstance()->isPluginInFilesystem($pluginName)) {
81+
throw new PluginNotFoundException($pluginName);
82+
}
7483

7584
$pluginAnnotationsSource = $currentPluginDir . '/tmp/annotations/' . $pluginName . 'GeneratedAnnotations.php';
7685
try {

0 commit comments

Comments
 (0)