Skip to content

Commit

Permalink
Merge pull request #226 from shlinkio/develop
Browse files Browse the repository at this point in the history
Release 9.2.0
  • Loading branch information
acelaya authored Aug 11, 2024
2 parents 94a5a66 + c1afdd6 commit 269ea3f
Show file tree
Hide file tree
Showing 12 changed files with 206 additions and 30 deletions.
20 changes: 20 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,26 @@ All notable changes to this project will be documented in this file.

The format is based on [Keep a Changelog](https://keepachangelog.com), and this project adheres to [Semantic Versioning](https://semver.org).

## [9.2.0] - 2024-08-11
### Added
* Add `ROBOTS_ALLOW_ALL_SHORT_URLS` config option.
* Add `ROBOTS_USER_AGENTS` config option.
* Add support for `laminas/laminas-servicemanager` v4.x.

### Changed
* Update to PHPUnit 11
* Update to PHPStan 1.11

### Deprecated
* *Nothing*

### Removed
* *Nothing*

### Fixed
* *Nothing*


## [9.1.0] - 2024-04-14
### Added
* Add `MEMORY_LIMIT` config option.
Expand Down
24 changes: 12 additions & 12 deletions composer.json
Original file line number Diff line number Diff line change
Expand Up @@ -14,22 +14,22 @@
"require": {
"php": "^8.2",
"laminas/laminas-config": "^3.9",
"laminas/laminas-config-aggregator": "^1.14",
"laminas/laminas-servicemanager": "^3.22",
"laminas/laminas-config-aggregator": "^1.15",
"laminas/laminas-servicemanager": "^4.2 || ^3.22",
"laminas/laminas-stdlib": "^3.19",
"shlinkio/shlink-config": "^3.0 || ^2.5",
"symfony/console": "^7.0 || ^6.4",
"symfony/filesystem": "^7.0 || ^6.4",
"symfony/process": "^7.0 || ^6.4"
"shlinkio/shlink-config": "^3.1",
"symfony/console": "^7.1",
"symfony/filesystem": "^7.1",
"symfony/process": "^7.1"
},
"require-dev": {
"devster/ubench": "^2.1",
"phpstan/phpstan": "^1.10",
"phpstan/phpstan-phpunit": "^1.3",
"phpunit/phpunit": "^10.5",
"phpstan/phpstan": "^1.11",
"phpstan/phpstan-phpunit": "^1.4",
"phpunit/phpunit": "^11.3",
"roave/security-advisories": "dev-master",
"shlinkio/php-coding-standard": "~2.3.0",
"symfony/var-dumper": "^7.0 || ^6.4"
"symfony/var-dumper": "^7.1"
},
"autoload": {
"psr-4": {
Expand All @@ -49,8 +49,8 @@
],
"cs": "phpcs",
"cs:fix": "phpcbf",
"stan": "phpstan analyse src test test-resources config --level=8",
"test": "phpunit --order-by=random --testdox --colors=always",
"stan": "phpstan analyse",
"test": "phpunit --order-by=random --testdox --testdox-summary",
"test:ci": "@test --coverage-clover=build/clover.xml",
"test:pretty": "@test --coverage-html=build/coverage-html"
},
Expand Down
5 changes: 5 additions & 0 deletions config/config.php
Original file line number Diff line number Diff line change
Expand Up @@ -96,6 +96,10 @@
'QR codes > Enabled for disabled short URLs'
=> Config\Option\QrCode\EnabledForDisabledShortUrlsConfigOption::class,
],
'ROBOTS' => [
'Robots.txt > allow all' => Config\Option\Robots\RobotsAllowAllShortUrlsConfigOption::class,
'Robots.txt > user agents' => Config\Option\Robots\RobotsUserAgentsConfigOption::class,
],
'APPLICATION' => [
'Delete short URLs > Visits threshold' => Config\Option\Visit\VisitsThresholdConfigOption::class,
'Base path' => Config\Option\BasePathConfigOption::class,
Expand Down Expand Up @@ -148,6 +152,7 @@
Config\Option\UrlShortener\EnableMultiSegmentSlugsConfigOption::class => InvokableFactory::class,
Config\Option\UrlShortener\EnableTrailingSlashConfigOption::class => InvokableFactory::class,
Config\Option\UrlShortener\ShortUrlModeConfigOption::class => InvokableFactory::class,
Config\Option\Robots\RobotsAllowAllShortUrlsConfigOption::class => InvokableFactory::class,
Config\Option\Redis\RedisServersConfigOption::class => InvokableFactory::class,
Config\Option\Redis\RedisSentinelServiceConfigOption::class => InvokableFactory::class,
Config\Option\Redis\RedisPubSubConfigOption::class => InvokableFactory::class,
Expand Down
2 changes: 0 additions & 2 deletions docker-compose.override.yml.dist
Original file line number Diff line number Diff line change
@@ -1,5 +1,3 @@
version: '3'

services:
shlink_installer_php:
user: 1000:1000
Expand Down
2 changes: 0 additions & 2 deletions docker-compose.yml
Original file line number Diff line number Diff line change
@@ -1,5 +1,3 @@
version: '3'

services:
shlink_installer_php:
container_name: shlink_installer_php
Expand Down
14 changes: 10 additions & 4 deletions phpstan.neon
Original file line number Diff line number Diff line change
@@ -1,6 +1,12 @@
includes:
- vendor/phpstan/phpstan-phpunit/extension.neon
- vendor/phpstan/phpstan-phpunit/rules.neon
- vendor/phpstan/phpstan-phpunit/extension.neon
- vendor/phpstan/phpstan-phpunit/rules.neon
parameters:
checkMissingIterableValueType: false
checkGenericClassInNonGenericObjectType: false
level: 8
paths:
- config
- src
- test
- test-resources
ignoreErrors:
- identifier: missingType.iterableValue
23 changes: 23 additions & 0 deletions src/Config/ConfigOptionsManager.php
Original file line number Diff line number Diff line change
Expand Up @@ -5,8 +5,31 @@
namespace Shlinkio\Shlink\Installer\Config;

use Laminas\ServiceManager\AbstractPluginManager;
use Laminas\ServiceManager\Exception\InvalidServiceException;

use function get_debug_type;
use function sprintf;

/**
* @extends AbstractPluginManager<Option\ConfigOptionInterface>
* @todo Extend from AbstractSingleInstancePluginManager once servicemanager 3 is no longer supported
*/
class ConfigOptionsManager extends AbstractPluginManager implements ConfigOptionsManagerInterface
{
/** @var class-string<Option\ConfigOptionInterface> */
protected $instanceOf = Option\ConfigOptionInterface::class; // phpcs:ignore

public function validate(mixed $instance): void
{
if ($instance instanceof $this->instanceOf) {
return;
}

throw new InvalidServiceException(sprintf(
'Plugin manager "%s" expected an instance of type "%s", but "%s" was received',
static::class,
$this->instanceOf,
get_debug_type($instance),
));
}
}
25 changes: 25 additions & 0 deletions src/Config/Option/Robots/RobotsAllowAllShortUrlsConfigOption.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,25 @@
<?php

declare(strict_types=1);

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

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

class RobotsAllowAllShortUrlsConfigOption extends BaseConfigOption
{
public function getEnvVar(): string
{
return 'ROBOTS_ALLOW_ALL_SHORT_URLS';
}

public function ask(StyleInterface $io, array $currentOptions): bool
{
return $io->confirm(
'Do you want all short URLs to be crawlable/allowed by the robots.txt file? '
. 'You can still allow them individually, regardless of this.',
default: false,
);
}
}
23 changes: 23 additions & 0 deletions src/Config/Option/Robots/RobotsUserAgentsConfigOption.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,23 @@
<?php

declare(strict_types=1);

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

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

class RobotsUserAgentsConfigOption extends BaseConfigOption
{
public function getEnvVar(): string
{
return 'ROBOTS_USER_AGENTS';
}

public function ask(StyleInterface $io, array $currentOptions): ?string
{
return $io->ask(
'Provide a comma-separated list of user agents for your robots.txt file. Defaults to all user agents (*)',
);
}
}
18 changes: 8 additions & 10 deletions test/Config/ConfigOptionsManagerFactoryTest.php
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,6 @@
use PHPUnit\Framework\MockObject\MockObject;
use PHPUnit\Framework\TestCase;
use Psr\Container\ContainerInterface;
use ReflectionObject;
use Shlinkio\Shlink\Installer\Config\ConfigOptionsManagerFactory;
use Shlinkio\Shlink\Installer\Config\Option\ConfigOptionInterface;

Expand All @@ -25,23 +24,22 @@ public function setUp(): void
}

