Code Coverage
 
Lines
Functions and Methods
Classes and Traits
Total
88.17% covered (warning)
88.17%
82 / 93
66.67% covered (warning)
66.67%
6 / 9
CRAP
0.00% covered (danger)
0.00%
0 / 1
DeprecationHelper
89.13% covered (warning)
89.13%
82 / 92
66.67% covered (warning)
66.67%
6 / 9
39.85
0.00% covered (danger)
0.00%
0 / 1
 deprecatePublicProperty
100.00% covered (success)
100.00%
8 / 8
100.00% covered (success)
100.00%
1 / 1
3
 deprecatePublicPropertyFallback
100.00% covered (success)
100.00%
10 / 10
100.00% covered (success)
100.00%
1 / 1
3
 deprecateDynamicPropertiesAccess
100.00% covered (success)
100.00%
1 / 1
100.00% covered (success)
100.00%
1 / 1
2
 __isset
53.33% covered (warning)
53.33%
8 / 15
0.00% covered (danger)
0.00%
0 / 1
7.54
 __get
94.12% covered (success)
94.12%
16 / 17
0.00% covered (danger)
0.00%
0 / 1
7.01
 __set
90.91% covered (success)
90.91%
20 / 22
0.00% covered (danger)
0.00%
0 / 1
8.05
 deprecationHelperGetPropertyOwner
100.00% covered (success)
100.00%
9 / 9
100.00% covered (success)
100.00%
1 / 1
4
 deprecationHelperCallGetter
100.00% covered (success)
100.00%
5 / 5
100.00% covered (success)
100.00%
1 / 1
3
 deprecationHelperCallSetter
100.00% covered (success)
100.00%
5 / 5
100.00% covered (success)
100.00%
1 / 1
3
1<?php
2/**
3 * This program is free software; you can redistribute it and/or modify
4 * it under the terms of the GNU General Public License as published by
5 * the Free Software Foundation; either version 2 of the License, or
6 * (at your option) any later version.
7 *
8 * This program is distributed in the hope that it will be useful,
9 * but WITHOUT ANY WARRANTY; without even the implied warranty of
10 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
11 * GNU General Public License for more details.
12 *
13 * You should have received a copy of the GNU General Public License along
14 * with this program; if not, write to the Free Software Foundation, Inc.,
15 * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
16 * http://www.gnu.org/copyleft/gpl.html
17 *
18 * @file
19 */
20
21namespace MediaWiki\Debug;
22
23use ReflectionFunction;
24use ReflectionProperty;
25
26/**
27 * Trait for issuing warnings on deprecated access.
28 *
29 * Use this trait in classes which have properties for which public access
30 * is deprecated or implementation has been moved to another class.
31 * Set the list of properties in $deprecatedPublicProperties
32 * and make the properties non-public. The trait will preserve public access
33 * but issue deprecation warnings when it is needed.
34 *
35 * Example usage:
36 *     class Foo {
37 *         use DeprecationHelper;
38 *         protected $bar;
39 *         public function __construct() {
40 *             $this->deprecatePublicProperty( 'bar', '1.21', __CLASS__ );
41 *             $this->deprecatePublicPropertyFallback(
42 *                 'movedValue',
43 *                 '1.35',
44 *                 function () {
45 *                     return MediaWikiServices()::getInstance()
46 *                         ->getNewImplementationService()->getValue();
47 *                 },
48 *                 function ( $value ) {
49 *                     MediaWikiServices()::getInstance()
50 *                         ->getNewImplementationService()->setValue( $value );
51 *                 }
52 *             );
53 *         }
54 *     }
55 *
56 *     $foo = new Foo;
57 *     $foo->bar; // works but logs a warning
58 *     $foo->movedValue = 10; // works but logs a warning
59 *     $movedValue = $foo->movedValue; // also works
60 *
61 * Cannot be used with classes that have their own __get/__set methods.
62 *
63 * @since 1.32
64 */
65trait DeprecationHelper {
66
67    /**
68     * List of deprecated properties, in <property name> => [<version>, <class>,
69     * <component>, <getter>, <setter> ] format where <version> is the MediaWiki version
70     * where the property got deprecated, <class> is the
71     * the name of the class defining the property, <component> is the MediaWiki component
72     * (extension, skin etc.) for use in the deprecation warning) or null if it is MediaWiki.
73     * E.g. [ 'mNewRev' => [ '1.32', 'DifferenceEngine', null ]
74     * @var string[][]
75     */
76    protected static $deprecatedPublicProperties = [];
77
78    /**
79     * Whether to emit a deprecation warning when unknown properties are accessed.
80     *
81     * @var bool|array
82     */
83    private $dynamicPropertiesAccessDeprecated = false;
84
85    /**
86     * Mark a property as deprecated. Only use this for properties that used to be public and only
87     *   call it in the constructor.
88     *
89     * @note  Providing callbacks makes it not serializable
90     *
91     * @param string $property The name of the property.
92     * @param string $version MediaWiki version where the property became deprecated.
93     * @param string|null $class The class which has the deprecated property. This can usually be
94     *   guessed, but PHP can get confused when both the parent class and the subclass use the
95     *   trait, so it should be specified in classes meant for subclassing.
96     * @param string|null $component
97     * @see wfDeprecated()
98     */
99    protected function deprecatePublicProperty(
100        $property,
101        $version,
102        $class = null,
103        $component = null
104    ) {
105        if ( isset( self::$deprecatedPublicProperties[$property] ) ) {
106            return;
107        }
108        self::$deprecatedPublicProperties[$property] = [
109            $version,
110            $class ?: __CLASS__,
111            $component,
112            null, null
113        ];
114    }
115
116    /**
117     * Mark a removed public property as deprecated and provide fallback getter and setter callables.
118     * Only use this for properties that used to be public and only
119     * call it in the constructor.
120     *
121     * @param string $property The name of the property.
122     * @param string $version MediaWiki version where the property became deprecated.
123     * @param callable|string $getter A user provided getter that implements a `get` logic
124     *        for the property. If a string is given, it is called as a method on $this.
125     * @param callable|string|null $setter A user provided setter that implements a `set` logic
126     *        for the property. If a string is given, it is called as a method on $this.
127     * @param string|null $class The class which has the deprecated property.
128     * @param string|null $component
129     *
130     * @since 1.36
131     * @see wfDeprecated()
132     */
133    protected function deprecatePublicPropertyFallback(
134        string $property,
135        string $version,
136        $getter,
137        $setter = null,
138        $class = null,
139        $component = null
140    ) {
141        if ( isset( self::$deprecatedPublicProperties[$property] ) ) {
142            return;
143        }
144        self::$deprecatedPublicProperties[$property] = [
145            $version,
146            $class ?: __CLASS__,
147            null,
148            $getter,
149            $setter,
150            $component
151        ];
152    }
153
154    /**
155     * Emit deprecation warnings when dynamic and unknown properties
156     * are accessed.
157     *
158     * @param string $version MediaWiki version where the property became deprecated.
159     * @param string|null $class The class which has the deprecated property.
160     * @param string|null $component
161     */
162    protected function deprecateDynamicPropertiesAccess(
163        string $version,
164        string $class = null,
165        string $component = null
166    ) {