Skip to content

Commit

Permalink
Merge pull request #202 from acelaya-forks/feature/matomo-support
Browse files Browse the repository at this point in the history
Feature/matomo support
  • Loading branch information
acelaya authored Nov 11, 2023
2 parents c1ef08c + 21a3b94 commit c505a19
Show file tree
Hide file tree
Showing 12 changed files with 291 additions and 3 deletions.
1 change: 1 addition & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -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*
Expand Down
8 changes: 8 additions & 0 deletions config/config.php
Original file line number Diff line number Diff line change
Expand Up @@ -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,
],
],

Expand Down Expand Up @@ -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,
Expand Down
20 changes: 20 additions & 0 deletions src/Config/Option/Matomo/AbstractMatomoEnabledConfigOption.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,20 @@
<?php

namespace Shlinkio\Shlink\Installer\Config\Option\Matomo;

use Shlinkio\Shlink\Installer\Config\Option\BaseConfigOption;
use Shlinkio\Shlink\Installer\Config\Option\DependentConfigOptionInterface;

abstract class AbstractMatomoEnabledConfigOption extends BaseConfigOption implements DependentConfigOptionInterface
{
public function shouldBeAsked(array $currentOptions): bool
{
$matomoEnabled = $currentOptions[MatomoEnabledConfigOption::ENV_VAR] ?? false;
return $matomoEnabled && parent::shouldBeAsked($currentOptions);
}

public function getDependentOption(): string
{
return MatomoEnabledConfigOption::class;
}
}
21 changes: 21 additions & 0 deletions src/Config/Option/Matomo/MatomoApiTokenConfigOption.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,21 @@
<?php

namespace Shlinkio\Shlink\Installer\Config\Option\Matomo;

use Shlinkio\Shlink\Installer\Util\AskUtilsTrait;
use Symfony\Component\Console\Style\StyleInterface;

class MatomoApiTokenConfigOption extends AbstractMatomoEnabledConfigOption
{
use AskUtilsTrait;

public function getEnvVar(): string
{
return 'MATOMO_API_TOKEN';
}

public function ask(StyleInterface $io, array $currentOptions): string
{
return $this->askRequired($io, 'Matomo API token');
}
}
21 changes: 21 additions & 0 deletions src/Config/Option/Matomo/MatomoBaseUrlConfigOption.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,21 @@
<?php

namespace Shlinkio\Shlink\Installer\Config\Option\Matomo;

use Shlinkio\Shlink\Installer\Util\AskUtilsTrait;
use Symfony\Component\Console\Style\StyleInterface;

class MatomoBaseUrlConfigOption extends AbstractMatomoEnabledConfigOption
{
use AskUtilsTrait;

public function getEnvVar(): string
{
return 'MATOMO_BASE_URL';
}

public function ask(StyleInterface $io, array $currentOptions): string
{
return $this->askRequired($io, 'Matomo server URL');
}
}
21 changes: 21 additions & 0 deletions src/Config/Option/Matomo/MatomoEnabledConfigOption.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,21 @@
<?php

namespace Shlinkio\Shlink\Installer\Config\Option\Matomo;

use Shlinkio\Shlink\Installer\Config\Option\BaseConfigOption;
use Symfony\Component\Console\Style\StyleInterface;

class MatomoEnabledConfigOption extends BaseConfigOption
{
public const ENV_VAR = 'MATOMO_ENABLED';

public function getEnvVar(): string
{
return self::ENV_VAR;
}

public function ask(StyleInterface $io, array $currentOptions): bool
{
return $io->confirm('Do you want Shlink to send all visits to an external Matomo server?', false);
}
}
21 changes: 21 additions & 0 deletions src/Config/Option/Matomo/MatomoSiteIdConfigOption.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,21 @@
<?php

namespace Shlinkio\Shlink\Installer\Config\Option\Matomo;

use Shlinkio\Shlink\Installer\Util\AskUtilsTrait;
use Symfony\Component\Console\Style\StyleInterface;

class MatomoSiteIdConfigOption extends AbstractMatomoEnabledConfigOption
{
use AskUtilsTrait;

public function getEnvVar(): string
{
return 'MATOMO_SITE_ID';
}

public function ask(StyleInterface $io, array $currentOptions): string
{
return $this->askRequired($io, 'Matomo site ID');
}
}
6 changes: 3 additions & 3 deletions src/Util/AskUtilsTrait.php
Original file line number Diff line number Diff line change
Expand Up @@ -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;
Expand Down
38 changes: 38 additions & 0 deletions test/Config/Option/Matomo/MatomoApiTokenConfigOptionTest.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,38 @@
<?php

declare(strict_types=1);

namespace ShlinkioTest\Shlink\Installer\Config\Option\Matomo;

use PHPUnit\Framework\Attributes\Test;
use PHPUnit\Framework\TestCase;
use Shlinkio\Shlink\Installer\Config\Option\Matomo\MatomoApiTokenConfigOption;
use Symfony\Component\Console\Style\StyleInterface;

class MatomoApiTokenConfigOptionTest extends TestCase
{
private MatomoApiTokenConfigOption $configOption;

public function setUp(): void
{
$this->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);
}
}
59 changes: 59 additions & 0 deletions test/Config/Option/Matomo/MatomoBaseUrlConfigOptionTest.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,59 @@
<?php

declare(strict_types=1);

namespace ShlinkioTest\Shlink\Installer\Config\Option\Matomo;

use PHPUnit\Framework\Attributes\DataProvider;
use PHPUnit\Framework\Attributes\Test;
use PHPUnit\Framework\TestCase;
use Shlinkio\Shlink\Installer\Config\Option\Matomo\MatomoBaseUrlConfigOption;
use Shlinkio\Shlink\Installer\Config\Option\Matomo\MatomoEnabledConfigOption;
use Symfony\Component\Console\Style\StyleInterface;

class MatomoBaseUrlConfigOptionTest extends TestCase
{
private MatomoBaseUrlConfigOption $configOption;

public function setUp(): void
{
$this->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];
}
}
40 changes: 40 additions & 0 deletions test/Config/Option/Matomo/MatomoEnabledConfigOptionTest.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,40 @@
<?php

declare(strict_types=1);

namespace ShlinkioTest\Shlink\Installer\Config\Option\Matomo;

use PHPUnit\Framework\Attributes\Test;
use PHPUnit\Framework\TestCase;
use Shlinkio\Shlink\Installer\Config\Option\Matomo\MatomoEnabledConfigOption;
use Symfony\Component\Console\Style\StyleInterface;

class MatomoEnabledConfigOptionTest extends TestCase
{
private MatomoEnabledConfigOption $configOption;

public function setUp(): void
{
$this->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);
}
}
38 changes: 38 additions & 0 deletions test/Config/Option/Matomo/MatomoSiteIdConfigOptionTest.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,38 @@
<?php

declare(strict_types=1);

namespace ShlinkioTest\Shlink\Installer\Config\Option\Matomo;

use PHPUnit\Framework\Attributes\Test;
use PHPUnit\Framework\TestCase;
use Shlinkio\Shlink\Installer\Config\Option\Matomo\MatomoSiteIdConfigOption;
use Symfony\Component\Console\Style\StyleInterface;

class MatomoSiteIdConfigOptionTest extends TestCase
{
private MatomoSiteIdConfigOption $configOption;

public function setUp(): void
{
$this->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);
}
}

0 comments on commit c505a19

Please sign in to comment.