#[Test, DataProvider('provideConfigs')]
public function createsServiceWithExpectedPlugins(callable $configCreator, int $expectedSize): void
public function createsServiceWithExpectedPlugins(callable $configCreator, bool $servicesExist): void
{
$config = $configCreator($this);
$this->container->expects($this->once())->method('get')->with('config')->willReturn($config);

$service = ($this->factory)($this->container);
$ref = new ReflectionObject($service);
$servicesProp = $ref->getProperty('services');
$servicesProp->setAccessible(true);
$manager = ($this->factory)($this->container);

self::assertCount($expectedSize, $servicesProp->getValue($service));
self::assertEquals($servicesExist, $manager->has('a'));
self::assertEquals($servicesExist, $manager->has('b'));
self::assertEquals($servicesExist, $manager->has('c'));
}

public static function provideConfigs(): iterable
{
yield 'config_options not defined' => [static fn (TestCase $test) => [], 0];
yield 'config_options empty' => [static fn (TestCase $test) => ['config_options' => []], 0];
yield 'config_options not defined' => [static fn (TestCase $test) => [], false];
yield 'config_options empty' => [static fn (TestCase $test) => ['config_options' => []], false];
yield 'config_options with values' => [
static fn (TestCase $test) => [
'config_options' => [
Expand All @@ -52,7 +50,7 @@ public static function provideConfigs(): iterable
],
],
],
3,
true,
];
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,41 @@
<?php

