Code Coverage
 
Lines
Functions and Methods
Classes and Traits
Total
89.87% covered (warning)
89.87%
71 / 79
85.19% covered (warning)
85.19%
23 / 27
CRAP
0.00% covered (danger)
0.00%
0 / 1
DerivativeContext
89.87% covered (warning)
89.87%
71 / 79
85.19% covered (warning)
85.19%
23 / 27
47.10
0.00% covered (danger)
0.00%
0 / 1
 __construct
100.00% covered (success)
100.00%
1 / 1
100.00% covered (success)
100.00%
1 / 1
1
 getModules
100.00% covered (success)
100.00%
3 / 3
100.00% covered (success)
100.00%
1 / 1
2
 setModules
100.00% covered (success)
100.00%
1 / 1
100.00% covered (success)
100.00%
1 / 1
1
 getLanguage
100.00% covered (success)
100.00%
3 / 3
100.00% covered (success)
100.00%
1 / 1
2
 setLanguage
100.00% covered (success)
100.00%
3 / 3
100.00% covered (success)
100.00%
1 / 1
1
 getDirection
100.00% covered (success)
100.00%
6 / 6
100.00% covered (success)
100.00%
1 / 1
3
 setDirection
100.00% covered (success)
100.00%
2 / 2
100.00% covered (success)
100.00%
1 / 1
1
 getSkin
100.00% covered (success)
100.00%
3 / 3
100.00% covered (success)
100.00%
1 / 1
2
 setSkin
100.00% covered (success)
100.00%
2 / 2
100.00% covered (success)
100.00%
1 / 1
1
 getUser
100.00% covered (success)
100.00%
3 / 3
100.00% covered (success)
100.00%
1 / 1
2
 getUserIdentity
70.00% covered (warning)
70.00%
7 / 10
0.00% covered (danger)
0.00%
0 / 1
4.43
 getUserObj
88.89% covered (warning)
88.89%
8 / 9
0.00% covered (danger)
0.00%
0 / 1
4.02
 setUser
100.00% covered (success)
100.00%
4 / 4
100.00% covered (success)
100.00%
1 / 1
1
 getDebug
100.00% covered (success)
100.00%
3 / 3
100.00% covered (success)
100.00%
1 / 1
2
 setDebug
100.00% covered (success)
100.00%
2 / 2
100.00% covered (success)
100.00%
1 / 1
1
 getOnly
100.00% covered (success)
100.00%
3 / 3
100.00% covered (success)
100.00%
1 / 1
2
 setOnly
100.00% covered (success)
100.00%
2 / 2
100.00% covered (success)
100.00%
1 / 1
1
 getVersion
100.00% covered (success)
100.00%
3 / 3
100.00% covered (success)
100.00%
1 / 1
2
 setVersion
100.00% covered (success)
100.00%
2 / 2
100.00% covered (success)
100.00%
1 / 1
1
 getRaw
100.00% covered (success)
100.00%
3 / 3
100.00% covered (success)
100.00%
1 / 1
2
 setRaw
100.00% covered (success)
100.00%
1 / 1
100.00% covered (success)
100.00%
1 / 1
1
 isSourceMap
0.00% covered (danger)
0.00%
0 / 3
0.00% covered (danger)
0.00%
0 / 1
6
 setIsSourceMap
0.00% covered (danger)
0.00%
0 / 1
0.00% covered (danger)
0.00%
0 / 1
2
 getRequest
100.00% covered (success)
100.00%
1 / 1
100.00% covered (success)
100.00%
1 / 1
1
 getResourceLoader
100.00% covered (success)
100.00%
1 / 1
100.00% covered (success)
100.00%
1 / 1
1
 getContentOverrideCallback
100.00% covered (success)
100.00%
3 / 3
100.00% covered (success)
100.00%
1 / 1
2
 setContentOverrideCallback
