MediaWiki  master
ExpiryDef.php
Go to the documentation of this file.
1 <?php
2 
4 
5 use InvalidArgumentException;
10 use Wikimedia\Timestamp\ConvertibleTimestamp;
11 
17 class ExpiryDef extends TypeDef {
18 
20  public const INFINITY_VALS = [ 'infinite', 'indefinite', 'infinity', 'never' ];
21 
28  public const PARAM_USE_MAX = 'param-use-max';
29 
33  public const PARAM_MAX = 'param-max';
34 
35  public function validate( $name, $value, array $settings, array $options ) {
36  try {
37  $expiry = self::normalizeExpiry( $value, TS_ISO_8601 );
38  } catch ( InvalidArgumentException $e ) {
39  $this->failure( 'badexpiry', $name, $value, $settings, $options );
40  }
41 
42  if ( $expiry !== 'infinity' && $expiry < ConvertibleTimestamp::now( TS_ISO_8601 ) ) {
43  $this->failure( 'badexpiry-past', $name, $value, $settings, $options );
44  }
45 
46  $max = $settings[self::PARAM_MAX] ?? null;
47 
48  if ( self::expiryExceedsMax( $expiry, $max ) ) {
49  $dontUseMax = empty( $settings[self::PARAM_USE_MAX] );
50  // Show warning that expiry exceeds the max, and that the max is being used instead.
51  $msg = DataMessageValue::new(
52  $dontUseMax
53  ? 'paramvalidator-badexpiry-duration'
54  : 'paramvalidator-badexpiry-duration-max',
55  [ $max ]
56  );
57  $this->failure( $msg, $name, $value, $settings, $options, $dontUseMax );
58 
59  return self::normalizeExpiry( $max, TS_ISO_8601 );
60  }
61 
62  return $expiry;
63  }
64 
65  public function getHelpInfo( $name, array $settings, array $options ) {
66  $info = parent::getHelpInfo( $name, $settings, $options );
67 
68  $info[ParamValidator::PARAM_TYPE] = MessageValue::new( 'paramvalidator-help-type-expiry' )
69  ->params( empty( $settings[ParamValidator::PARAM_ISMULTI] ) ? 1 : 2 )
70  ->textListParams(
71  // Should be quoted or monospace for presentation purposes,
72  // but textListParams() doesn't do this.
73  array_map( static function ( $val ) {
74  return "\"$val\"";
75  }, self::INFINITY_VALS )
76  );
77 
78  return $info;
79  }
80 
92  public static function normalizeExpiry( ?string $expiry = null, ?int $style = null ) {
93  if ( $expiry === null ) {
94  return null;
95  }
96  if ( in_array( $expiry, self::INFINITY_VALS, true ) ) {
97  return 'infinity';
98  }
99 
100  // ConvertibleTimestamp::time() used so we can fake the current time in ExpiryDefTest.
101  $unix = strtotime( $expiry, ConvertibleTimestamp::time() );
102  if ( $unix === false ) {
103  // Invalid expiry.
104  throw new InvalidArgumentException( "Invalid expiry value: {$expiry}" );
105  }
106 
107  // Don't pass 0, since ConvertibleTimestamp interprets that to mean the current timestamp.
108  // '00' does the right thing. Without this check, calling normalizeExpiry()
109  // with 1970-01-01T00:00:00Z incorrectly returns the current time.
110  $expiryConvertibleTimestamp = new ConvertibleTimestamp( $unix === 0 ? '00' : $unix );
111 
112  if ( $style !== null ) {
113  return $expiryConvertibleTimestamp->getTimestamp( $style );
114  }
115 
116  return $expiryConvertibleTimestamp;
117  }
118 
128  public static function normalizeUsingMaxExpiry( ?string $expiry, ?string $maxExpiryDuration, ?int $style ) {
129  if ( self::expiryExceedsMax( $expiry, $maxExpiryDuration ) ) {
130  return self::normalizeExpiry( $maxExpiryDuration, $style );
131  }
132  return self::normalizeExpiry( $expiry, $style );
133  }
134 
135  public function checkSettings( string $name, $settings, array $options, array $ret ): array {
136  $ret = parent::checkSettings( $name, $settings, $options, $ret );
137 
138  $ret['allowedKeys'][] = self::PARAM_USE_MAX;
139  $ret['allowedKeys'][] = self::PARAM_MAX;
140 
141  return $ret;
142  }
143 
151  private static function expiryExceedsMax( ?string $expiry, ?string $max = null ): bool {
152  $expiry = self::normalizeExpiry( $expiry );
153  $max = self::normalizeExpiry( $max );
154 
155  if ( !$max || !$expiry || $expiry === 'infinity' ) {
156  // Either there is no max or given expiry was invalid.
157  return false;
158  }
159 
160  return $expiry > $max;
161  }
162 
163 }
Value object representing a message for i18n with alternative machine-readable data.
static new( $key, $params=[], $code=null, array $data=null)
Static constructor for easier chaining of ->params() methods.
Value object representing a message for i18n.
static new( $key, $params=[])
Static constructor for easier chaining of ->params() methods.
Service for formatting and validating API parameters.
const PARAM_ISMULTI
(bool) Indicate that the parameter is multi-valued.
const PARAM_TYPE
(string|array) Type of the parameter.
Type definition for expiry timestamps.
Definition: ExpiryDef.php:17
validate( $name, $value, array $settings, array $options)
Validate the value.
Definition: ExpiryDef.php:35
static normalizeExpiry(?string $expiry=null, ?int $style=null)
Normalize a user-inputted expiry in ConvertibleTimestamp.
Definition: ExpiryDef.php:92
static normalizeUsingMaxExpiry(?string $expiry, ?string $maxExpiryDuration, ?int $style)
Returns a normalized expiry or the max expiry if the given expiry exceeds it.
Definition: ExpiryDef.php:128
const PARAM_MAX
(int|float) Maximum non-infinity duration.
Definition: ExpiryDef.php:33
checkSettings(string $name, $settings, array $options, array $ret)
Validate a parameter settings array.
Definition: ExpiryDef.php:135
const PARAM_USE_MAX
(bool) If truthy, the value given for the PARAM_MAX setting is used if the provided expiry exceeds it...
Definition: ExpiryDef.php:28
getHelpInfo( $name, array $settings, array $options)
Describe parameter settings in human-readable format.
Definition: ExpiryDef.php:65
Base definition for ParamValidator types.
Definition: TypeDef.php:19
failure( $failure, $name, $value, array $settings, array $options, $fatal=true)
Record a failure message.
Definition: TypeDef.php:49