MediaWiki  master
ResourceLoaderContext.php
Go to the documentation of this file.
1 <?php
28 use Psr\Log\LoggerInterface;
29 
38  public const DEFAULT_LANG = 'qqx';
39  public const DEFAULT_SKIN = 'fallback';
40 
42  public const DEBUG_OFF = 0;
44  public const DEBUG_LEGACY = 1;
45  private const DEBUG_MAIN = 2;
46 
48  protected $resourceLoader;
50  protected $request;
52  protected $logger;
53 
54  // Module content vary
56  protected $skin;
58  protected $language;
60  protected $debug;
62  protected $user;
63 
64  // Request vary (in addition to cache vary)
66  protected $modules;
68  protected $only;
70  protected $version;
72  protected $raw;
74  protected $image;
76  protected $variant;
78  protected $format;
79 
81  protected $direction;
83  protected $hash;
85  protected $userObj;
87  protected $userIdentity = false;
89  protected $imageObj;
90 
96  $this->resourceLoader = $resourceLoader;
97  $this->request = $request;
98  $this->logger = $resourceLoader->getLogger();
99 
100  // Optimisation: Use WebRequest::getRawVal() instead of getVal(). We don't
101  // need the slow Language+UTF logic meant for user input here. (f303bb9360)
102 
103  // List of modules
104  $modules = $request->getRawVal( 'modules' );
105  $this->modules = $modules ? ResourceLoader::expandModuleNames( $modules ) : [];
106 
107  // Various parameters
108  $this->user = $request->getRawVal( 'user' );
109  $this->debug = self::debugFromString( $request->getRawVal( 'debug' ) );
110  $this->only = $request->getRawVal( 'only' );
111  $this->version = $request->getRawVal( 'version' );
112  $this->raw = $request->getFuzzyBool( 'raw' );
113 
114  // Image requests
115  $this->image = $request->getRawVal( 'image' );
116  $this->variant = $request->getRawVal( 'variant' );
117  $this->format = $request->getRawVal( 'format' );
118 
119  $this->skin = $request->getRawVal( 'skin' );
120  $skinFactory = MediaWikiServices::getInstance()->getSkinFactory();
121  $skinnames = $skinFactory->getInstalledSkins();
122 
123  if ( !$this->skin || !isset( $skinnames[$this->skin] ) ) {
124  // The 'skin' parameter is required. (Not yet enforced.)
125  // For requests without a known skin specified,
126  // use MediaWiki's 'fallback' skin for skin-specific decisions.
127  $this->skin = self::DEFAULT_SKIN;
128  }
129  }
130 
136  public static function debugFromString( ?string $debug ): int {
137  // The canonical way to enable debug mode is via debug=true
138  // This continues to map to v1 until v2 is ready (T85805).
139  if ( $debug === 'true' || $debug === '1' ) {
140  $ret = self::DEBUG_LEGACY;
141  } elseif ( $debug === '2' ) {
142  $ret = self::DEBUG_MAIN;
143  } else {
144  $ret = self::DEBUG_OFF;
145  }
146 
147  return $ret;
148  }
149 
159  public static function newDummyContext(): ResourceLoaderContext {
160  // This currently creates a non-empty instance of ResourceLoader (all modules registered),
161  // but that's probably not needed. So once that moves into ServiceWiring, this'll
162  // become more like the EmptyResourceLoader class we have in PHPUnit tests, which
163  // is what this should've had originally. If this turns out to be untrue, change to:
164  // `MediaWikiServices::getInstance()->getResourceLoader()` instead.
165  return new self( new ResourceLoader(
166  MediaWikiServices::getInstance()->getMainConfig(),
167  LoggerFactory::getInstance( 'resourceloader' )
168  ), new FauxRequest( [] ) );
169  }
170 
171  public function getResourceLoader(): ResourceLoader {
172  return $this->resourceLoader;
173  }
174 
181  public function getConfig() {
182  wfDeprecated( __METHOD__, '1.34' );
183  return $this->getResourceLoader()->getConfig();
184  }
185 
186  public function getRequest(): WebRequest {
187  return $this->request;
188  }
189 
196  public function getLogger() {
197  return $this->logger;
198  }
199 
200  public function getModules(): array {
201  return $this->modules;
202  }
203 
204  public function getLanguage(): string {
205  if ( $this->language === null ) {
206  // Must be a valid language code after this point (T64849)
207  // Only support uselang values that follow built-in conventions (T102058)
208  $lang = $this->getRequest()->getRawVal( 'lang', '' );
209  '@phan-var string $lang'; // getRawVal does not return null here
210  // Stricter version of RequestContext::sanitizeLangCode()
211  $validBuiltinCode = MediaWikiServices::getInstance()->getLanguageNameUtils()
212  ->isValidBuiltInCode( $lang );
213  if ( !$validBuiltinCode ) {
214  // The 'lang' parameter is required. (Not yet enforced.)
215  // If omitted, localise with the dummy language code.
217  }
218  $this->language = $lang;
219  }
220  return $this->language;
221  }
222 
223  public function getDirection(): string {
224  if ( $this->direction === null ) {
225  $direction = $this->getRequest()->getRawVal( 'dir' );
226  if ( $direction === 'ltr' || $direction === 'rtl' ) {
227  $this->direction = $direction;
228  } else {
229  // Determine directionality based on user language (T8100)
230  $this->direction = MediaWikiServices::getInstance()->getLanguageFactory()
231  ->getLanguage( $this->getLanguage() )->getDir();
232  }
233  }
234  return $this->direction;
235  }
236 
237  public function getSkin(): string {
238  return $this->skin;
239  }
240 
244  public function getUser(): ?string {
245  return $this->user;
246  }
247 
257  public function msg( $key, ...$params ): Message {
258  return wfMessage( $key, ...$params )
259  // Do not use MediaWiki user language from session. Use the provided one instead.
260  ->inLanguage( $this->getLanguage() )
261  // inLanguage() clears the interface flag, so we need re-enable it. (T291601)
262  ->setInterfaceMessageFlag( true )
263  // Use a dummy title because there is no real title for this endpoint, and the cache won't
264  // vary on it anyways.
265  ->page( PageReferenceValue::localReference( NS_SPECIAL, 'Badtitle/ResourceLoaderContext' ) );
266  }
267 
277  public function getUserIdentity(): ?UserIdentity {
278  if ( $this->userIdentity === false ) {
279  $username = $this->getUser();
280  if ( $username === null ) {
281  // Anonymous user
282  $this->userIdentity = null;
283  } else {
284  // Use provided username if valid
285  $this->userIdentity = MediaWikiServices::getInstance()
286  ->getUserFactory()
287  ->newFromName( $username, UserFactory::RIGOR_VALID );
288  }
289  }
290  return $this->userIdentity;
291  }
292 
299  public function getUserObj(): User {
300  if ( $this->userObj === null ) {
301  $username = $this->getUser();
302  if ( $username ) {
303  // Use provided username if valid, fallback to anonymous user
304  $this->userObj = User::newFromName( $username ) ?: new User;
305  } else {
306  // Anonymous user
307  $this->userObj = new User;
308  }
309  }
310 
311  return $this->userObj;
312  }
313 
314  public function getDebug(): int {
315  return $this->debug;
316  }
317 
321  public function getOnly(): ?string {
322  return $this->only;
323  }
324 
330  public function getVersion(): ?string {
331  return $this->version;
332  }
333 
334  public function getRaw(): bool {
335  return $this->raw;
336  }
337 
341  public function getImage(): ?string {
342  return $this->image;
343  }
344 
348  public function getVariant(): ?string {
349  return $this->variant;
350  }
351 
355  public function getFormat(): ?string {
356  return $this->format;
357  }
358 
365  public function getImageObj() {
366  if ( $this->imageObj === null ) {
367  $this->imageObj = false;
368 
369  if ( !$this->image ) {
370  return $this->imageObj;
371  }
372 
373  $modules = $this->getModules();
374  if ( count( $modules ) !== 1 ) {
375  return $this->imageObj;
376  }
377 
378  $module = $this->getResourceLoader()->getModule( $modules[0] );
379  if ( !$module || !$module instanceof ResourceLoaderImageModule ) {
380  return $this->imageObj;
381  }
382 
383  $image = $module->getImage( $this->image, $this );
384  if ( !$image ) {
385  return $this->imageObj;
386  }
387 
388  $this->imageObj = $image;
389  }
390 
391  return $this->imageObj;
392  }
393 
406  public function getContentOverrideCallback() {
407  return null;
408  }
409 
410  public function shouldIncludeScripts(): bool {
411  return $this->getOnly() === null || $this->getOnly() === 'scripts';
412  }
413 
414  public function shouldIncludeStyles(): bool {
415  return $this->getOnly() === null || $this->getOnly() === 'styles';
416  }
417 
418  public function shouldIncludeMessages(): bool {
419  return $this->getOnly() === null;
420  }
421 
433  public function getHash(): string {
434  if ( $this->hash === null ) {
435  $this->hash = implode( '|', [
436  // Module content vary
437  $this->getLanguage(),
438  $this->getSkin(),
439  (string)$this->getDebug(),
440  $this->getUser() ?? '',
441  // Request vary
442  $this->getOnly() ?? '',
443  $this->getVersion() ?? '',
444  (string)$this->getRaw(),
445  $this->getImage() ?? '',
446  $this->getVariant() ?? '',
447  $this->getFormat() ?? '',
448  ] );
449  }
450  return $this->hash;
451  }
452 
459  public function getReqBase(): array {
460  $reqBase = [];
461  $lang = $this->getLanguage();
462  if ( $lang !== self::DEFAULT_LANG ) {
463  $reqBase['lang'] = $lang;
464  }
465  $skin = $this->getSkin();
466  if ( $skin !== self::DEFAULT_SKIN ) {
467  $reqBase['skin'] = $skin;
468  }
469  $debug = $this->getDebug();
470  if ( $debug !== self::DEBUG_OFF ) {
471  $reqBase['debug'] = strval( $debug );
472  }
473  return $reqBase;
474  }
475 
484  public function encodeJson( $data ) {
485  // Keep output as small as possible by disabling needless escape modes
486  // that PHP uses by default.
487  // However, while most module scripts are only served on HTTP responses
488  // for JavaScript, some modules can also be embedded in the HTML as inline
489  // scripts. This, and the fact that we sometimes need to export strings
490  // containing user-generated content and labels that may genuinely contain
491  // a sequences like "</script>", we need to encode either '/' or '<'.
492  // By default PHP escapes '/'. Let's escape '<' instead which is less common
493  // and allows URLs to mostly remain readable.
494  $jsonFlags = JSON_UNESCAPED_SLASHES |
495  JSON_UNESCAPED_UNICODE |
496  JSON_HEX_TAG |
497  JSON_HEX_AMP;
498  if ( $this->getDebug() ) {
499  $jsonFlags |= JSON_PRETTY_PRINT;
500  }
501  return json_encode( $data, $jsonFlags );
502  }
503 }
ResourceLoaderContext
Context object that contains information about the state of a specific ResourceLoader web request.
Definition: ResourceLoaderContext.php:37
ResourceLoaderContext\getReqBase
getReqBase()
Get the request base parameters, omitting any defaults.
Definition: ResourceLoaderContext.php:459
ResourceLoaderContext\getConfig
getConfig()
Definition: ResourceLoaderContext.php:181
FauxRequest
WebRequest clone which takes values from a provided array.
Definition: FauxRequest.php:36
ResourceLoaderContext\getDirection
getDirection()
Definition: ResourceLoaderContext.php:223
ResourceLoaderContext\getUserIdentity
getUserIdentity()
Get the possibly-cached UserIdentity object for the specified username.
Definition: ResourceLoaderContext.php:277
ResourceLoaderContext\newDummyContext
static newDummyContext()
Return a dummy ResourceLoaderContext object suitable for passing into things that don't "really" need...
Definition: ResourceLoaderContext.php:159
MediaWiki\MediaWikiServices
MediaWikiServices is the service locator for the application scope of MediaWiki.
Definition: MediaWikiServices.php:203
$lang
if(!isset( $args[0])) $lang
Definition: testCompression.php:37
ResourceLoaderContext\getResourceLoader
getResourceLoader()
Definition: ResourceLoaderContext.php:171
ResourceLoaderContext\getImage
getImage()
Definition: ResourceLoaderContext.php:341
ResourceLoaderContext\getModules
getModules()
Definition: ResourceLoaderContext.php:200
ResourceLoader\getLogger
getLogger()
Definition: ResourceLoader.php:286
ResourceLoaderContext\getContentOverrideCallback
getContentOverrideCallback()
Return the replaced-content mapping callback.
Definition: ResourceLoaderContext.php:406
ResourceLoaderContext\$language
string $language
Definition: ResourceLoaderContext.php:58
User\newFromName
static newFromName( $name, $validate='valid')
Definition: User.php:595
ResourceLoaderContext\$variant
string null $variant
Definition: ResourceLoaderContext.php:76
wfMessage
wfMessage( $key,... $params)
This is the function for getting translated interface messages.
Definition: GlobalFunctions.php:1167
ResourceLoaderContext\getOnly
getOnly()
Definition: ResourceLoaderContext.php:321
ResourceLoaderContext\DEBUG_LEGACY
const DEBUG_LEGACY
Definition: ResourceLoaderContext.php:44
MediaWiki\User\UserIdentity
Interface for objects representing user identity.
Definition: UserIdentity.php:39
ResourceLoaderContext\getVariant
getVariant()
Definition: ResourceLoaderContext.php:348
ResourceLoaderContext\getFormat
getFormat()
Definition: ResourceLoaderContext.php:355
ResourceLoaderContext\$logger
LoggerInterface $logger
Definition: ResourceLoaderContext.php:52
MessageLocalizer
Interface for localizing messages in MediaWiki.
Definition: MessageLocalizer.php:29
NS_SPECIAL
const NS_SPECIAL
Definition: Defines.php:53
ResourceLoaderContext\DEBUG_OFF
const DEBUG_OFF
Definition: ResourceLoaderContext.php:42
wfDeprecated
wfDeprecated( $function, $version=false, $component=false, $callerOffset=2)
Logs a warning that a deprecated feature was used.
Definition: GlobalFunctions.php:997
MediaWiki\Logger\LoggerFactory
PSR-3 logger instance factory.
Definition: LoggerFactory.php:45
ResourceLoaderContext\getRequest
getRequest()
Definition: ResourceLoaderContext.php:186
ResourceLoaderContext\$userIdentity
UserIdentity null false $userIdentity
Definition: ResourceLoaderContext.php:87
ResourceLoaderContext\$modules
string[] $modules
Definition: ResourceLoaderContext.php:66
ResourceLoaderContext\getDebug
getDebug()
Definition: ResourceLoaderContext.php:314
ResourceLoaderContext\getLanguage
getLanguage()
Definition: ResourceLoaderContext.php:204
ResourceLoaderContext\getVersion
getVersion()
Definition: ResourceLoaderContext.php:330
ResourceLoaderContext\shouldIncludeStyles
shouldIncludeStyles()
Definition: ResourceLoaderContext.php:414
WebRequest\getRawVal
getRawVal( $name, $default=null)
Fetch a string WITHOUT any Unicode or line break normalization.
Definition: WebRequest.php:478
ResourceLoaderContext\msg
msg( $key,... $params)
Get a Message object with context set.
Definition: ResourceLoaderContext.php:257
ResourceLoaderContext\$request
WebRequest $request
Definition: ResourceLoaderContext.php:50
ResourceLoaderImage
Class encapsulating an image used in a ResourceLoaderImageModule.
Definition: ResourceLoaderImage.php:32
ResourceLoaderContext\$version
string null $version
Definition: ResourceLoaderContext.php:70
ResourceLoaderContext\$debug
int $debug
Definition: ResourceLoaderContext.php:60
ResourceLoaderContext\DEFAULT_SKIN
const DEFAULT_SKIN
Definition: ResourceLoaderContext.php:39
ResourceLoaderContext\$only
string null $only
Definition: ResourceLoaderContext.php:68
ResourceLoaderContext\__construct
__construct(ResourceLoader $resourceLoader, WebRequest $request)
Definition: ResourceLoaderContext.php:95
ResourceLoaderContext\DEFAULT_LANG
const DEFAULT_LANG
Definition: ResourceLoaderContext.php:38
ResourceLoaderContext\$userObj
User null $userObj
Definition: ResourceLoaderContext.php:85
ResourceLoaderContext\shouldIncludeMessages
shouldIncludeMessages()
Definition: ResourceLoaderContext.php:418
ResourceLoaderContext\$resourceLoader
ResourceLoader $resourceLoader
Definition: ResourceLoaderContext.php:48
ResourceLoader\expandModuleNames
static expandModuleNames( $modules)
Expand a string of the form jquery.foo,bar|jquery.ui.baz,quux to an array of module names like ‘[ 'jq...
Definition: ResourceLoader.php:1671
ResourceLoaderContext\getSkin
getSkin()
Definition: ResourceLoaderContext.php:237
ResourceLoaderContext\shouldIncludeScripts
shouldIncludeScripts()
Definition: ResourceLoaderContext.php:410
ResourceLoaderContext\$direction
string null $direction
Definition: ResourceLoaderContext.php:81
ResourceLoaderContext\getUser
getUser()
Definition: ResourceLoaderContext.php:244
WebRequest
The WebRequest class encapsulates getting at data passed in the URL or via a POSTed form stripping il...
Definition: WebRequest.php:43
ResourceLoaderContext\$imageObj
ResourceLoaderImage false $imageObj
Definition: ResourceLoaderContext.php:89
ResourceLoaderContext\getLogger
getLogger()
Definition: ResourceLoaderContext.php:196
ResourceLoaderContext\$raw
bool $raw
Definition: ResourceLoaderContext.php:72
ResourceLoader
ResourceLoader is a loading system for JavaScript and CSS resources.
Definition: ResourceLoader.php:59
Page\PageReferenceValue
Immutable value object representing a page reference.
Definition: PageReferenceValue.php:42
ResourceLoaderContext\$format
string null $format
Definition: ResourceLoaderContext.php:78
ResourceLoaderContext\$skin
string $skin
Definition: ResourceLoaderContext.php:56
ResourceLoaderContext\$image
string null $image
Definition: ResourceLoaderContext.php:74
Message
The Message class deals with fetching and processing of interface message into a variety of formats.
Definition: Message.php:139
ResourceLoaderContext\debugFromString
static debugFromString(?string $debug)
Definition: ResourceLoaderContext.php:136
ResourceLoaderContext\getHash
getHash()
All factors that uniquely identify this request, except 'modules'.
Definition: ResourceLoaderContext.php:433
ResourceLoaderContext\getImageObj
getImageObj()
If this is a request for an image, get the ResourceLoaderImage object.
Definition: ResourceLoaderContext.php:365
ResourceLoaderContext\$user
string null $user
Definition: ResourceLoaderContext.php:62
ResourceLoaderContext\getUserObj
getUserObj()
Get the possibly-cached User object for the specified username.
Definition: ResourceLoaderContext.php:299
ResourceLoaderContext\DEBUG_MAIN
const DEBUG_MAIN
Definition: ResourceLoaderContext.php:45
ResourceLoaderImageModule
Module for generated and embedded images.
Definition: ResourceLoaderImageModule.php:29
User
The User object encapsulates all of the user-specific settings (user_id, name, rights,...
Definition: User.php:67
WebRequest\getFuzzyBool
getFuzzyBool( $name, $default=false)
Fetch a boolean value from the input or return $default if not set.
Definition: WebRequest.php:664
ResourceLoaderContext\getRaw
getRaw()
Definition: ResourceLoaderContext.php:334
ResourceLoaderContext\encodeJson
encodeJson( $data)
Wrapper around json_encode that avoids needless escapes, and pretty-prints in debug mode.
Definition: ResourceLoaderContext.php:484
MediaWiki\User\UserFactory
Creates User objects.
Definition: UserFactory.php:41
ResourceLoaderContext\$hash
string null $hash
Definition: ResourceLoaderContext.php:83