diff --git a/CHANGELOG.md b/CHANGELOG.md index 0785476..ded4a0f 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -8,6 +8,7 @@ The format is based on [Keep a Changelog](https://keepachangelog.com), and this ### Added * Add `CacheNamespaceConfigOption` to customize the cache namespace. * Add support for PHP 8.3 +* [#200](https://github.com/shlinkio/shlink-installer/issues/200) Add Matomo integration config options. ### Changed * *Nothing* diff --git a/config/config.php b/config/config.php index c7f6da1..103a907 100644 --- a/config/config.php +++ b/config/config.php @@ -110,6 +110,10 @@ 'RabbitMQ > User' => Config\Option\RabbitMq\RabbitMqUserConfigOption::class, 'RabbitMQ > Password' => Config\Option\RabbitMq\RabbitMqPasswordConfigOption::class, 'RabbitMQ > VHost' => Config\Option\RabbitMq\RabbitMqVhostConfigOption::class, + 'Matomo > Enable' => Config\Option\Matomo\MatomoEnabledConfigOption::class, + 'Matomo > Server URL' => Config\Option\Matomo\MatomoBaseUrlConfigOption::class, + 'Matomo > Site ID' => Config\Option\Matomo\MatomoSiteIdConfigOption::class, + 'Matomo > API token' => Config\Option\Matomo\MatomoApiTokenConfigOption::class, ], ], @@ -153,6 +157,10 @@ Config\Option\RabbitMq\RabbitMqUserConfigOption::class => ConfigAbstractFactory::class, Config\Option\RabbitMq\RabbitMqPasswordConfigOption::class => ConfigAbstractFactory::class, Config\Option\RabbitMq\RabbitMqVhostConfigOption::class => ConfigAbstractFactory::class, + Config\Option\Matomo\MatomoEnabledConfigOption::class => InvokableFactory::class, + Config\Option\Matomo\MatomoBaseUrlConfigOption::class => InvokableFactory::class, + Config\Option\Matomo\MatomoSiteIdConfigOption::class => InvokableFactory::class, + Config\Option\Matomo\MatomoApiTokenConfigOption::class => InvokableFactory::class, Config\Option\UrlShortener\GeoLiteLicenseKeyConfigOption::class => InvokableFactory::class, Config\Option\Tracking\OrphanVisitsTrackingConfigOption::class => InvokableFactory::class, Config\Option\Tracking\DisableTrackParamConfigOption::class => InvokableFactory::class, diff --git a/src/Config/Option/Matomo/AbstractMatomoEnabledConfigOption.php b/src/Config/Option/Matomo/AbstractMatomoEnabledConfigOption.php new file mode 100644 index 0000000..3ada3b0 --- /dev/null +++ b/src/Config/Option/Matomo/AbstractMatomoEnabledConfigOption.php @@ -0,0 +1,20 @@ +askRequired($io, 'Matomo API token'); + } +} diff --git a/src/Config/Option/Matomo/MatomoBaseUrlConfigOption.php b/src/Config/Option/Matomo/MatomoBaseUrlConfigOption.php new file mode 100644 index 0000000..bea9a3e --- /dev/null +++ b/src/Config/Option/Matomo/MatomoBaseUrlConfigOption.php @@ -0,0 +1,21 @@ +askRequired($io, 'Matomo server URL'); + } +} diff --git a/src/Config/Option/Matomo/MatomoEnabledConfigOption.php b/src/Config/Option/Matomo/MatomoEnabledConfigOption.php new file mode 100644 index 0000000..dd58c22 --- /dev/null +++ b/src/Config/Option/Matomo/MatomoEnabledConfigOption.php @@ -0,0 +1,21 @@ +confirm('Do you want Shlink to send all visits to an external Matomo server?', false); + } +} diff --git a/src/Config/Option/Matomo/MatomoSiteIdConfigOption.php b/src/Config/Option/Matomo/MatomoSiteIdConfigOption.php new file mode 100644 index 0000000..da6d6ce --- /dev/null +++ b/src/Config/Option/Matomo/MatomoSiteIdConfigOption.php @@ -0,0 +1,21 @@ +askRequired($io, 'Matomo site ID'); + } +} diff --git a/src/Util/AskUtilsTrait.php b/src/Util/AskUtilsTrait.php index 7adc3cc..9078777 100644 --- a/src/Util/AskUtilsTrait.php +++ b/src/Util/AskUtilsTrait.php @@ -9,11 +9,11 @@ trait AskUtilsTrait { - private function askRequired(StyleInterface $io, string $optionNameOrQuestion, ?string $question = null): string + private function askRequired(StyleInterface $io, string $optionName, ?string $question = null): string { - return $io->ask($question ?? $optionNameOrQuestion, null, static function ($value) use ($optionNameOrQuestion) { + return $io->ask($question ?? $optionName, null, static function ($value) use ($optionName) { if (empty($value)) { - throw MissingRequiredOptionException::fromOption($optionNameOrQuestion); + throw MissingRequiredOptionException::fromOption($optionName); } return $value; diff --git a/test/Config/Option/Matomo/MatomoApiTokenConfigOptionTest.php b/test/Config/Option/Matomo/MatomoApiTokenConfigOptionTest.php new file mode 100644 index 0000000..54056bf --- /dev/null +++ b/test/Config/Option/Matomo/MatomoApiTokenConfigOptionTest.php @@ -0,0 +1,38 @@ +configOption = new MatomoApiTokenConfigOption(); + } + + #[Test] + public function returnsExpectedEnvVar(): void + { + self::assertEquals('MATOMO_API_TOKEN', $this->configOption->getEnvVar()); + } + + #[Test] + public function expectedQuestionIsAsked(): void + { + $expectedAnswer = 'abc123'; + $io = $this->createMock(StyleInterface::class); + $io->expects($this->once())->method('ask')->with('Matomo API token')->willReturn($expectedAnswer); + + $answer = $this->configOption->ask($io, []); + + self::assertEquals($expectedAnswer, $answer); + } +} diff --git a/test/Config/Option/Matomo/MatomoBaseUrlConfigOptionTest.php b/test/Config/Option/Matomo/MatomoBaseUrlConfigOptionTest.php new file mode 100644 index 0000000..a52be70 --- /dev/null +++ b/test/Config/Option/Matomo/MatomoBaseUrlConfigOptionTest.php @@ -0,0 +1,59 @@ +configOption = new MatomoBaseUrlConfigOption(); + } + + #[Test] + public function returnsExpectedEnvVar(): void + { + self::assertEquals('MATOMO_BASE_URL', $this->configOption->getEnvVar()); + } + + #[Test] + public function expectedQuestionIsAsked(): void + { + $expectedAnswer = 'foobar.com'; + $io = $this->createMock(StyleInterface::class); + $io->expects($this->once())->method('ask')->with('Matomo server URL')->willReturn($expectedAnswer); + + $answer = $this->configOption->ask($io, []); + + self::assertEquals($expectedAnswer, $answer); + } + + #[Test] + public function dependsOnMatomoEnabled(): void + { + self::assertEquals(MatomoEnabledConfigOption::class, $this->configOption->getDependentOption()); + } + + #[Test, DataProvider('provideCurrentOptions')] + public function shouldBeAskedOnlyIfMatomoIsEnabled(array $currentOptions, bool $expected): void + { + self::assertEquals($expected, $this->configOption->shouldBeAsked($currentOptions)); + } + + public static function provideCurrentOptions(): iterable + { + yield 'matomo enabled' => [[MatomoEnabledConfigOption::ENV_VAR => true], true]; + yield 'matomo not enabled' => [[MatomoEnabledConfigOption::ENV_VAR => false], false]; + yield 'matomo not set' => [[], false]; + } +} diff --git a/test/Config/Option/Matomo/MatomoEnabledConfigOptionTest.php b/test/Config/Option/Matomo/MatomoEnabledConfigOptionTest.php new file mode 100644 index 0000000..cbc62fa --- /dev/null +++ b/test/Config/Option/Matomo/MatomoEnabledConfigOptionTest.php @@ -0,0 +1,40 @@ +configOption = new MatomoEnabledConfigOption(); + } + + #[Test] + public function returnsExpectedEnvVar(): void + { + self::assertEquals('MATOMO_ENABLED', $this->configOption->getEnvVar()); + } + + #[Test] + public function expectedQuestionIsAsked(): void + { + $io = $this->createMock(StyleInterface::class); + $io->expects($this->once())->method('confirm')->with( + 'Do you want Shlink to send all visits to an external Matomo server?', + false, + )->willReturn(true); + + $answer = $this->configOption->ask($io, []); + + self::assertTrue($answer); + } +} diff --git a/test/Config/Option/Matomo/MatomoSiteIdConfigOptionTest.php b/test/Config/Option/Matomo/MatomoSiteIdConfigOptionTest.php new file mode 100644 index 0000000..d894ff3 --- /dev/null +++ b/test/Config/Option/Matomo/MatomoSiteIdConfigOptionTest.php @@ -0,0 +1,38 @@ +configOption = new MatomoSiteIdConfigOption(); + } + + #[Test] + public function returnsExpectedEnvVar(): void + { + self::assertEquals('MATOMO_SITE_ID', $this->configOption->getEnvVar()); + } + + #[Test] + public function expectedQuestionIsAsked(): void + { + $expectedAnswer = '12345'; + $io = $this->createMock(StyleInterface::class); + $io->expects($this->once())->method('ask')->with('Matomo site ID')->willReturn($expectedAnswer); + + $answer = $this->configOption->ask($io, []); + + self::assertEquals($expectedAnswer, $answer); + } +}