100.00% covered (success)
100.00%
1 / 1
100.00% covered (success)
100.00%
1 / 1
1
1<?php
2/**
3 * @license GPL-2.0-or-later
4 * @file
5 * @author Kunal Mehta
6 */
7
8namespace MediaWiki\ResourceLoader;
9
10use MediaWiki\MediaWikiServices;
11use MediaWiki\Request\WebRequest;
12use MediaWiki\User\User;
13use MediaWiki\User\UserIdentity;
14use MediaWiki\User\UserRigorOptions;
15
16/**
17 * A mutable version of Context.
18 *
19 * Allows changing specific properties of a context object,
20 * without changing the main one. Inspired by MediaWiki's DerivativeContext.
21 *
22 * @ingroup ResourceLoader
23 * @since 1.24
24 */
25class DerivativeContext extends Context {
26    private const INHERIT_VALUE = -1;
27
28    /**
29     * @var Context
30     */
31    private $context;
32
33    /** @var int|string[] */
34    protected $modules = self::INHERIT_VALUE;
35    /** @var int|string */
36    protected $language = self::INHERIT_VALUE;
37    /** @var int|string|null */
38    protected $direction = self::INHERIT_VALUE;
39    /** @var int|string */
40    protected $skin = self::INHERIT_VALUE;
41    /** @var int|string|null */
42    protected $user = self::INHERIT_VALUE;
43    /** @var int|UserIdentity|null|false */
44    protected $userIdentity = self::INHERIT_VALUE;
45    /** @var int|User|null */
46    protected $userObj = self::INHERIT_VALUE;
47    /** @var int */
48    protected $debug = self::INHERIT_VALUE;
49    /** @var int|string|null */
50    protected $only = self::INHERIT_VALUE;
51    /** @var int|string|null */
52    protected $version = self::INHERIT_VALUE;
53    /** @var int|bool */
54    protected $raw = self::INHERIT_VALUE;
55    /** @var int|bool */
56    protected $sourcemap = self::INHERIT_VALUE;
57    /** @var int|callable|null */
58    protected $contentOverrideCallback = self::INHERIT_VALUE;
59
60    public function __construct( Context $context ) {
61        $this->context = $context;
62    }
63
64    public function getModules(): array {
65        if ( $this->modules === self::INHERIT_VALUE ) {
66            return $this->context->getModules();
67        }
68
69        return $this->modules;
70    }
71
72    /**
73     * @param string[] $modules
74     */
75    public function setModules( array $modules ) {
76        $this->modules = $modules;
77    }
78
79    public function getLanguage(): string {
80        if ( $this->language === self::INHERIT_VALUE ) {
81            return $this->context->getLanguage();
82        }
83        return $this->language;
84    }
85
86    public function setLanguage( string $language ) {
87        $this->language = $language;
88        // Invalidate direction since it is based on language
89        $this->direction = null;
90        $this->hash = null;
91    }
92
93    public function getDirection(): string {
94        if ( $this->direction === self::INHERIT_VALUE ) {
95            return $this->context->getDirection();
96        }
97        if ( $this->direction === null ) {
98            $this->direction = MediaWikiServices::getInstance()->getLanguageFactory()
99                ->getLanguage( $this->getLanguage() )->getDir();
100        }
101        return $this->direction;
102    }
103
104    public function setDirection( string $direction ) {
105        $this->direction = $direction;
106        $this->hash = null;
107    }
108
109    public function getSkin(): string {
110        if ( $this->skin === self::INHERIT_VALUE ) {
111            return $this->context->getSkin();
112        }
113        return $this->skin;
114    }
115
116    public function setSkin( string $skin ) {
117        $this->skin = $skin;
118        $this->hash = null;
119    }
120
121    public function getUser(): ?string {
122        if ( $this->user === self::INHERIT_VALUE ) {
123            return $this->context->getUser();
124        }
125        return $this->user;
126    }
127
128    public function getUserIdentity(): ?UserIdentity {
129        if ( $this->userIdentity === self::INHERIT_VALUE ) {
130            return $this->context->getUserIdentity();
131        }
132        if ( $this->userIdentity === false ) {
133            $username = $this->getUser();
134            if ( $username === null ) {
135                // Anonymous user
136                $this->userIdentity = null;
137            } else {
138                // Use provided username if valid
139                $this->userIdentity = MediaWikiServices::getInstance()
140                    ->getUserFactory()
141                    ->newFromName( $username, UserRigorOptions::RIGOR_VALID );
142            }
143        }
144        return $this->userIdentity;
145    }
146
147    public function getUserObj(): User {
148        if ( $this->userObj === self::INHERIT_VALUE ) {
149            return $this->context->getUserObj();
150        }
151        if ( $this->userObj === null ) {
152            $username = $this->getUser();
153            $userFactory = MediaWikiServices::getInstance()->getUserFactory();
154            if ( $username ) {
155                $this->userObj = $userFactory->newFromName( $username, UserRigorOptions::RIGOR_VALID );
156            }
157            $this->userObj ??= $userFactory->newAnonymous();
158        }
159        return $this->userObj;
160    }
161
162    public function setUser( ?string $user ) {
163        $this->user = $user;
164        $this->hash = null;
165        // Clear getUserObj cache
166        $this->userObj = null;
167        $this->userIdentity = false;
168    }
169
170    public function getDebug(): int {
171        if ( $this->debug === self::INHERIT_VALUE ) {
172            return $this->context->getDebug();
173        }
174        return $this->debug;
175    }
176
177    public function setDebug( int $debug ) {
178        $this->debug = $debug;
179        $this->hash = null;
180    }
181
182    public function getOnly(): ?string {
183        if ( $this->only === self::INHERIT_VALUE ) {
184            return $this->context->getOnly();
185        }
186        return $this->only;
187    }
188
189    public function setOnly( ?string $only ) {
190        $this->only = $only;
191        $this->hash = null;
192    }
193
194    public function getVersion(): ?string {
195        if ( $this->version === self::INHERIT_VALUE ) {
196            return $this->context->getVersion();
197        }
198        return $this->version;
199    }
200
201    public function setVersion( ?string $version ) {
202        $this->version = $version;
203        $this->hash = null;
204    }
205
206    public function getRaw(): bool {
207        if ( $this->raw === self::INHERIT_VALUE ) {
208            return $this->context->getRaw();
209        }
210        return $this->raw;
211    }
212
213    public function setRaw( bool $raw ) {
214        $this->raw = $raw;
215    }
216
217    public function isSourceMap(): bool {
218        if ( $this->sourcemap === self::INHERIT_VALUE ) {
219            return $this->context->isSourceMap();
220        }
221        return $this->sourcemap;
222    }
223
224    public function setIsSourceMap( bool $sourcemap ) {
225        $this->sourcemap = $sourcemap;
226    }
227
228    public function getRequest(): WebRequest {
229        return $this->context->getRequest();
230    }
231
232    public function getResourceLoader(): ResourceLoader {
233        return $this->context->getResourceLoader();
234    }
235
236    /** @inheritDoc */
237    public function getContentOverrideCallback() {
238        if ( $this->contentOverrideCallback === self::INHERIT_VALUE ) {
239            return $this->context->getContentOverrideCallback();
240        }
241        return $this->contentOverrideCallback;
242    }
243
244    /**
245     * @see self::getContentOverrideCallback
246     * @since 1.32
247     * @param callable|null|int $callback As per self::getContentOverrideCallback,
248     *  or self::INHERIT_VALUE
249     */
250    public function setContentOverrideCallback( $callback ) {
251        $this->contentOverrideCallback = $callback;
252    }
253
254}