Page Menu
Home
WickedGov Phorge
Search
Configure Global Search
Log In
Files
F2751620
BannerRenderer.php
No One
Temporary
Actions
Download File
Edit File
Delete File
View Transforms
Subscribe
Flag For Later
Award Token
Size
9 KB
Referenced Files
None
Subscribers
None
BannerRenderer.php
View Options
<?php
use
MediaWiki\Context\IContextSource
;
use
MediaWiki\Html\Html
;
use
MediaWiki\MediaWikiServices
;
use
MediaWiki\ResourceLoader\ResourceLoader
;
use
MediaWiki\SpecialPage\SpecialPage
;
/**
* Produce HTML and JSON output for a given banner and context
*/
class
BannerRenderer
{
/**
* @var IContextSource
*/
private
$context
;
/**
* @var Banner
*/
private
$banner
;
/**
* Campaign in which context the rendering is taking place. Empty during preview.
* @var string
*/
private
$campaignName
=
""
;
/**
* Unsaved raw banner content to use for rendering an unsaved preview.
* @var string|null
*/
private
$previewContent
;
/**
* Associative array of banner message names and values, for rendering an unsaved
* preview.
* @var array|null
*/
private
$previewMessages
;
/** @var MixinController|null */
private
$mixinController
=
null
;
/** @var bool */
private
$debug
;
/**
* Creates a new renderer for a given banner and context
*
* @param IContextSource $context UI context, including language.
* @param Banner $banner Banner to be rendered.
* @param string|null $campaignName Which campaign we're serving. This is
* substituted in for {{{campaign}}} magic word.
* @param string|null $previewContent Unsaved raw banner content to use for rendering
* an unsaved preview.
* @param array|null $previewMessages Associative array of banner message names and
* and values, for rendering unsaved preview.
* @param bool $debug If false, minify the output.
*/
public
function
__construct
(
IContextSource
$context
,
Banner
$banner
,
$campaignName
=
null
,
$previewContent
=
null
,
$previewMessages
=
null
,
$debug
=
false
)
{
$this
->
context
=
$context
;
$this
->
banner
=
$banner
;
$this
->
campaignName
=
$campaignName
;
$this
->
previewContent
=
$previewContent
;
$this
->
previewMessages
=
$previewMessages
;
$this
->
debug
=
$debug
;
$this
->
mixinController
=
new
MixinController
(
$this
->
context
,
$this
->
banner
->
getMixins
()
);
// FIXME: it should make sense to do this:
// $this->mixinController->registerMagicWord( 'campaign', array( $this, 'getCampaign' ) );
// $this->mixinController->registerMagicWord( 'banner', array( $this, 'getBanner' ) );
}
/**
* Get the edit link for a banner (static version).
*
* @param string $name Banner name.
* @return string Edit URL.
*
* TODO Move the following method somewhere more appropriate.
*/
public
static
function
linkToBanner
(
$name
)
{
$linkRenderer
=
MediaWikiServices
::
getInstance
()->
getLinkRenderer
();
return
$linkRenderer
->
makeLink
(
SpecialPage
::
getTitleFor
(
'CentralNoticeBanners'
,
"edit/{$name}"
),
$name
,
[
'class'
=>
'cn-banner-title'
]
);
}
/**
* Return a rendered link to the Special:Random banner preview.
*
* @param string $name Banner name
* @return string HTML anchor tag
*
* TODO Move this method somewhere more appropriate.
*/
public
static
function
getPreviewLink
(
$name
)
{
$linkRenderer
=
MediaWikiServices
::
getInstance
()->
getLinkRenderer
();
// FIXME: Need a reusable way to get a known target language. We want
// to set uselang= so that the banner is rendered using an available
// translation. banner->getPriorityLanguages isn't reliable.
return
$linkRenderer
->
makeKnownLink
(
SpecialPage
::
getTitleFor
(
'Randompage'
),
wfMessage
(
'centralnotice-live-preview'
)->
text
(),
[
'class'
=>
'cn-banner-list-element-label-text'
],
[
'banner'
=>
$name
,
// TODO: 'uselang' => $language,
'force'
=>
'1'
,
]
);
}
/**
* Get the body of the banner, with all transformations applied.
*
* FIXME: "->inLanguage( $context->getLanguage() )" is necessary due to a bug
* in DerivativeContext
*
* @return string HTML fragment for the banner body.
*/
public
function
toHtml
()
{
global
$wgNoticeUseLanguageConversion
;
$parentLang
=
$lang
=
$this
->
context
->
getLanguage
();
if
(
$wgNoticeUseLanguageConversion
)
{
$parentLang
=
MediaWikiServices
::
getInstance
()->
getLanguageFactory
()
->
getParentLanguage
(
$lang
->
getCode
()
)
??
$lang
;
}
if
(
$this
->
previewContent
!==
null
)
{
// Preview mode, banner content is ephemeral
// TODO Double-check that this is the correct way to get process as a i18n
// message, and add documentation to the core method.
$bannerHtml
=
MediaWikiServices
::
getInstance
()->
getMessageCache
()->
transform
(
$this
->
previewContent
,
false
,
$parentLang
);
}
else
{
// Normal mode, banner content is stored as message
$bannerKey
=
$this
->
banner
->
getDbKey
();
$bannerContentMessage
=
$this
->
context
->
msg
(
$bannerKey
)->
inLanguage
(
$parentLang
);
if
(
!
$bannerContentMessage
->
exists
()
)
{
// Translation subsystem failure
throw
new
RuntimeException
(
"Banner message key $bannerKey could not be found in {$parentLang->getCode()}"
);
}
$bannerHtml
=
$bannerContentMessage
->
text
();
}
$bannerHtml
.=
$this
->
getResourceLoaderHtml
();
$bannerHtml
=
$this
->
substituteMagicWords
(
$bannerHtml
);
if
(
$wgNoticeUseLanguageConversion
)
{
$converter
=
MediaWikiServices
::
getInstance
()->
getLanguageConverterFactory
()
->
getLanguageConverter
(
$parentLang
);
$variant
=
$lang
->
getCode
();
if
(
$converter
->
hasVariant
(
$variant
)
)
{
$bannerHtml
=
$converter
->
convertTo
(
$bannerHtml
,
$variant
);
}
}
return
$bannerHtml
;
}
/**
* Render any preload javascript for this banner
*
* TODO: Remove/refactor. See T225831.
*
* @return string JavaScript code
*/
public
function
getPreloadJs
()
{
$code
=
$this
->
substituteMagicWords
(
$this
->
getPreloadJsRaw
()
);
// Minify the code, if any.
if
(
!
$this
->
debug
&&
$code
)
{
$code
=
ResourceLoader
::
filter
(
'minify-js'
,
$code
,
[
'cache'
=>
false
]
);
}
return
$code
;
}
/**
* Unrendered blob of preload javascript snippets
*
* This is only used internally, and will be parsed for magic words
* before use.
*
* TODO: Remove/refactor. See T225831.
*
* @return string JavaScript code
*/
public
function
getPreloadJsRaw
()
{
$snippets
=
$this
->
mixinController
->
getPreloadJsSnippets
();
return
implode
(
"
\n\n
"
,
$snippets
);
}
/**
* Render any ResourceLoader modules
*
* If the banner includes RL mixins, render the JS (TODO: and CSS) and
* return here.
*
* @return string HTML snippet.
*/
public
function
getResourceLoaderHtml
()
{
$modules
=
$this
->
mixinController
->
getResourceLoaderModules
();
if
(
$modules
)
{
// FIXME: Does the RL library already include a helper to do this?
$html
=
"<!-- "
.
implode
(
", "
,
array_keys
(
$modules
)
)
.
" -->"
;
$html
.=
ResourceLoader
::
makeInlineScript
(
Html
::
encodeJsCall
(
'mw.loader.load'
,
array_values
(
$modules
)
)
);
return
$html
;
}
return
""
;
}
/**
* Replace magic word placeholders with their value
*
* We rely on $this->renderMagicWord to do the heavy lifting.
*
* @param string $contents Raw contents to be processed.
*
* @return string Rendered contents.
*/
public
function
substituteMagicWords
(
$contents
)
{
// FIXME The syntax {{{magicword:param1|param2}}} for magic words does not work,
// since it is munged by core before we get it here. It was part of the in-banner
// mixin system, currently unused.
return
preg_replace_callback
(
'/{{{([^}:]+)(?:[:]([^}]*))?}}}/'
,
[
$this
,
'renderMagicWord'
],
$contents
);
}
/**
* Get a list of magic words provided or dependened upon by this banner
*
* @return array List of magic word names.
*/
public
function
getMagicWords
()
{
$words
=
[
'banner'
,
'campaign'
];
$words
=
array_merge
(
$words
,
$this
->
mixinController
->
getMagicWords
()
);
return
$words
;
}
/**
* Get the value for a magic word
*
* @param array $re_matches Funky PCRE callback param having the form,
* array(
* 0 => full match, ignored,
* 1 => magic word name,
* 2 => optional arguments to the magic word replacement function
* FIXME Doesn't work, unused
* );
*
* @return string HTML fragment with the resulting value.
*/
private
function
renderMagicWord
(
$re_matches
)
{
$field
=
$re_matches
[
1
];
if
(
$field
===
'banner'
)
{
return
$this
->
banner
->
getName
();
}
elseif
(
$field
===
'campaign'
)
{
return
$this
->
campaignName
;
}
// FIXME This doesn't work; part of the unused in-banner mixin system.
$params
=
[];
if
(
isset
(
$re_matches
[
2
]
)
)
{
$params
=
explode
(
"|"
,
$re_matches
[
2
]
);
}
$value
=
$this
->
mixinController
->
renderMagicWord
(
$field
,
$params
);
if
(
$value
!==
null
)
{
return
$value
;
}
// Treat anything else as a translatable message
$messageFields
=
explode
(
','
,
$field
,
2
);
if
(
isset
(
$messageFields
[
1
]
)
)
{
// A translatable message from a named banner. String before the comma is the
// banner that defines the message, and the rest is the name of the
// translatable message from that banner.
$bannerMessage
=
Banner
::
getMessageFieldForBanner
(
trim
(
$messageFields
[
0
]
),
trim
(
$messageFields
[
1
]
)
);
}
elseif
(
$this
->
previewMessages
!==
null
&&
array_key_exists
(
$field
,
$this
->
previewMessages
)
)
{
// If we're rendering an unsaved preview and the field is provided as an
// unsaved preview message, transform as a messages, sanitize and return that.
// TODO As above, double-check that this is the correct way to get process as
// a i18n message.
return
MediaWikiServices
::
getInstance
()->
getMessageCache
()->
transform
(
BannerMessage
::
sanitize
(
$this
->
previewMessages
[
$field
]
)
);
}
else
{
$bannerMessage
=
$this
->
banner
->
getMessageField
(
$field
);
}
return
$bannerMessage
->
toHtml
(
$this
->
context
);
}
}
File Metadata
Details
Attached
Mime Type
text/x-php
Expires
Fri, Jul 3, 18:54 (1 d, 13 h)
Storage Engine
local-disk
Storage Format
Raw Data
Storage Handle
10/51/7e39373635b8821fc812d40b9974
Default Alt Text
BannerRenderer.php (9 KB)
Attached To
Mode
rMWPROD MediaWiki Production
Attached
Detach File
Event Timeline
Log In to Comment