ExtensionRegistry: Avoid array_key_exists on $GLOBALS in PHP 8.1+
Passing $GLOBALS as function argument to array_key_exists creates a read only copy on each call Bug: T366547 Follow-Up: I9b46e7bc25365d01dbc86a9b2288559cb9e2cb8d Change-Id: Ic6b884141a1998e30ba1ccb054ee922d9f026404
This commit is contained in:
parent
3ee101f708
commit
f369b84194
1 changed files with 52 additions and 43 deletions
|
|
@ -467,54 +467,63 @@ class ExtensionRegistry {
|
|||
}
|
||||
|
||||
protected function exportExtractedData( array $info ) {
|
||||
foreach ( $info['globals'] as $key => $val ) {
|
||||
// If a merge strategy is set, read it and remove it from the value
|
||||
// so it doesn't accidentally end up getting set.
|
||||
if ( is_array( $val ) && isset( $val[self::MERGE_STRATEGY] ) ) {
|
||||
$mergeStrategy = $val[self::MERGE_STRATEGY];
|
||||
unset( $val[self::MERGE_STRATEGY] );
|
||||
} else {
|
||||
$mergeStrategy = 'array_merge';
|
||||
}
|
||||
if ( $info['globals'] ) {
|
||||
// Create a copy of the keys to allow fast access via isset also for null values
|
||||
// Since php8.1 always a read-only copy is created when the whole object is passed on function calls
|
||||
// (like for array_key_exists). See T366547 - https://wiki.php.net/rfc/restrict_globals_usage
|
||||
$knownGlobals = array_fill_keys( array_keys( $GLOBALS ), true );
|
||||
|
||||
if ( $mergeStrategy === 'provide_default' ) {
|
||||
if ( !array_key_exists( $key, $GLOBALS ) ) {
|
||||
$GLOBALS[$key] = $val;
|
||||
foreach ( $info['globals'] as $key => $val ) {
|
||||
// If a merge strategy is set, read it and remove it from the value
|
||||
// so it doesn't accidentally end up getting set.
|
||||
if ( is_array( $val ) && isset( $val[self::MERGE_STRATEGY] ) ) {
|
||||
$mergeStrategy = $val[self::MERGE_STRATEGY];
|
||||
unset( $val[self::MERGE_STRATEGY] );
|
||||
} else {
|
||||
$mergeStrategy = 'array_merge';
|
||||
}
|
||||
continue;
|
||||
}
|
||||
|
||||
// When at least one of the global value and the default is not an array, the merge
|
||||
// strategy is ignored and the global value will simply override the default.
|
||||
if ( array_key_exists( $key, $GLOBALS ) && ( !is_array( $GLOBALS[$key] ) || !is_array( $val ) ) ) {
|
||||
continue;
|
||||
}
|
||||
if ( $mergeStrategy === 'provide_default' ) {
|
||||
if ( !isset( $knownGlobals[$key] ) ) {
|
||||
$GLOBALS[$key] = $val;
|
||||
$knownGlobals[$key] = true;
|
||||
}
|
||||
continue;
|
||||
}
|
||||
|
||||
// Optimistic: If the global is not set, or is an empty array, replace it entirely.
|
||||
// Will be O(1) performance.
|
||||
if ( !array_key_exists( $key, $GLOBALS ) || ( is_array( $GLOBALS[$key] ) && !$GLOBALS[$key] ) ) {
|
||||
$GLOBALS[$key] = $val;
|
||||
continue;
|
||||
}
|
||||
// When at least one of the global value and the default is not an array, the merge
|
||||
// strategy is ignored and the global value will simply override the default.
|
||||
if ( isset( $knownGlobals[$key] ) && ( !is_array( $GLOBALS[$key] ) || !is_array( $val ) ) ) {
|
||||
continue;
|
||||
}
|
||||
|
||||
switch ( $mergeStrategy ) {
|
||||
case 'array_merge_recursive':
|
||||
$GLOBALS[$key] = array_merge_recursive( $GLOBALS[$key], $val );
|
||||
break;
|
||||
case 'array_replace_recursive':
|
||||
$GLOBALS[$key] = array_replace_recursive( $val, $GLOBALS[$key] );
|
||||
break;
|
||||
case 'array_plus_2d':
|
||||
$GLOBALS[$key] = wfArrayPlus2d( $GLOBALS[$key], $val );
|
||||
break;
|
||||
case 'array_plus':
|
||||
$GLOBALS[$key] += $val;
|
||||
break;
|
||||
case 'array_merge':
|
||||
$GLOBALS[$key] = array_merge( $val, $GLOBALS[$key] );
|
||||
break;
|
||||
default:
|
||||
throw new UnexpectedValueException( "Unknown merge strategy '$mergeStrategy'" );
|
||||
// Optimistic: If the global is not set, or is an empty array, replace it entirely.
|
||||
// Will be O(1) performance.
|
||||
if ( !isset( $knownGlobals[$key] ) || ( is_array( $GLOBALS[$key] ) && !$GLOBALS[$key] ) ) {
|
||||
$GLOBALS[$key] = $val;
|
||||
$knownGlobals[$key] = true;
|
||||
continue;
|
||||
}
|
||||
|
||||
switch ( $mergeStrategy ) {
|
||||
case 'array_merge_recursive':
|
||||
$GLOBALS[$key] = array_merge_recursive( $GLOBALS[$key], $val );
|
||||
break;
|
||||
case 'array_replace_recursive':
|
||||
$GLOBALS[$key] = array_replace_recursive( $val, $GLOBALS[$key] );
|
||||
break;
|
||||
case 'array_plus_2d':
|
||||
$GLOBALS[$key] = wfArrayPlus2d( $GLOBALS[$key], $val );
|
||||
break;
|
||||
case 'array_plus':
|
||||
$GLOBALS[$key] += $val;
|
||||
break;
|
||||
case 'array_merge':
|
||||
$GLOBALS[$key] = array_merge( $val, $GLOBALS[$key] );
|
||||
break;
|
||||
default:
|
||||
throw new UnexpectedValueException( "Unknown merge strategy '$mergeStrategy'" );
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
|||
Loading…
Reference in a new issue