From 562763199a26aef992e300b0d2a3c448a6febe59 Mon Sep 17 00:00:00 2001 From: Alejandro Celaya Date: Fri, 7 Jan 2022 13:13:45 +0100 Subject: [PATCH] Ensured URL titles are trimmed to avoid error when persisted in database --- composer.json | 8 +++++- .../src/Validation/ShortUrlInputFilter.php | 9 +++++- module/Core/test/Model/ShortUrlMetaTest.php | 28 +++++++++++++++++++ 3 files changed, 43 insertions(+), 2 deletions(-) diff --git a/composer.json b/composer.json index b8ff3349..8e55c3c4 100644 --- a/composer.json +++ b/composer.json @@ -192,6 +192,12 @@ }, "config": { "sort-packages": true, - "platform-check": false + "platform-check": false, + "allow-plugins": { + "composer/package-versions-deprecated": true, + "dealerdirect/phpcodesniffer-composer-installer": true, + "infection/extension-installer": true, + "veewee/composer-run-parallel": true + } } } diff --git a/module/Core/src/Validation/ShortUrlInputFilter.php b/module/Core/src/Validation/ShortUrlInputFilter.php index 47f6f8ac..2497f85d 100644 --- a/module/Core/src/Validation/ShortUrlInputFilter.php +++ b/module/Core/src/Validation/ShortUrlInputFilter.php @@ -6,6 +6,7 @@ namespace Shlinkio\Shlink\Core\Validation; use Cocur\Slugify\Slugify; use DateTime; +use Laminas\Filter; use Laminas\InputFilter\Input; use Laminas\InputFilter\InputFilter; use Laminas\Validator; @@ -13,6 +14,8 @@ use Shlinkio\Shlink\Common\Validation; use Shlinkio\Shlink\Core\Util\CocurSymfonySluggerBridge; use Shlinkio\Shlink\Rest\Entity\ApiKey; +use function substr; + use const Shlinkio\Shlink\CUSTOM_SLUGS_REGEXP; use const Shlinkio\Shlink\MIN_SHORT_CODES_LENGTH; @@ -107,7 +110,11 @@ class ShortUrlInputFilter extends InputFilter $this->add($this->createTagsInput(self::TAGS, false)); - $this->add($this->createInput(self::TITLE, false)); + $title = $this->createInput(self::TITLE, false); + $title->getFilterChain()->attach(new Filter\Callback( + static fn (?string $value) => $value === null ? $value : substr($value, 0, 512), + )); + $this->add($title); $this->add($this->createBooleanInput(self::CRAWLABLE, false)); } diff --git a/module/Core/test/Model/ShortUrlMetaTest.php b/module/Core/test/Model/ShortUrlMetaTest.php index 2b57987b..5fef14d8 100644 --- a/module/Core/test/Model/ShortUrlMetaTest.php +++ b/module/Core/test/Model/ShortUrlMetaTest.php @@ -11,6 +11,10 @@ use Shlinkio\Shlink\Core\Model\ShortUrlMeta; use Shlinkio\Shlink\Core\Validation\ShortUrlInputFilter; use stdClass; +use function str_pad; + +use const STR_PAD_BOTH; + class ShortUrlMetaTest extends TestCase { /** @@ -99,4 +103,28 @@ class ShortUrlMetaTest extends TestCase yield ['谷歌', '谷歌']; yield ['гугл', 'гугл']; } + + /** + * @test + * @dataProvider provideTitles + */ + public function titleIsCroppedIfTooLong(?string $title, ?string $expectedTitle): void + { + $meta = ShortUrlMeta::fromRawData([ + 'title' => $title, + 'longUrl' => '', + ]); + + self::assertEquals($expectedTitle, $meta->getTitle()); + } + + public function provideTitles(): iterable + { + yield [null, null]; + yield ['foo', 'foo']; + yield [str_pad('bar', 600, ' ', STR_PAD_BOTH), 'bar']; + yield [str_pad('', 512, 'a'), str_pad('', 512, 'a')]; + yield [str_pad('', 600, 'b'), str_pad('', 512, 'b')]; + yield [str_pad('', 800, 'b'), str_pad('', 512, 'b')]; + } }