MediaWiki  master
ResourceLoaderContext.php
Go to the documentation of this file.
1 <?php
25 
34  const DEFAULT_LANG = 'qqx';
35  const DEFAULT_SKIN = 'fallback';
36 
37  protected $resourceLoader;
38  protected $request;
39  protected $logger;
40 
41  // Module content vary
42  protected $skin;
43  protected $language;
44  protected $debug;
45  protected $user;
46 
47  // Request vary (in addition to cache vary)
48  protected $modules;
49  protected $only;
50  protected $version;
51  protected $raw;
52  protected $image;
53  protected $variant;
54  protected $format;
55 
56  protected $direction;
57  protected $hash;
58  protected $userObj;
60  protected $imageObj;
61 
67  $this->resourceLoader = $resourceLoader;
68  $this->request = $request;
69  $this->logger = $resourceLoader->getLogger();
70 
71  // Optimisation: Use WebRequest::getRawVal() instead of getVal(). We don't
72  // need the slow Language+UTF logic meant for user input here. (f303bb9360)
73 
74  // List of modules
75  $modules = $request->getRawVal( 'modules' );
76  $this->modules = $modules ? ResourceLoader::expandModuleNames( $modules ) : [];
77 
78  // Various parameters
79  $this->user = $request->getRawVal( 'user' );
80  $this->debug = $request->getRawVal( 'debug' ) === 'true';
81  $this->only = $request->getRawVal( 'only' );
82  $this->version = $request->getRawVal( 'version' );
83  $this->raw = $request->getFuzzyBool( 'raw' );
84 
85  // Image requests
86  $this->image = $request->getRawVal( 'image' );
87  $this->variant = $request->getRawVal( 'variant' );
88  $this->format = $request->getRawVal( 'format' );
89 
90  $this->skin = $request->getRawVal( 'skin' );
91  $skinnames = Skin::getSkinNames();
92  if ( !$this->skin || !isset( $skinnames[$this->skin] ) ) {
93  // The 'skin' parameter is required. (Not yet enforced.)
94  // For requests without a known skin specified,
95  // use MediaWiki's 'fallback' skin for skin-specific decisions.
96  $this->skin = self::DEFAULT_SKIN;
97  }
98  }
99 
109  public static function newDummyContext() : ResourceLoaderContext {
110  // This currently creates a non-empty instance of ResourceLoader (all modules registered),
111  // but that's probably not needed. So once that moves into ServiceWiring, this'll
112  // become more like the EmptyResourceLoader class we have in PHPUnit tests, which
113  // is what this should've had originally. If this turns out to be untrue, change to:
114  // `MediaWikiServices::getInstance()->getResourceLoader()` instead.
115  return new self( new ResourceLoader(
116  MediaWikiServices::getInstance()->getMainConfig(),
117  LoggerFactory::getInstance( 'resourceloader' )
118  ), new FauxRequest( [] ) );
119  }
120 
121  public function getResourceLoader() : ResourceLoader {
122  return $this->resourceLoader;
123  }
124 
131  public function getConfig() {
132  wfDeprecated( __METHOD__, '1.34' );
133  return $this->getResourceLoader()->getConfig();
134  }
135 
136  public function getRequest() : WebRequest {
137  return $this->request;
138  }
139 
146  public function getLogger() {
147  return $this->logger;
148  }
149 
150  public function getModules() : array {
151  return $this->modules;
152  }
153 
154  public function getLanguage() : string {
155  if ( $this->language === null ) {
156  // Must be a valid language code after this point (T64849)
157  // Only support uselang values that follow built-in conventions (T102058)
158  $lang = $this->getRequest()->getRawVal( 'lang', '' );
159  // Stricter version of RequestContext::sanitizeLangCode()
161  // The 'lang' parameter is required. (Not yet enforced.)
162  // If omitted, localise with the dummy language code.
163  $lang = self::DEFAULT_LANG;
164  }
165  $this->language = $lang;
166  }
167  return $this->language;
168  }
169 
170  public function getDirection() : string {
171  if ( $this->direction === null ) {
172  $direction = $this->getRequest()->getRawVal( 'dir' );
173  if ( $direction === 'ltr' || $direction === 'rtl' ) {
174  $this->direction = $direction;
175  } else {
176  // Determine directionality based on user language (T8100)
177  $this->direction = MediaWikiServices::getInstance()->getLanguageFactory()
178  ->getLanguage( $this->getLanguage() )->getDir();
179  }
180  }
181  return $this->direction;
182  }
183 
184  public function getSkin() : string {
185  return $this->skin;
186  }
187 
191  public function getUser() : ?string {
192  return $this->user;
193  }
194 
204  public function msg( $key, ...$params ) : Message {
205  return wfMessage( $key, ...$params )
206  ->inLanguage( $this->getLanguage() )
207  // Use a dummy title because there is no real title
208  // for this endpoint, and the cache won't vary on it
209  // anyways.
210  ->title( Title::newFromText( 'Dwimmerlaik' ) );
211  }
212 
219  public function getUserObj() : User {
220  if ( $this->userObj === null ) {
221  $username = $this->getUser();
222  if ( $username ) {
223  // Use provided username if valid, fallback to anonymous user
224  $this->userObj = User::newFromName( $username ) ?: new User;
225  } else {
226  // Anonymous user
227  $this->userObj = new User;
228  }
229  }
230 
231  return $this->userObj;
232  }
233 
234  public function getDebug() : bool {
235  return $this->debug;
236  }
237 
241  public function getOnly() : ?string {
242  return $this->only;
243  }
244 
250  public function getVersion() : ?string {
251  return $this->version;
252  }
253 
254  public function getRaw() : bool {
255  return $this->raw;
256  }
257 
261  public function getImage() : ?string {
262  return $this->image;
263  }
264 
268  public function getVariant() : ?string {
269  return $this->variant;
270  }
271 
275  public function getFormat() : ?string {
276  return $this->format;
277  }
278 
285  public function getImageObj() {
286  if ( $this->imageObj === null ) {
287  $this->imageObj = false;
288 
289  if ( !$this->image ) {
290  return $this->imageObj;
291  }
292 
293  $modules = $this->getModules();
294  if ( count( $modules ) !== 1 ) {
295  return $this->imageObj;
296  }
297 
298  $module = $this->getResourceLoader()->getModule( $modules[0] );
299  if ( !$module || !$module instanceof ResourceLoaderImageModule ) {
300  return $this->imageObj;
301  }
302 
303  $image = $module->getImage( $this->image, $this );
304  if ( !$image ) {
305  return $this->imageObj;
306  }
307 
308  $this->imageObj = $image;
309  }
310 
311  return $this->imageObj;
312  }
313 
326  public function getContentOverrideCallback() {
327  return null;
328  }
329 
330  public function shouldIncludeScripts() : bool {
331  return $this->getOnly() === null || $this->getOnly() === 'scripts';
332  }
333 
334  public function shouldIncludeStyles() : bool {
335  return $this->getOnly() === null || $this->getOnly() === 'styles';
336  }
337 
338  public function shouldIncludeMessages() : bool {
339  return $this->getOnly() === null;
340  }
341 
353  public function getHash() : string {
354  if ( !isset( $this->hash ) ) {
355  $this->hash = implode( '|', [
356  // Module content vary
357  $this->getLanguage(),
358  $this->getSkin(),
359  $this->getDebug(),
360  $this->getUser(),
361  // Request vary
362  $this->getOnly(),
363  $this->getVersion(),
364  $this->getRaw(),
365  $this->getImage(),
366  $this->getVariant(),
367  $this->getFormat(),
368  ] );
369  }
370  return $this->hash;
371  }
372 
379  public function getReqBase() : array {
380  $reqBase = [];
381  if ( $this->getLanguage() !== self::DEFAULT_LANG ) {
382  $reqBase['lang'] = $this->getLanguage();
383  }
384  if ( $this->getSkin() !== self::DEFAULT_SKIN ) {
385  $reqBase['skin'] = $this->getSkin();
386  }
387  if ( $this->getDebug() ) {
388  $reqBase['debug'] = 'true';
389  }
390  return $reqBase;
391  }
392 
401  public function encodeJson( $data ) {
402  // Keep output as small as possible by disabling needless escape modes
403  // that PHP uses by default.
404  // However, while most module scripts are only served on HTTP responses
405  // for JavaScript, some modules can also be embedded in the HTML as inline
406  // scripts. This, and the fact that we sometimes need to export strings
407  // containing user-generated content and labels that may genuinely contain
408  // a sequences like "</script>", we need to encode either '/' or '<'.
409  // By default PHP escapes '/'. Let's escape '<' instead which is less common
410  // and allows URLs to mostly remain readable.
411  $jsonFlags = JSON_UNESCAPED_SLASHES |
412  JSON_UNESCAPED_UNICODE |
413  JSON_HEX_TAG |
414  JSON_HEX_AMP;
415  if ( $this->getDebug() ) {
416  $jsonFlags |= JSON_PRETTY_PRINT;
417  }
418  return json_encode( $data, $jsonFlags );
419  }
420 }
getRawVal( $name, $default=null)
Fetch a scalar from the input without normalization, or return $default if it&#39;s not set...
Definition: WebRequest.php:465
Module for generated and embedded images.
static newDummyContext()
Return a dummy ResourceLoaderContext object suitable for passing into things that don&#39;t "really" need...
The Message class provides methods which fulfil two basic services:
Definition: Message.php:162
if(!isset( $args[0])) $lang
static getSkinNames()
Fetch the set of available skins.
Definition: Skin.php:57
static isValidBuiltInCode( $code)
Returns true if a language code is of a valid form for the purposes of internal customisation of Medi...
Definition: Language.php:341
The User object encapsulates all of the user-specific settings (user_id, name, rights, email address, options, last login time).
Definition: User.php:51
getReqBase()
Get the request base parameters, omitting any defaults.
encodeJson( $data)
Wrapper around json_encode that avoids needless escapes, and pretty-prints in debug mode...
getContentOverrideCallback()
Return the replaced-content mapping callback.
getFuzzyBool( $name, $default=false)
Fetch a boolean value from the input or return $default if not set.
Definition: WebRequest.php:630
getUserObj()
Get the possibly-cached User object for the specified username.
wfDeprecated( $function, $version=false, $component=false, $callerOffset=2)
Throws a warning that $function is deprecated.
static expandModuleNames( $modules)
Expand a string of the form jquery.foo,bar|jquery.ui.baz,quux to an array of module names like `[ &#39;jq...
getHash()
All factors that uniquely identify this request, except &#39;modules&#39;.
__construct(ResourceLoader $resourceLoader, WebRequest $request)
getImageObj()
If this is a request for an image, get the ResourceLoaderImage object.
wfMessage( $key,... $params)
This is the function for getting translated interface messages.
static newFromName( $name, $validate='valid')
Static factory method for creation from username.
Definition: User.php:536
ResourceLoaderImage false $imageObj
msg( $key,... $params)
Get a Message object with context set.
Context object that contains information about the state of a specific ResourceLoader web request...
static newFromText( $text, $defaultNamespace=NS_MAIN)
Create a new Title from text, such as what one would find in a link.
Definition: Title.php:317