$max ) { /* translators: %d: maximum text length in characters. */ CatalogValidator::invalid( $field, sprintf( __( 'Text must not exceed %d characters.', 'abece-booking' ), $max ) ); } return $value; } public static function date( mixed $value, string $field, bool $nullable = false ): ?string { if ( null === $value && $nullable ) { return null; } $date = is_string( $value ) && preg_match( '/^[1-9][0-9]{3}-[0-9]{2}-[0-9]{2}$/D', $value ) ? DateTimeImmutable::createFromFormat( '!Y-m-d', $value ) : false; if ( ! $date || $date->format( 'Y-m-d' ) !== $value ) { CatalogValidator::invalid( $field, __( 'A valid date in YYYY-MM-DD format is required.', 'abece-booking' ) ); } return $value; } /** REST accepts an explicit timezone; the approved datetime column stores UTC. */ public static function instant( mixed $value, string $field ): ?string { if ( null === $value ) { return null; } if ( ! is_string( $value ) || ! preg_match( '/^[1-9][0-9]{3}-[0-9]{2}-[0-9]{2}T[0-9]{2}:[0-9]{2}:[0-9]{2}(Z|[+-](?:[01][0-9]|2[0-3]):[0-5][0-9])$/D', $value ) ) { CatalogValidator::invalid( $field, __( 'A valid ISO 8601 date and time with timezone is required.', 'abece-booking' ) ); } $date = DateTimeImmutable::createFromFormat( '!Y-m-d\TH:i:sP', str_replace( 'Z', '+00:00', $value ) ); if ( ! $date || $date->format( 'Y-m-d\TH:i:sP' ) !== str_replace( 'Z', '+00:00', $value ) ) { CatalogValidator::invalid( $field, __( 'A valid ISO 8601 date and time with timezone is required.', 'abece-booking' ) ); } $utc = $date->setTimezone( new DateTimeZone( 'UTC' ) ); if ( (int) $utc->format( 'Y' ) < 1000 || (int) $utc->format( 'Y' ) > 9999 ) { CatalogValidator::invalid( $field, __( 'A valid ISO 8601 date and time with timezone is required.', 'abece-booking' ) ); } return $utc->format( 'Y-m-d H:i:s' ); } }