Code Coverage
 
Lines
Functions and Methods
Classes and Traits
Total
100.00% covered (success)
100.00%
25 / 25
100.00% covered (success)
100.00%
6 / 6
CRAP
100.00% covered (success)
100.00%
1 / 1
DeprecatablePropertyArray
100.00% covered (success)
100.00%
25 / 25
100.00% covered (success)
100.00%
6 / 6
10
100.00% covered (success)
100.00%
1 / 1
 __construct
100.00% covered (success)
100.00%
4 / 4
100.00% covered (success)
100.00%
1 / 1
1
 offsetExists
100.00% covered (success)
100.00%
2 / 2
100.00% covered (success)
100.00%
1 / 1
1
 offsetGet
100.00% covered (success)
100.00%
4 / 4
100.00% covered (success)
100.00%
1 / 1
3
 offsetSet
100.00% covered (success)
100.00%
3 / 3
100.00% covered (success)
100.00%
1 / 1
2
 offsetUnset
100.00% covered (success)
100.00%
2 / 2
100.00% covered (success)
100.00%
1 / 1
1
 checkDeprecatedAccess
100.00% covered (success)
100.00%
10 / 10
100.00% covered (success)
100.00%
1 / 1
2
1<?php
2
3namespace MediaWiki\Debug;
4
5use ArrayAccess;
6
7/**
8 * ArrayAccess with support for deprecating access to certain offsets.
9 *
10 * It behaves mostly as a normal array, however in order to avoid instantiating
11 * deprecated properties by default, a callable initializer can be set to the property.
12 * It will be executed upon 'get'.
13 * @note Setting properties does not emit deprecation warnings.
14 *
15 * @newable
16 * @since 1.35
17 */
18class DeprecatablePropertyArray implements ArrayAccess {
19
20    /** @var array */
21    private $container;
22
23    /** @var array Map of deprecated property names to deprecation versions */
24    private $deprecatedProperties;
25
26    /** @var string */
27    private $name;
28
29    /** @var string|null */
30    private $component;
31
32    /**
33     * @param array $initializer Initial value of the array.
34     * @param array $deprecatedProperties Map of deprecated property names to versions.
35     * @param string $name Descriptive identifier for the array
36     * @param string|null $component Component to which array belongs.
37     *  If not provided, assumed to be MW Core
38     */
39    public function __construct(
40        array $initializer,
41        array $deprecatedProperties,
42        string $name,
43        ?string $component = null
44    ) {
45        $this->container = $initializer;
46        $this->deprecatedProperties = $deprecatedProperties;
47        $this->name = $name;
48        $this->component = $component;
49    }
50
51    public function offsetExists( $offset ): bool {
52        $this->checkDeprecatedAccess( $offset, 'exists' );
53        return isset( $this->container[$offset] );
54    }
55
56    #[\ReturnTypeWillChange]
57    public function offsetGet( $offset ) {
58        if ( $this->checkDeprecatedAccess( $offset, 'get' ) ) {
59            if ( is_callable( $this->container[$offset] ) ) {
60                $this->container[$offset] = call_user_func( $this->container[$offset] );
61            }
62        }
63        return $this->container[$offset] ?? null;
64    }
65
66    public function offsetSet( $offset, $value ): void {
67        if ( $offset === null ) {
68            $this->container[] = $value;
69        } else {
70            $this->container[$offset] = $value;
71        }
72    }
73
74    public function offsetUnset( $offset ): void {
75        $this->checkDeprecatedAccess( $offset, 'unset' );
76        unset( $this->container[$offset] );
77    }
78
79    /**
80     * @param string|int $offset
81     * @param string $fname
82     * @return bool
83     */
84    private function checkDeprecatedAccess( $offset, string $fname ): bool {
85        if ( array_key_exists( $offset, $this->deprecatedProperties ) ) {
86            $deprecatedVersion = $this->deprecatedProperties[$offset];
87            wfDeprecated(
88                "{$this->name} {$fname} '{$offset}'",
89                $deprecatedVersion,
90                $this->component ?? false,
91                3
92            );
93            return true;
94        }
95        return false;
96    }
97}