diff --git a/typo3/sysext/core/Documentation/Changelog/master/Feature-80342-ExtbaseValidatorForURLs.rst b/typo3/sysext/core/Documentation/Changelog/master/Feature-80342-ExtbaseValidatorForURLs.rst new file mode 100644 index 0000000000000000000000000000000000000000..a83d9fba971c53723ee9178dcfd4878f9b676a8d --- /dev/null +++ b/typo3/sysext/core/Documentation/Changelog/master/Feature-80342-ExtbaseValidatorForURLs.rst @@ -0,0 +1,20 @@ +.. include:: ../../Includes.txt + +============================================ +Feature: #80342 - Extbase validator for URLs +============================================ + +See :issue:`80342` + +Description +=========== + +It is now possible to validate URLs in an Extbase model. + + +Impact +====== + +Validation may be used by adding the annotation :php`@validate Url`. + +.. index:: PHP-API, NotScanned diff --git a/typo3/sysext/extbase/Classes/Validation/Validator/UrlValidator.php b/typo3/sysext/extbase/Classes/Validation/Validator/UrlValidator.php new file mode 100644 index 0000000000000000000000000000000000000000..04f2c3f843d99358f8e30270f1dc7c35b5aeef98 --- /dev/null +++ b/typo3/sysext/extbase/Classes/Validation/Validator/UrlValidator.php @@ -0,0 +1,45 @@ +<?php +declare(strict_types=1); +namespace TYPO3\CMS\Extbase\Validation\Validator; + +/* + * This file is part of the TYPO3 CMS project. + * + * It is free software; you can redistribute it and/or modify it under + * the terms of the GNU General Public License, either version 2 + * of the License, or any later version. + * + * For the full copyright and license information, please read the + * LICENSE.txt file that was distributed with this source code. + * + * The TYPO3 project - inspiring people to share! + */ + +use TYPO3\CMS\Core\Utility\GeneralUtility; + +/** + * Validator for url. + * + * @api + */ +class UrlValidator extends AbstractValidator +{ + /** + * Checks if the given value is a string. + * + * @param mixed $value The value that should be validated + * @api + */ + public function isValid($value) + { + if (!is_string($value) || !GeneralUtility::isValidUrl($value)) { + $this->addError( + $this->translateErrorMessage( + 'validator.url.notvalid', + 'extbase' + ), + 1238108078 + ); + } + } +} diff --git a/typo3/sysext/extbase/Resources/Private/Language/locallang.xlf b/typo3/sysext/extbase/Resources/Private/Language/locallang.xlf index 731f2062791da7e629c9fcb5cf5ee59b862f2440..a2b9a809bec1e757784338be37212bcfd5ca8ef4 100644 --- a/typo3/sysext/extbase/Resources/Private/Language/locallang.xlf +++ b/typo3/sysext/extbase/Resources/Private/Language/locallang.xlf @@ -69,6 +69,9 @@ <trans-unit id="validator.boolean.notfalse"> <source>The given subject was not false.</source> </trans-unit> + <trans-unit id="validator.url.notvalid"> + <source>The given subject is no valid URL.</source> + </trans-unit> </body> </file> </xliff> diff --git a/typo3/sysext/extbase/Tests/Unit/Validation/Validator/UrlValidatorTest.php b/typo3/sysext/extbase/Tests/Unit/Validation/Validator/UrlValidatorTest.php new file mode 100644 index 0000000000000000000000000000000000000000..a21a826393f830796c41695e472d5e637e54d8b3 --- /dev/null +++ b/typo3/sysext/extbase/Tests/Unit/Validation/Validator/UrlValidatorTest.php @@ -0,0 +1,126 @@ +<?php +declare(strict_types=1); +namespace TYPO3\CMS\Extbase\Tests\Unit\Validation\Validator; + +/* + * This file is part of the TYPO3 CMS project. + * + * It is free software; you can redistribute it and/or modify it under + * the terms of the GNU General Public License, either version 2 + * of the License, or any later version. + * + * For the full copyright and license information, please read the + * LICENSE.txt file that was distributed with this source code. + * + * The TYPO3 project - inspiring people to share! + */ + +/** + * Test case + */ +class UrlValidatorTest extends \TYPO3\TestingFramework\Core\Unit\UnitTestCase +{ + /** + * @var string + */ + protected $validatorClassName = \TYPO3\CMS\Extbase\Validation\Validator\UrlValidator::class; + + /** + * @var \TYPO3\CMS\Extbase\Validation\Validator\UrlValidator + */ + protected $validator; + + protected function setUp() + { + $this->validator = $this->getMockBuilder($this->validatorClassName) + ->setMethods(['translateErrorMessage']) + ->getMock(); + } + + /** + * @return array + */ + public function urlDataProvider(): array + { + return [ + 'Regular URL' => [ + 'value' => 'https://typo3.org/', + 'isValid' => true, + ], + 'Regular URL with subdomain' => [ + 'value' => 'https://testify.typo3.org/', + 'isValid' => true, + ], + 'Valid URL with trailing slash and path segment' => [ + 'value' => 'https://testify.typo3.org/testify/', + 'isValid' => true, + ], + 'Valid URL without trailing slash and path segment' => [ + 'value' => 'https://testify.typo3.org/testify', + 'isValid' => true, + ], + 'mailto' => [ + 'value' => 'mailto:foobar@example.com', + 'isValid' => true, + ], + 'mailto with subject' => [ + 'value' => 'mailto:foobar@example.com?subject=Unit+test+results', + 'isValid' => true, + ], + 'ftp' => [ + 'value' => 'ftp://remotestorage.org', + 'isValid' => true, + ], + 'tel' => [ + 'value' => 'tel:01189998819991197253', + 'isValid' => true, + ], + 'Some scheme that most likely does not exist' => [ + 'value' => 'monk://convert.wololo', + 'isValid' => true, + ], + 'Umlauts in domain' => [ + 'value' => 'https://bürgerkarte.at', + 'isValid' => true, + ], + 'Domain without protocol' => [ + 'value' => 'typo3.org', + 'isValid' => false, + ], + 'Empty value' => [ + 'value' => '', + 'isValid' => true, + ], + 'Null value' => [ + 'value' => null, + 'isValid' => true, + ], + 'Invalid value is only a string' => [ + 'value' => 'testify', + 'isValid' => false, + ], + 'Invalid value is integer' => [ + 'value' => 1, + 'isValid' => false, + ], + 'Invalid value is object' => [ + 'value' => new \stdClass, + 'isValid' => false, + ], + 'Invalid value is closure' => [ + 'value' => function () { + }, + 'isValid' => false, + ], + ]; + } + + /** + * @test + * @dataProvider urlDataProvider + */ + public function urlValidatorDetectsUrlsCorrectly($value, $expected) + { + $this->assertSame($expected, !$this->validator->validate($value)->hasErrors()); + } +}