declare(strict_types=1);

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

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

class RobotsAllowAllShortUrlsConfigOptionTest extends TestCase
{
private RobotsAllowAllShortUrlsConfigOption $configOption;

public function setUp(): void
{
$this->configOption = new RobotsAllowAllShortUrlsConfigOption();
}

#[Test]
public function returnsExpectedEnvVar(): void
{
self::assertEquals('ROBOTS_ALLOW_ALL_SHORT_URLS', $this->configOption->getEnvVar());
}

#[Test]
public function expectedQuestionIsAsked(): void
{
$io = $this->createMock(StyleInterface::class);
$io->expects($this->once())->method('confirm')->with(
'Do you want all short URLs to be crawlable/allowed by the robots.txt file? '
. 'You can still allow them individually, regardless of this.',
false,
)->willReturn(true);

$answer = $this->configOption->ask($io, []);

self::assertTrue($answer);
}
}
39 changes: 39 additions & 0 deletions test/Config/Option/Robots/RobotsUserAgentsConfigOptionTest.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,39 @@
<?php

declare(strict_types=1);

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

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

class RobotsUserAgentsConfigOptionTest extends TestCase
{
private RobotsUserAgentsConfigOption $configOption;

public function setUp(): void
{
$this->configOption = new RobotsUserAgentsConfigOption();
}

#[Test]
public function returnsExpectedEnvVar(): void
{
self::assertEquals('ROBOTS_USER_AGENTS', $this->configOption->getEnvVar());
}

#[Test]
public function expectedQuestionIsAsked(): void
{
$io = $this->createMock(StyleInterface::class);
$io->expects($this->once())->method('ask')->with(
'Provide a comma-separated list of user agents for your robots.txt file. Defaults to all user agents (*)',
)->willReturn('foo,bar');

$answer = $this->configOption->ask($io, []);

self::assertEquals('foo,bar', $answer);
}
}

0 comments on commit 269ea3f

Please sign in to comment.