diff --git a/src/Assert.php b/src/Assert.php index 6269b44..631dfae 100644 --- a/src/Assert.php +++ b/src/Assert.php @@ -307,6 +307,37 @@ * @method static void allUuid(string[] $value, string $message = '', string $exception = '') * @method static void nullOrThrows(Closure|null $expression, string $class, string $message = '', string $exception = '') * @method static void allThrows(Closure[] $expression, string $class, string $message = '', string $exception = '') + * + * @method static void validDuration(mixed $value, string $message = '', string $exception = '') + * @method static void stringPlausibleBase64(mixed $value, string $message = '', string $exception = '') + * @method static void validDateTime(mixed $value, string $message = '', string $exception = '') + * @method static void validDateTimeZulu(mixed $value, string $message = '', string $exception = '') + * @method static void notInArray(mixed $value, array $values, string $message = '', string $exception = '') + * @method static void validURN(mixed $value, string $message = '', string $exception = '') + * @method static void validURI(mixed $value, string $message = '', string $exception = '') + * @method static void validURL(mixed $value, string $message = '', string $exception = '') + * @method static void validNCName(mixed $value, string $message = '', string $exception = '') + * @method static void validQName(mixed $value, string $message = '', string $exception = '') + * @method static void nullOrValidDuration(mixed $value, string $message = '', string $exception = '') + * @method static void nullOrStringPlausibleBase64(mixed $value, string $message = '', string $exception = '') + * @method static void nullOrValidDateTime(mixed $value, string $message = '', string $exception = '') + * @method static void nullOrValidDateTimeZulu(mixed $value, string $message = '', string $exception = '') + * @method static void nullOrNotInArray(mixed $value, array $values, string $message = '', string $exception = '') + * @method static void nullOrValidURN(mixed $value, string $message = '', string $exception = '') + * @method static void nullOrValidURI(mixed $value, string $message = '', string $exception = '') + * @method static void nullOrValidURL(mixed $value, string $message = '', string $exception = '') + * @method static void nullOrValidNCName(mixed $value, string $message = '', string $exception = '') + * @method static void nullOrValidQName(mixed $value, string $message = '', string $exception = '') + * @method static void allValidDuration(mixed $value, string $message = '', string $exception = '') + * @method static void allStringPlausibleBase64(mixed $value, string $message = '', string $exception = '') + * @method static void allValidDateTime(mixed $value, string $message = '', string $exception = '') + * @method static void allValidDateTimeZulu(mixed $value, string $message = '', string $exception = '') + * @method static void allNotInArray(mixed $value, array $values, string $message = '', string $exception = '') + * @method static void allValidURN(mixed $value, string $message = '', string $exception = '') + * @method static void allValidURI(mixed $value, string $message = '', string $exception = '') + * @method static void allValidURL(mixed $value, string $message = '', string $exception = '') + * @method static void allValidNCName(mixed $value, string $message = '', string $exception = '') + * @method static void allValidQName(mixed $value, string $message = '', string $exception = '') */ final class Assert { diff --git a/src/CustomAssertionTrait.php b/src/CustomAssertionTrait.php index d039034..7fceb62 100644 --- a/src/CustomAssertionTrait.php +++ b/src/CustomAssertionTrait.php @@ -5,6 +5,7 @@ namespace SimpleSAML\Assert; use DateTimeImmutable; // Requires ext-date +use DateTimeInterface; // Requires ext-date use InvalidArgumentException; use function array_map; @@ -17,62 +18,31 @@ /** * @package simplesamlphp/assert - * - * @method static void validDuration(mixed $value, string $message = '', string $exception = '') - * @method static void stringPlausibleBase64(mixed $value, string $message = '', string $exception = '') - * @method static void validDateTime(mixed $value, string $message = '', string $exception = '') - * @method static void validDateTimeZulu(mixed $value, string $message = '', string $exception = '') - * @method static void notInArray(mixed $value, array $values, string $message = '', string $exception = '') - * @method static void validURN(mixed $value, string $message = '', string $exception = '') - * @method static void validURI(mixed $value, string $message = '', string $exception = '') - * @method static void validURL(mixed $value, string $message = '', string $exception = '') - * @method static void validNCName(mixed $value, string $message = '', string $exception = '') - * @method static void validQName(mixed $value, string $message = '', string $exception = '') - * @method static void nullOrValidDuration(mixed $value, string $message = '', string $exception = '') - * @method static void nullOrStringPlausibleBase64(mixed $value, string $message = '', string $exception = '') - * @method static void nullOrValidDateTime(mixed $value, string $message = '', string $exception = '') - * @method static void nullOrValidDateTimeZulu(mixed $value, string $message = '', string $exception = '') - * @method static void nullOrNotInArray(mixed $value, array $values, string $message = '', string $exception = '') - * @method static void nullOrValidURN(mixed $value, string $message = '', string $exception = '') - * @method static void nullOrValidURI(mixed $value, string $message = '', string $exception = '') - * @method static void nullOrValidURL(mixed $value, string $message = '', string $exception = '') - * @method static void nullOrValidNCName(mixed $value, string $message = '', string $exception = '') - * @method static void nullOrValidQName(mixed $value, string $message = '', string $exception = '') - * @method static void allValidDuration(mixed $value, string $message = '', string $exception = '') - * @method static void allStringPlausibleBase64(mixed $value, string $message = '', string $exception = '') - * @method static void allValidDateTime(mixed $value, string $message = '', string $exception = '') - * @method static void allValidDateTimeZulu(mixed $value, string $message = '', string $exception = '') - * @method static void allNotInArray(mixed $value, array $values, string $message = '', string $exception = '') - * @method static void allValidURN(mixed $value, string $message = '', string $exception = '') - * @method static void allValidURI(mixed $value, string $message = '', string $exception = '') - * @method static void allValidURL(mixed $value, string $message = '', string $exception = '') - * @method static void allValidNCName(mixed $value, string $message = '', string $exception = '') - * @method static void allValidQName(mixed $value, string $message = '', string $exception = '') */ trait CustomAssertionTrait { - /** @var non-falsy-string */ + /** @var string */ private static string $duration_regex = '/^([-+]?)P(?!$)(?:(?\d+(?:[\.\,]\d+)?)Y)?(?:(?\d+(?:[\.\,]\d+)?)M)?(?:(?\d+(?:[\.\,]\d+)?)W)?(?:(?\d+(?:[\.\,]\d+)?)D)?(T(?=\d)(?:(?\d+(?:[\.\,]\d+)?)H)?(?:(?\d+(?:[\.\,]\d+)?)M)?(?:(?\d+(?:[\.\,]\d+)?)S)?)?$/'; - /** @var non-falsy-string */ + /** @var string */ private static string $qname_regex = '/^[a-zA-Z_][\w.-]*:[a-zA-Z_][\w.-]*$/'; - /** @var non-falsy-string */ + /** @var string */ private static string $ncname_regex = '/^[a-zA-Z_][\w.-]*$/'; - /** @var non-falsy-string */ + /** @var string */ private static string $base64_regex = '/^(?:[a-z0-9+\/]{4})*(?:[a-z0-9+\/]{2}==|[a-z0-9+\/]{3}=)?$/i'; - /** @var non-falsy-string */ + /** @var string */ private static string $uri_same_document_regex = '#^(?:\#([A-Za-z][A-Za-z0-9+\-.]*:(?:\/\/(?:(?:[A-Za-z0-9\-._~!$&\'()*+,;=:]|%[0-9A-Fa-f]{2})*@)?(?:\[(?:(?:(?:(?:[0-9A-Fa-f]{1,4}:){6}|::(?:[0-9A-Fa-f]{1,4}:){5}|(?:[0-9A-Fa-f]{1,4})?::(?:[0-9A-Fa-f]{1,4}:){4}|(?:(?:[0-9A-Fa-f]{1,4}:){0,1}[0-9A-Fa-f]{1,4})?::(?:[0-9A-Fa-f]{1,4}:){3}|(?:(?:[0-9A-Fa-f]{1,4}:){0,2}[0-9A-Fa-f]{1,4})?::(?:[0-9A-Fa-f]{1,4}:){2}|(?:(?:[0-9A-Fa-f]{1,4}:){0,3}[0-9A-Fa-f]{1,4})?::[0-9A-Fa-f]{1,4}:|(?:(?:[0-9A-Fa-f]{1,4}:){0,4}[0-9A-Fa-f]{1,4})?::)(?:[0-9A-Fa-f]{1,4}:[0-9A-Fa-f]{1,4}|(?:(?:25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?)\.){3}(?:25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?))|(?:(?:[0-9A-Fa-f]{1,4}:){0,5}[0-9A-Fa-f]{1,4})?::[0-9A-Fa-f]{1,4}|(?:(?:[0-9A-Fa-f]{1,4}:){0,6}[0-9A-Fa-f]{1,4})?::)|[Vv][0-9A-Fa-f]+\.[A-Za-z0-9\-._~!$&\'()*+,;=:]+)\]|(?:(?:25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?)\.){3}(?:25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?)|(?:[A-Za-z0-9\-._~!$&\'()*+,;=]|%[0-9A-Fa-f]{2})*)(?::[0-9]*)?(?:\/(?:[A-Za-z0-9\-._~!$&\'()*+,;=:@]|%[0-9A-Fa-f]{2})*)*|\/(?:(?:[A-Za-z0-9\-._~!$&\'()*+,;=:@]|%[0-9A-Fa-f]{2})+(?:\/(?:[A-Za-z0-9\-._~!$&\'()*+,;=:@]|%[0-9A-Fa-f]{2})*)*)?|(?:[A-Za-z0-9\-._~!$&\'()*+,;=:@]|%[0-9A-Fa-f]{2})+(?:\/(?:[A-Za-z0-9\-._~!$&\'()*+,;=:@]|%[0-9A-Fa-f]{2})*)*|)(?:\?(?:[A-Za-z0-9\-._~!$&\'()*+,;=:@/?]|%[0-9A-Fa-f]{2})*)?(?:\#(?:[A-Za-z0-9\-._~!$&\'()*+,;=:@/?]|%[0-9A-Fa-f]{2})*)?|(?:\/\/(?:(?:[A-Za-z0-9\-._~!$&\'()*+,;=:]|%[0-9A-Fa-f]{2})*@)?(?:\[(?:(?:(?:(?:[0-9A-Fa-f]{1,4}:){6}|::(?:[0-9A-Fa-f]{1,4}:){5}|(?:[0-9A-Fa-f]{1,4})?::(?:[0-9A-Fa-f]{1,4}:){4}|(?:(?:[0-9A-Fa-f]{1,4}:){0,1}[0-9A-Fa-f]{1,4})?::(?:[0-9A-Fa-f]{1,4}:){3}|(?:(?:[0-9A-Fa-f]{1,4}:){0,2}[0-9A-Fa-f]{1,4})?::(?:[0-9A-Fa-f]{1,4}:){2}|(?:(?:[0-9A-Fa-f]{1,4}:){0,3}[0-9A-Fa-f]{1,4})?::[0-9A-Fa-f]{1,4}:|(?:(?:[0-9A-Fa-f]{1,4}:){0,4}[0-9A-Fa-f]{1,4})?::)(?:[0-9A-Fa-f]{1,4}:[0-9A-Fa-f]{1,4}|(?:(?:25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?)\.){3}(?:25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?))|(?:(?:[0-9A-Fa-f]{1,4}:){0,5}[0-9A-Fa-f]{1,4})?::[0-9A-Fa-f]{1,4}|(?:(?:[0-9A-Fa-f]{1,4}:){0,6}[0-9A-Fa-f]{1,4})?::)|[Vv][0-9A-Fa-f]+\.[A-Za-z0-9\-._~!$&\'()*+,;=:]+)\]|(?:(?:25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?)\.){3}(?:25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?)|(?:[A-Za-z0-9\-._~!$&\'()*+,;=]|%[0-9A-Fa-f]{2})*)(?::[0-9]*)?(?:\/(?:[A-Za-z0-9\-._~!$&\'()*+,;=:@]|%[0-9A-Fa-f]{2})*)*|\/(?:(?:[A-Za-z0-9\-._~!$&\'()*+,;=:@]|%[0-9A-Fa-f]{2})+(?:\/(?:[A-Za-z0-9\-._~!$&\'()*+,;=:@]|%[0-9A-Fa-f]{2})*)*)?|(?:[A-Za-z0-9\-._~!$&\'()*+,;=@]|%[0-9A-Fa-f]{2})+(?:\/(?:[A-Za-z0-9\-._~!$&\'()*+,;=:@]|%[0-9A-Fa-f]{2})*)*|)(?:\?(?:[A-Za-z0-9\-._~!$&\'()*+,;=:@/?]|%[0-9A-Fa-f]{2})*)?(?:\#(?:[A-Za-z0-9\-._~!$&\'()*+,;=:@/?]|%[0-9A-Fa-f]{2})*)?))$#'; - /** @var non-falsy-string */ + /** @var string */ private static string $urn_regex = '/\A(?i:urn:(?!urn:)(?[a-z0-9][a-z0-9-]{1,31}):(?(?:[-a-z0-9()+,.:=@;$_!*\'&~\/]|%[0-9a-f]{2})+)(?:\?\+(?.*?))?(?:\?=(?.*?))?(?:#(?.*?))?)\z/'; - /** @var non-falsy-string */ + /** @var string */ private static string $uri_regex = '#[A-Za-z][A-Za-z0-9+\-.]*:(?:\/\/(?:(?:[A-Za-z0-9\-._~!$&\'()*+,;=:]|%[0-9A-Fa-f]{2})*@)?(?:\[(?:(?:(?:(?:[0-9A-Fa-f]{1,4}:){6}|::(?:[0-9A-Fa-f]{1,4}:){5}|(?:[0-9A-Fa-f]{1,4})?::(?:[0-9A-Fa-f]{1,4}:){4}|(?:(?:[0-9A-Fa-f]{1,4}:){0,1}[0-9A-Fa-f]{1,4})?::(?:[0-9A-Fa-f]{1,4}:){3}|(?:(?:[0-9A-Fa-f]{1,4}:){0,2}[0-9A-Fa-f]{1,4})?::(?:[0-9A-Fa-f]{1,4}:){2}|(?:(?:[0-9A-Fa-f]{1,4}:){0,3}[0-9A-Fa-f]{1,4})?::[0-9A-Fa-f]{1,4}:|(?:(?:[0-9A-Fa-f]{1,4}:){0,4}[0-9A-Fa-f]{1,4})?::)(?:[0-9A-Fa-f]{1,4}:[0-9A-Fa-f]{1,4}|(?:(?:25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?)\.){3}(?:25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?))|(?:(?:[0-9A-Fa-f]{1,4}:){0,5}[0-9A-Fa-f]{1,4})?::[0-9A-Fa-f]{1,4}|(?:(?:[0-9A-Fa-f]{1,4}:){0,6}[0-9A-Fa-f]{1,4})?::)|[Vv][0-9A-Fa-f]+\.[A-Za-z0-9\-._~!$&\'()*+,;=:]+)\]|(?:(?:25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?)\.){3}(?:25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?)|(?:[A-Za-z0-9\-._~!$&\'()*+,;=]|%[0-9A-Fa-f]{2})*)(?::[0-9]*)?(?:\/(?:[A-Za-z0-9\-._~!$&\'()*+,;=:@]|%[0-9A-Fa-f]{2})*)*|\/(?:(?:[A-Za-z0-9\-._~!$&\'()*+,;=:@]|%[0-9A-Fa-f]{2})+(?:\/(?:[A-Za-z0-9\-._~!$&\'()*+,;=:@]|%[0-9A-Fa-f]{2})*)*)?|(?:[A-Za-z0-9\-._~!$&\'()*+,;=:@]|%[0-9A-Fa-f]{2})+(?:\/(?:[A-Za-z0-9\-._~!$&\'()*+,;=:@]|%[0-9A-Fa-f]{2})*)*|)(?:\?(?:[A-Za-z0-9\-._~!$&\'()*+,;=:@/?]|%[0-9A-Fa-f]{2})*)?(?:\#(?:[A-Za-z0-9\-._~!$&\'()*+,;=:@/?]|%[0-9A-Fa-f]{2})*)?#'; - /** @var non-falsy-string */ + /** @var string */ private static string $hostname_regex = '/^(([a-zA-Z0-9]|[a-zA-Z0-9][a-zA-Z0-9\-]*[a-zA-Z0-9])\.)*([A-Za-z0-9]|[A-Za-z0-9][A-Za-z0-9\-]*[A-Za-z0-9])$/'; /*********************************************************************************** @@ -86,6 +56,7 @@ trait CustomAssertionTrait /** * @param string $value + * @param string $message */ private static function validDuration(string $value, string $message = ''): void { @@ -138,8 +109,8 @@ private static function stringPlausibleBase64(string $value, string $message = ' private static function validDateTime(string $value, string $message = ''): void { if ( - DateTimeImmutable::createFromFormat(DateTimeImmutable::ISO8601, $value) === false && - DateTimeImmutable::createFromFormat(DateTimeImmutable::RFC3339_EXTENDED, $value) === false + DateTimeImmutable::createFromFormat(DateTimeInterface::ISO8601, $value) === false && + DateTimeImmutable::createFromFormat(DateTimeInterface::RFC3339_EXTENDED, $value) === false ) { throw new InvalidArgumentException(sprintf( $message ?: '\'%s\' is not a valid DateTime', @@ -155,8 +126,8 @@ private static function validDateTime(string $value, string $message = ''): void */ private static function validDateTimeZulu(string $value, string $message = ''): void { - $dateTime1 = DateTimeImmutable::createFromFormat(DateTimeImmutable::ISO8601, $value); - $dateTime2 = DateTimeImmutable::createFromFormat(DateTimeImmutable::RFC3339_EXTENDED, $value); + $dateTime1 = DateTimeImmutable::createFromFormat(DateTimeInterface::ISO8601, $value); + $dateTime2 = DateTimeImmutable::createFromFormat(DateTimeInterface::RFC3339_EXTENDED, $value); $dateTime = $dateTime1 ?: $dateTime2; if ($dateTime === false) {