diff --git a/API.php b/API.php
index 9311c6e..7f7ecdb 100644
--- a/API.php
+++ b/API.php
@@ -12,6 +12,7 @@
use Piwik\Piwik;
use Piwik\Plugin\Manager;
use Piwik\Plugins\OpenApiDocs\Specs\SpecGenerator;
+use Piwik\Plugins\OpenApiDocs\Specs\PathResolver;
/**
* API for plugin OpenApiDocs
@@ -67,9 +68,7 @@ public function getOpenApiSpec(string $pluginName, string $format = 'json'): arr
protected function getSpecFilePath(string $pluginName): string
{
- $currentPluginDir = Manager::getInstance()::getPluginDirectory('OpenApiDocs');
-
- return $currentPluginDir . OpenApiDocs::GENERATED_SPECS_PATH . $pluginName . '_openapi_spec_v' . OpenApiDocs::DEFAULT_SPEC_VERSION . '.json';
+ return $this->getSpecPathResolver()->getSpecFilePath($pluginName);
}
protected function isSpecFileReadable(string $filePath): bool
@@ -98,6 +97,11 @@ protected function validateJsonFormat(string $format): void
}
}
+ protected function getSpecPathResolver(): PathResolver
+ {
+ return new PathResolver();
+ }
+
/**
* Get the generated API documentation data for the specified plugin.
*
diff --git a/Annotations/AnnotationGenerator.php b/Annotations/AnnotationGenerator.php
index 96773c9..0a699aa 100644
--- a/Annotations/AnnotationGenerator.php
+++ b/Annotations/AnnotationGenerator.php
@@ -23,7 +23,9 @@
use Piwik\Http;
use Piwik\Piwik;
use Piwik\Plugin\Manager;
+use Piwik\Plugins\OpenApiDocs\Artifact\ArtifactWriter;
use Piwik\Plugins\OpenApiDocs\OpenApiDocs;
+use Piwik\Plugins\OpenApiDocs\Specs\PathResolver;
use Piwik\SettingsPiwik;
use Piwik\Url;
use Piwik\UrlHelper;
@@ -72,6 +74,16 @@ class AnnotationGenerator
*/
protected $generator;
+ /**
+ * @var PathResolver
+ */
+ protected $pathResolver;
+
+ /**
+ * @var ArtifactWriter
+ */
+ protected $artifactWriter;
+
/**
* @var array[]
*/
@@ -82,9 +94,14 @@ class AnnotationGenerator
*/
protected $missingImportantDataWarnings;
- public function __construct(DocumentationGenerator $generator)
- {
+ public function __construct(
+ DocumentationGenerator $generator,
+ ?PathResolver $pathResolver = null,
+ ?ArtifactWriter $artifactWriter = null
+ ) {
$this->generator = $generator;
+ $this->pathResolver = $pathResolver ?? new PathResolver();
+ $this->artifactWriter = $artifactWriter ?? new ArtifactWriter();
$this->missingImportantDataWarnings = [];
$this->currentPluginDir = Manager::getInstance()::getPluginDirectory('OpenApiDocs');
}
@@ -115,8 +132,7 @@ public function generatePluginApiAnnotations(string $pluginName, bool $writeToFi
}
$rules = require $this->currentPluginDir . '/Annotations/config.php';
- $pluginAnnotationDir = $this->currentPluginDir . OpenApiDocs::GENERATED_ANNOTATIONS_PATH;
- $pluginAnnotationPath = $pluginAnnotationDir . "/{$pluginName}GeneratedAnnotations.php";
+ $pluginAnnotationPath = $this->pathResolver->getAnnotationFilePath($pluginName);
$className = Request::getClassNameAPI($pluginName);
@@ -231,8 +247,7 @@ public function getContentForGeneratedAnnotationsFile(array $annotations, string
*/
protected function writeAnnotationsToFile(array $annotations, string $filePath, string $pluginName)
{
- // Create or overwrite the annotations file
- return file_put_contents($filePath, $this->getContentForGeneratedAnnotationsFile($annotations, $pluginName));
+ return $this->writeFile($filePath, $this->getContentForGeneratedAnnotationsFile($annotations, $pluginName));
}
/**
@@ -903,11 +918,11 @@ protected function getExampleIfAvailable(string $url, bool $useLocalToken = fals
}
$method = $queryParams['method'];
$format = strtolower($queryParams['format']);
- $exampleFilePath = $this->currentPluginDir . OpenApiDocs::EXAMPLE_RESPONSES_PATH . $method . '.' . $format;
+ [$pluginName, $methodName] = explode('.', $method);
+ $exampleFilePath = $this->pathResolver->getExampleResponseFilePath($pluginName, $methodName, $format);
// If there's already a file, use that instead of making a new server call. Ignore the file when the flag is set.
if (!$ignoreCached) {
// If an example file is found, return its contents instead of making the server call.
- [$pluginName, $methodName] = explode('.', $method);
$exampleContents = $this->getCachedExampleResponseFile($pluginName, $methodName, $format);
if (!empty($exampleContents)) {
return $exampleContents;
@@ -962,7 +977,7 @@ protected function getExampleIfAvailable(string $url, bool $useLocalToken = fals
$body = $response['data'];
// Write the example response to file as a cache and reference.
- file_put_contents($exampleFilePath, $body);
+ $this->writeFile($exampleFilePath, $body);
// Convert the XML responses into a JSON object and then encode it into a string. This is helpful for building schemas.
if ($format === 'xml') {
@@ -994,7 +1009,7 @@ protected function getExampleIfAvailable(string $url, bool $useLocalToken = fals
*/
protected function getCachedExampleResponseFile(string $pluginName, string $methodName, string $format, bool $rawResult = false, bool $applyMaxLength = true): string
{
- $exampleFilePath = $this->currentPluginDir . OpenApiDocs::EXAMPLE_RESPONSES_PATH . $pluginName . '.' . $methodName . '.' . $format;
+ $exampleFilePath = $this->pathResolver->getExampleResponseFilePath($pluginName, $methodName, $format);
// Simply return an empty string if the file doesn't exist yet.
if (!file_exists($exampleFilePath)) {
return '';
@@ -1021,6 +1036,11 @@ protected function getCachedExampleResponseFile(string $pluginName, string $meth
return $exampleContents;
}
+ protected function writeFile(string $filePath, string $contents)
+ {
+ return $this->artifactWriter->writeFile($filePath, $contents);
+ }
+
/**
* Try to build an example URL for a specific API method using report metadata. This queries the demo server for
* report metadata to get examples of existing reports which can be used as example URLS. If no metadata matches the
diff --git a/Annotations/ApiMethodInfoExtractor.php b/Annotations/ApiMethodInfoExtractor.php
index 23e41a2..aead720 100644
--- a/Annotations/ApiMethodInfoExtractor.php
+++ b/Annotations/ApiMethodInfoExtractor.php
@@ -15,12 +15,29 @@
use Piwik\API\Proxy;
use Piwik\API\Request;
use Piwik\Plugin\Manager;
-use Piwik\Plugins\OpenApiDocs\OpenApiDocs;
+use Piwik\Plugins\OpenApiDocs\Artifact\ArtifactWriter;
+use Piwik\Plugins\OpenApiDocs\Specs\PathResolver;
use Piwik\Validators\BaseValidator;
use Piwik\Validators\NotEmpty;
class ApiMethodInfoExtractor
{
+ /**
+ * @var PathResolver
+ */
+ private $pathResolver;
+
+ /**
+ * @var ArtifactWriter
+ */
+ private $artifactWriter;
+
+ public function __construct(?PathResolver $pathResolver = null, ?ArtifactWriter $artifactWriter = null)
+ {
+ $this->pathResolver = $pathResolver ?? new PathResolver();
+ $this->artifactWriter = $artifactWriter ?? new ArtifactWriter();
+ }
+
/**
* Look up the Matomo Reporting API methods for the specified plugin(s) and output the basic information for each.
* This includes the comment block, parameter information, and things like that. This can then be fed to a secure
@@ -38,8 +55,6 @@ public function extractMethodInfo(string $pluginName, bool $writeToFile = false)
$pluginNames = explode(',', $pluginName);
BaseValidator::check('pluginNames', $pluginNames, [new NotEmpty()]);
- $currentPluginDir = Manager::getInstance()::getPluginDirectory('OpenApiDocs');
-
$methodInfoArray = [];
foreach ($pluginNames as $plugin) {
BaseValidator::check('pluginName', $plugin, [new NotEmpty()]);
@@ -63,8 +78,8 @@ public function extractMethodInfo(string $pluginName, bool $writeToFile = false)
}
if ($writeToFile) {
- $pluginSpecPath = $currentPluginDir . OpenApiDocs::GENERATED_ANNOTATIONS_PATH . $fileBaseName . '_api_method_info.json';
- file_put_contents($pluginSpecPath, $methodInfoString);
+ $pluginSpecPath = $this->pathResolver->getApiMethodInfoFilePath($fileBaseName);
+ $this->artifactWriter->writeFile($pluginSpecPath, $methodInfoString);
}
return $methodInfoString;
diff --git a/Artifact/ArtifactWriter.php b/Artifact/ArtifactWriter.php
new file mode 100644
index 0000000..1ff0712
--- /dev/null
+++ b/Artifact/ArtifactWriter.php
@@ -0,0 +1,27 @@
+extractMethodInfo($plugin, $notDryRun);
if ($notDryRun) {
- $output->writeln('Results written to plugins/OpenApiDocs/tmp/annotations directory.');
+ $output->writeln('Results written to ' . StaticContainer::get(PathResolver::class)->getAnnotationsDirectory() . '');
return $result ? self::SUCCESS : self::FAILURE;
}
diff --git a/Commands/GenerateAnnotations.php b/Commands/GenerateAnnotations.php
index d5faa45..1f43a30 100644
--- a/Commands/GenerateAnnotations.php
+++ b/Commands/GenerateAnnotations.php
@@ -12,6 +12,7 @@
use Piwik\Container\StaticContainer;
use Piwik\Plugin\ConsoleCommand;
use Piwik\Plugins\OpenApiDocs\Annotations\AnnotationGenerator;
+use Piwik\Plugins\OpenApiDocs\Specs\PathResolver;
/**
* This class lets you define a new command. To read more about commands have a look at our Matomo Console guide on
@@ -83,7 +84,7 @@ protected function doExecute(): int
$result = (StaticContainer::get(AnnotationGenerator::class))->generatePluginApiAnnotations($plugin, $notDryRun);
if ($notDryRun) {
- $output->writeln('Results written to plugins/OpenApiDocs/tmp/annotations/ directory.');
+ $output->writeln('Results written to ' . StaticContainer::get(PathResolver::class)->getAnnotationsDirectory() . '');
return $result ? self::SUCCESS : self::FAILURE;
}
diff --git a/Commands/GenerateSpecFile.php b/Commands/GenerateSpecFile.php
index c593de5..c688fe9 100644
--- a/Commands/GenerateSpecFile.php
+++ b/Commands/GenerateSpecFile.php
@@ -13,6 +13,7 @@
use Piwik\Plugin\ConsoleCommand;
use Piwik\Plugins\OpenApiDocs\Generation\SpecGenerationService;
use Piwik\Plugins\OpenApiDocs\OpenApiDocs;
+use Piwik\Plugins\OpenApiDocs\Specs\PathResolver;
/**
* This class lets you define a new command. To read more about commands have a look at our Matomo Console guide on
@@ -28,9 +29,15 @@ class GenerateSpecFile extends ConsoleCommand
*/
private $specGenerationService;
- public function __construct(?SpecGenerationService $specGenerationService = null)
+ /**
+ * @var PathResolver
+ */
+ private $specPathResolver;
+
+ public function __construct(?SpecGenerationService $specGenerationService = null, ?PathResolver $specPathResolver = null)
{
$this->specGenerationService = $specGenerationService ?: StaticContainer::get(SpecGenerationService::class);
+ $this->specPathResolver = $specPathResolver ?: StaticContainer::get(PathResolver::class);
parent::__construct();
}
@@ -116,12 +123,12 @@ protected function doExecute(): int
if ($addAnnotations) {
foreach ($pluginNames as $pluginName) {
- $output->writeln('Created Annotations for ' . $pluginName . ' and wrote results to plugins/OpenApiDocs/tmp/annotations.');
+ $output->writeln('Created Annotations for ' . $pluginName . ' and wrote results to ' . $this->specPathResolver->getAnnotationsDirectory() . '');
}
}
if ($notDryRun) {
- $output->writeln('Results written to plugins/OpenApiDocs/tmp/specs/ directory.');
+ $output->writeln('Results written to ' . $this->specPathResolver->getSpecDirectory() . '');
return self::SUCCESS;
}
diff --git a/Specs/PathResolver.php b/Specs/PathResolver.php
new file mode 100644
index 0000000..1a012d2
--- /dev/null
+++ b/Specs/PathResolver.php
@@ -0,0 +1,121 @@
+pluginDirectory = $pluginDirectory ?? Manager::getInstance()::getPluginDirectory('OpenApiDocs');
+ $this->isCloudActivated = $isCloudActivated ?? Manager::getInstance()->isPluginActivated('Cloud');
+ $this->container = $container ?? $this->getStaticContainer();
+ }
+
+ public function getSpecDirectory(): string
+ {
+ return $this->getArtifactDirectory(self::SHARED_SPECS_SUBDIRECTORY, OpenApiDocs::GENERATED_SPECS_PATH);
+ }
+
+ public function getSpecFilePath(
+ string $specFileBaseName,
+ string $version = OpenApiDocs::DEFAULT_SPEC_VERSION,
+ string $format = 'json'
+ ): string {
+ return $this->getSpecDirectory() . $specFileBaseName . '_openapi_spec_v' . $version . '.' . strtolower($format);
+ }
+
+ public function getAnnotationsDirectory(): string
+ {
+ return $this->getArtifactDirectory(self::SHARED_ANNOTATIONS_SUBDIRECTORY, OpenApiDocs::GENERATED_ANNOTATIONS_PATH);
+ }
+
+ public function getAnnotationFilePath(string $pluginName): string
+ {
+ return $this->getAnnotationsDirectory() . $pluginName . 'GeneratedAnnotations.php';
+ }
+
+ public function getApiMethodInfoFilePath(string $fileBaseName): string
+ {
+ return $this->getAnnotationsDirectory() . $fileBaseName . '_api_method_info.json';
+ }
+
+ public function getResponsesDirectory(): string
+ {
+ return $this->getArtifactDirectory(self::SHARED_RESPONSES_SUBDIRECTORY, OpenApiDocs::EXAMPLE_RESPONSES_PATH);
+ }
+
+ public function getExampleResponseFilePath(string $pluginName, string $methodName, string $format): string
+ {
+ return $this->getResponsesDirectory() . $pluginName . '.' . $methodName . '.' . strtolower($format);
+ }
+
+ private function getArtifactDirectory(string $sharedSubdirectory, string $fallbackPath): string
+ {
+ $sharedPath = $this->getSharedArtifactDirectory($sharedSubdirectory);
+ if ($sharedPath !== null) {
+ return $sharedPath;
+ }
+
+ return $this->pluginDirectory . $fallbackPath;
+ }
+
+ private function getSharedArtifactDirectory(string $sharedSubdirectory): ?string
+ {
+ if (!$this->isCloudActivated || $this->container === null || !$this->container->has('CloudDistributedCachePath')) {
+ return null;
+ }
+
+ $sharedBasePath = trim((string) $this->container->get('CloudDistributedCachePath'));
+ if ($sharedBasePath === '') {
+ return null;
+ }
+
+ if (!$this->isUsableSharedBasePath($sharedBasePath)) {
+ return null;
+ }
+
+ return rtrim($sharedBasePath, '/\\') . self::SHARED_BASE_SUBDIRECTORY . ltrim(substr($sharedSubdirectory, strlen(self::SHARED_BASE_SUBDIRECTORY)), '/\\');
+ }
+
+ protected function isUsableSharedBasePath(string $sharedBasePath): bool
+ {
+ return is_dir($sharedBasePath) && is_writable($sharedBasePath);
+ }
+
+ private function getStaticContainer(): ?Container
+ {
+ try {
+ return StaticContainer::getContainer();
+ } catch (\Throwable $e) {
+ return null;
+ }
+ }
+}
diff --git a/Specs/SpecGenerator.php b/Specs/SpecGenerator.php
index c7f8bfb..e7dc959 100644
--- a/Specs/SpecGenerator.php
+++ b/Specs/SpecGenerator.php
@@ -16,6 +16,7 @@
use Piwik\Log\LoggerInterface;
use Piwik\Log\NullLogger;
use Piwik\Plugin\Manager;
+use Piwik\Plugins\OpenApiDocs\Artifact\ArtifactWriter;
use Piwik\Plugins\OpenApiDocs\OpenApiDocs;
use Piwik\SettingsPiwik;
use Piwik\Validators\BaseValidator;
@@ -23,8 +24,21 @@
class SpecGenerator
{
- public function __construct()
+ /**
+ * @var PathResolver
+ */
+ private $specPathResolver;
+
+ /**
+ * @var ArtifactWriter
+ */
+ private $artifactWriter;
+
+ public function __construct(?PathResolver $specPathResolver = null, ?ArtifactWriter $artifactWriter = null)
{
+ $this->specPathResolver = $specPathResolver ?? new PathResolver();
+ $this->artifactWriter = $artifactWriter ?? new ArtifactWriter();
+
// Set the constant for the current instance's URL
if (!defined('LOCAL_MATOMO_SERVER_URL')) {
define('LOCAL_MATOMO_SERVER_URL', SettingsPiwik::getPiwikUrl());
@@ -79,7 +93,7 @@ public function generateSpec(array $pluginNames, string $format = 'json', string
throw new PluginNotFoundException($pluginName);
}
- $pluginAnnotationsSource = $currentPluginDir . '/tmp/annotations/' . $pluginName . 'GeneratedAnnotations.php';
+ $pluginAnnotationsSource = $this->specPathResolver->getAnnotationFilePath($pluginName);
try {
$openapi = (new Generator(StaticContainer::get(NullLogger::class)))->generate([
$pluginAnnotationsSource,
@@ -117,8 +131,8 @@ public function generateSpec(array $pluginNames, string $format = 'json', string
$lowercaseFormat = strtolower($format);
$specContents = $lowercaseFormat === 'yaml' ? $openapi->toYaml() : $openapi->toJson();
if ($writeToFile) {
- $pluginSpecPath = $currentPluginDir . OpenApiDocs::GENERATED_SPECS_PATH . $specFileBaseName . '_openapi_spec_v' . $version . '.' . $lowercaseFormat;
- file_put_contents($pluginSpecPath, $specContents);
+ $pluginSpecPath = $this->specPathResolver->getSpecFilePath($specFileBaseName, $version, $lowercaseFormat);
+ $this->artifactWriter->writeFile($pluginSpecPath, $specContents);
}
return $specContents;
diff --git a/tests/Unit/APITest.php b/tests/Unit/APITest.php
index bcc49ce..124b6b4 100644
--- a/tests/Unit/APITest.php
+++ b/tests/Unit/APITest.php
@@ -17,6 +17,7 @@
use Piwik\Access;
use Piwik\Container\StaticContainer;
use Piwik\Plugins\OpenApiDocs\API;
+use Piwik\Plugins\OpenApiDocs\Specs\PathResolver;
use Piwik\Tests\Framework\Mock\FakeAccess;
/**
@@ -100,12 +101,21 @@ public function testGetOpenApiSpecThrowsExceptionWhenSpecIsNotAValidPlugin()
$api->getOpenApiSpec('DefinitelyNotARealPlugin');
}
- public function testGetSpecFilePathUsesPluginSpecificFileName()
+ public function testGetSpecFilePathDelegatesToPathResolver()
{
- $api = new API();
+ $pathResolver = $this->createMock(PathResolver::class);
+ $pathResolver->expects($this->once())
+ ->method('getSpecFilePath')
+ ->with('CustomAlerts')
+ ->willReturn('/shared/specs/CustomAlerts_openapi_spec_v1.0.0.json');
+
+ $api = $this->getMockBuilder(API::class)
+ ->onlyMethods(['getSpecPathResolver'])
+ ->getMock();
+ $api->method('getSpecPathResolver')->willReturn($pathResolver);
$this->assertSame(
- PIWIK_INCLUDE_PATH . '/plugins/OpenApiDocs/tmp/specs/CustomAlerts_openapi_spec_v1.0.0.json',
+ '/shared/specs/CustomAlerts_openapi_spec_v1.0.0.json',
$this->callProtectedMethod($api, 'getSpecFilePath', ['CustomAlerts'])
);
}
diff --git a/tests/Unit/Artifact/ArtifactWriterTest.php b/tests/Unit/Artifact/ArtifactWriterTest.php
new file mode 100644
index 0000000..fb969a7
--- /dev/null
+++ b/tests/Unit/Artifact/ArtifactWriterTest.php
@@ -0,0 +1,66 @@
+temporaryDirectory = sys_get_temp_dir() . '/openapidocs_artifact_writer_' . uniqid('', true);
+ }
+
+ protected function tearDown(): void
+ {
+ if (is_dir($this->temporaryDirectory)) {
+ $files = scandir($this->temporaryDirectory);
+ if (is_array($files)) {
+ foreach ($files as $file) {
+ if ($file === '.' || $file === '..') {
+ continue;
+ }
+
+ @unlink($this->temporaryDirectory . '/' . $file);
+ }
+ }
+
+ @rmdir($this->temporaryDirectory . '/nested');
+ @rmdir($this->temporaryDirectory);
+ }
+
+ parent::tearDown();
+ }
+
+ public function testWriteFileCreatesDirectoryAndWritesContents(): void
+ {
+ $writer = new ArtifactWriter();
+ $filePath = $this->temporaryDirectory . '/nested/example.json';
+
+ $result = $writer->writeFile($filePath, '{"status":"ok"}');
+
+ $this->assertIsInt($result);
+ $this->assertSame('{"status":"ok"}', file_get_contents($filePath));
+ }
+}
diff --git a/tests/Unit/Specs/PathResolverTest.php b/tests/Unit/Specs/PathResolverTest.php
new file mode 100644
index 0000000..45d983a
--- /dev/null
+++ b/tests/Unit/Specs/PathResolverTest.php
@@ -0,0 +1,121 @@
+assertSame('/plugins/OpenApiDocs/tmp/specs/', $resolver->getSpecDirectory());
+ $this->assertSame('/plugins/OpenApiDocs/tmp/annotations/', $resolver->getAnnotationsDirectory());
+ $this->assertSame('/plugins/OpenApiDocs/tmp/responses/', $resolver->getResponsesDirectory());
+ }
+
+ public function testReturnsSharedPathsWhenCloudIsEnabledAndDistributedCachePathExists(): void
+ {
+ $resolver = $this->buildPathResolverWithSharedPathValidationResult(true, '/cache/distributed', true);
+
+ $this->assertSame('/cache/distributed/OpenApiDocs/specs/', $resolver->getSpecDirectory());
+ $this->assertSame('/cache/distributed/OpenApiDocs/annotations/', $resolver->getAnnotationsDirectory());
+ $this->assertSame('/cache/distributed/OpenApiDocs/responses/', $resolver->getResponsesDirectory());
+ }
+
+ public function testFallsBackToPluginLocalPathsWhenCloudCachePathIsMissing(): void
+ {
+ $resolver = new PathResolver('/plugins/OpenApiDocs', true, $this->buildContainerStub(false));
+
+ $this->assertSame('/plugins/OpenApiDocs/tmp/specs/', $resolver->getSpecDirectory());
+ $this->assertSame('/plugins/OpenApiDocs/tmp/annotations/', $resolver->getAnnotationsDirectory());
+ $this->assertSame('/plugins/OpenApiDocs/tmp/responses/', $resolver->getResponsesDirectory());
+ }
+
+ public function testFallsBackToPluginLocalPathsWhenCloudCachePathIsEmpty(): void
+ {
+ $resolver = new PathResolver('/plugins/OpenApiDocs', true, $this->buildContainerStub(true, ' '));
+
+ $this->assertSame('/plugins/OpenApiDocs/tmp/specs/', $resolver->getSpecDirectory());
+ $this->assertSame('/plugins/OpenApiDocs/tmp/annotations/', $resolver->getAnnotationsDirectory());
+ $this->assertSame('/plugins/OpenApiDocs/tmp/responses/', $resolver->getResponsesDirectory());
+ }
+
+ public function testBuildsFilePathsUsingExpectedNamingConventions(): void
+ {
+ $resolver = $this->buildPathResolverWithSharedPathValidationResult(true, '/cache/distributed/', true);
+
+ $this->assertSame(
+ '/cache/distributed/OpenApiDocs/specs/CustomAlerts_openapi_spec_v2.0.0.yaml',
+ $resolver->getSpecFilePath('CustomAlerts', '2.0.0', 'YAML')
+ );
+ $this->assertSame(
+ '/cache/distributed/OpenApiDocs/annotations/CustomAlertsGeneratedAnnotations.php',
+ $resolver->getAnnotationFilePath('CustomAlerts')
+ );
+ $this->assertSame(
+ '/cache/distributed/OpenApiDocs/annotations/matomo_api_method_info.json',
+ $resolver->getApiMethodInfoFilePath('matomo')
+ );
+ $this->assertSame(
+ '/cache/distributed/OpenApiDocs/responses/CustomAlerts.getAlerts.json',
+ $resolver->getExampleResponseFilePath('CustomAlerts', 'getAlerts', 'JSON')
+ );
+ }
+
+ private function buildContainerStub(bool $hasDistributedCachePath, string $distributedCachePath = ''): Container
+ {
+ $container = $this->getMockBuilder(Container::class)
+ ->disableOriginalConstructor()
+ ->onlyMethods(['has', 'get'])
+ ->getMock();
+
+ $container->method('has')
+ ->with('CloudDistributedCachePath')
+ ->willReturn($hasDistributedCachePath);
+
+ if ($hasDistributedCachePath) {
+ $container->method('get')
+ ->with('CloudDistributedCachePath')
+ ->willReturn($distributedCachePath);
+ }
+
+ return $container;
+ }
+
+ private function buildPathResolverWithSharedPathValidationResult(
+ bool $hasDistributedCachePath,
+ string $distributedCachePath,
+ bool $isUsableSharedBasePath
+ ): PathResolver {
+ $resolver = $this->getMockBuilder(PathResolver::class)
+ ->setConstructorArgs(['/plugins/OpenApiDocs', true, $this->buildContainerStub($hasDistributedCachePath, $distributedCachePath)])
+ ->onlyMethods(['isUsableSharedBasePath'])
+ ->getMock();
+
+ $resolver->method('isUsableSharedBasePath')
+ ->with(trim($distributedCachePath))
+ ->willReturn($isUsableSharedBasePath);
+
+ return $resolver;
+ }
+}