Page MenuHomeWickedGov Phorge

ExpiryDef.php
No OneTemporary

Size
5 KB
Referenced Files
None
Subscribers
None

ExpiryDef.php

<?php
namespace Wikimedia\ParamValidator\TypeDef;
use InvalidArgumentException;
use Wikimedia\Message\DataMessageValue;
use Wikimedia\Message\MessageValue;
use Wikimedia\ParamValidator\ParamValidator;
use Wikimedia\ParamValidator\TypeDef;
use Wikimedia\Timestamp\ConvertibleTimestamp;
/**
* Type definition for expiry timestamps.
*
* @since 1.35
*/
class ExpiryDef extends TypeDef {
/** @var array Possible values that mean "doesn't expire". */
public const INFINITY_VALS = [ 'infinite', 'indefinite', 'infinity', 'never' ];
/**
* (bool) If truthy, the value given for the PARAM_MAX setting is used if the provided expiry
* exceeds it, and the 'badexpiry-duration' message is shown as a warning.
*
* If false, 'badexpiry-duration' is shown and is fatal.
*/
public const PARAM_USE_MAX = 'param-use-max';
/**
* (int|float) Maximum non-infinity duration.
*/
public const PARAM_MAX = 'param-max';
public function validate( $name, $value, array $settings, array $options ) {
$this->failIfNotString( $name, $value, $settings, $options );
try {
$expiry = self::normalizeExpiry( $value, TS_ISO_8601 );
} catch ( InvalidArgumentException $e ) {
$this->failure( 'badexpiry', $name, $value, $settings, $options );
}
if ( $expiry !== 'infinity' && $expiry < ConvertibleTimestamp::now( TS_ISO_8601 ) ) {
$this->failure( 'badexpiry-past', $name, $value, $settings, $options );
}
$max = $settings[self::PARAM_MAX] ?? null;
if ( self::expiryExceedsMax( $expiry, $max ) ) {
$dontUseMax = empty( $settings[self::PARAM_USE_MAX] );
// Show warning that expiry exceeds the max, and that the max is being used instead.
$msg = DataMessageValue::new(
$dontUseMax
? 'paramvalidator-badexpiry-duration'
: 'paramvalidator-badexpiry-duration-max',
[ $max ]
);
$this->failure( $msg, $name, $value, $settings, $options, $dontUseMax );
return self::normalizeExpiry( $max, TS_ISO_8601 );
}
return $expiry;
}
public function getHelpInfo( $name, array $settings, array $options ) {
$info = parent::getHelpInfo( $name, $settings, $options );
$info[ParamValidator::PARAM_TYPE] = MessageValue::new( 'paramvalidator-help-type-expiry' )
->params( empty( $settings[ParamValidator::PARAM_ISMULTI] ) ? 1 : 2 )
->textListParams(
// Should be quoted or monospace for presentation purposes,
// but textListParams() doesn't do this.
array_map( static function ( $val ) {
return "\"$val\"";
}, self::INFINITY_VALS )
);
return $info;
}
/**
* Normalize a user-inputted expiry in ConvertibleTimestamp.
* @param string|null $expiry
* @param int|null $style null or in a format acceptable to ConvertibleTimestamp (TS_* constants)
*
* @return ConvertibleTimestamp|string|null Timestamp as ConvertibleTimestamp if $style is null, a string
* timestamp in $style is not null, 'infinity' if $expiry is one of the self::INFINITY_VALS,
* or null if $expiry is null.
*
* @throws InvalidArgumentException if $expiry is invalid
*/
public static function normalizeExpiry( ?string $expiry = null, ?int $style = null ) {
if ( $expiry === null ) {
return null;
}
if ( in_array( $expiry, self::INFINITY_VALS, true ) ) {
return 'infinity';
}
// ConvertibleTimestamp::time() used so we can fake the current time in ExpiryDefTest.
$unix = strtotime( $expiry, ConvertibleTimestamp::time() );
if ( $unix === false ) {
// Invalid expiry.
throw new InvalidArgumentException( "Invalid expiry value: {$expiry}" );
}
// Don't pass 0, since ConvertibleTimestamp interprets that to mean the current timestamp.
// '00' does the right thing. Without this check, calling normalizeExpiry()
// with 1970-01-01T00:00:00Z incorrectly returns the current time.
$expiryConvertibleTimestamp = new ConvertibleTimestamp( $unix === 0 ? '00' : $unix );
if ( $style !== null ) {
return $expiryConvertibleTimestamp->getTimestamp( $style );
}
return $expiryConvertibleTimestamp;
}
/**
* Returns a normalized expiry or the max expiry if the given expiry exceeds it.
* @param string|null $expiry
* @param string|null $maxExpiryDuration
* @param int|null $style null or in a format acceptable to ConvertibleTimestamp (TS_* constants)
* @return ConvertibleTimestamp|string|null Timestamp as ConvertibleTimestamp if $style is null, a string
* timestamp in $style is not null, 'infinity' if $expiry is one of the self::INFINITY_VALS,
* or null if $expiry is null.
*/
public static function normalizeUsingMaxExpiry( ?string $expiry, ?string $maxExpiryDuration, ?int $style ) {
if ( self::expiryExceedsMax( $expiry, $maxExpiryDuration ) ) {
return self::normalizeExpiry( $maxExpiryDuration, $style );
}
return self::normalizeExpiry( $expiry, $style );
}
public function checkSettings( string $name, $settings, array $options, array $ret ): array {
$ret = parent::checkSettings( $name, $settings, $options, $ret );
$ret['allowedKeys'][] = self::PARAM_USE_MAX;
$ret['allowedKeys'][] = self::PARAM_MAX;
return $ret;
}
/**
* Given an expiry, test if the normalized value exceeds the given maximum.
*
* @param string|null $expiry
* @param string|null $max Relative maximum duration acceptable by strtotime() (i.e. '6 months')
* @return bool
*/
private static function expiryExceedsMax( ?string $expiry, ?string $max = null ): bool {
$expiry = self::normalizeExpiry( $expiry );
$max = self::normalizeExpiry( $max );
if ( !$max || !$expiry || $expiry === 'infinity' ) {
// Either there is no max or given expiry was invalid.
return false;
}
return $expiry > $max;
}
}

File Metadata

Mime Type
text/x-php
Expires
Sat, Oct 3, 18:28 (1 h, 17 m ago)
Storage Engine
local-disk
Storage Format
Raw Data
Storage Handle
8f/11/4638576363d8f72f102280784de0
Default Alt Text
ExpiryDef.php (5 KB)

Event Timeline