Page Menu
Home
WickedGov Phorge
Search
Configure Global Search
Log In
Files
F2753627
CentralNoticeHooks.php
No One
Temporary
Actions
Download File
Edit File
Delete File
View Transforms
Subscribe
Flag For Later
Award Token
Size
24 KB
Referenced Files
None
Subscribers
None
CentralNoticeHooks.php
View Options
<?php
// phpcs:disable MediaWiki.NamingConventions.LowerCamelFunctionsName.FunctionName
use
MediaWiki\ChangeTags\Hook\ChangeTagsListActiveHook
;
use
MediaWiki\ChangeTags\Hook\ListDefinedTagsHook
;
use
MediaWiki\Hook\CanonicalNamespacesHook
;
use
MediaWiki\Hook\PreferencesGetIconHook
;
use
MediaWiki\Hook\SkinTemplateNavigation__UniversalHook
;
use
MediaWiki\MediaWikiServices
;
use
MediaWiki\Message\Message
;
use
MediaWiki\Output\OutputPage
;
use
MediaWiki\Preferences\Hook\GetPreferencesHook
;
use
MediaWiki\Registration\ExtensionRegistry
;
use
MediaWiki\ResourceLoader
as
RL
;
use
MediaWiki\ResourceLoader\Hook\ResourceLoaderRegisterModulesHook
;
use
MediaWiki\ResourceLoader\ResourceLoader
;
use
MediaWiki\Skin\Skin
;
use
MediaWiki\SpecialPage\SpecialPage
;
use
MediaWiki\User\User
;
/**
* General hook definitions
*
* This file is part of the CentralNotice Extension to MediaWiki
* https://www.mediawiki.org/wiki/Extension:CentralNotice
*
* @file
* @ingroup Extensions
*
* @section LICENSE
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 2 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License along
* with this program; if not, write to the Free Software Foundation, Inc.,
* 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
* http://www.gnu.org/copyleft/gpl.html
*/
class
CentralNoticeHooks
implements
CanonicalNamespacesHook
,
ChangeTagsListActiveHook
,
ListDefinedTagsHook
,
SkinTemplateNavigation__UniversalHook
,
ResourceLoaderRegisterModulesHook
,
GetPreferencesHook
,
PreferencesGetIconHook
{
/**
* Conditional configuration
*/
public
static
function
onRegistration
()
{
// @phpcs:ignore MediaWiki.Usage.DeprecatedGlobalVariables.Deprecated$wgHooks
global
$wgHooks
,
$wgNoticeInfrastructure
,
$wgSpecialPages
,
$wgCentralNoticeLoader
,
$wgNoticeUseTranslateExtension
,
$wgAvailableRights
,
$wgGroupPermissions
,
$wgCentralNoticeAdminGroup
,
$wgCentralNoticeMessageProtectRight
,
$wgResourceModules
,
$wgDefaultUserOptions
;
// If CentralNotice banners should be shown on this wiki, load the components we need for
// showing banners. For discussion of banner loading strategies, see
// http://wikitech.wikimedia.org/view/CentralNotice/Optimizing_banner_loading
if
(
$wgCentralNoticeLoader
)
{
$wgHooks
[
'MakeGlobalVariablesScript'
][]
=
'CentralNoticeHooks::onMakeGlobalVariablesScript'
;
$wgHooks
[
'BeforePageDisplay'
][]
=
'CentralNoticeHooks::onBeforePageDisplay'
;
$wgHooks
[
'SiteNoticeAfter'
][]
=
'CentralNoticeHooks::onSiteNoticeAfter'
;
$wgHooks
[
'ResourceLoaderGetConfigVars'
][]
=
'CentralNoticeHooks::onResourceLoaderGetConfigVars'
;
}
// Set default user preferences for campaign type filtering.
// All types are on by default.
foreach
(
CampaignType
::
getTypes
()
as
$type
)
{
$wgDefaultUserOptions
[
$type
->
getPreferenceKey
()
]
=
1
;
}
// If this is the wiki that hosts the management interface, load further components
if
(
$wgNoticeInfrastructure
)
{
if
(
$wgNoticeUseTranslateExtension
)
{
$wgHooks
[
'TranslatePostInitGroups'
][]
=
'BannerMessageGroup::registerGroupHook'
;
$wgHooks
[
'TranslateEventMessageGroupStateChange'
][]
=
'BannerMessageGroup::updateBannerGroupStateHook'
;
}
$wgSpecialPages
[
'CentralNotice'
]
=
CentralNotice
::
class
;
$wgSpecialPages
[
'NoticeTemplate'
]
=
SpecialNoticeTemplate
::
class
;
$wgSpecialPages
[
'BannerAllocation'
]
=
SpecialBannerAllocation
::
class
;
$wgSpecialPages
[
'CentralNoticeLogs'
]
=
SpecialCentralNoticeLogs
::
class
;
$wgSpecialPages
[
'CentralNoticeBanners'
]
=
SpecialCentralNoticeBanners
::
class
;
$moduleTemplate
=
[
'localBasePath'
=>
dirname
(
__DIR__
)
.
'/resources'
,
'remoteExtPath'
=>
'CentralNotice/resources'
,
];
$wgResourceModules
+=
[
'ext.centralNotice.adminUi'
=>
$moduleTemplate
+
[
'dependencies'
=>
[
'jquery.ui'
,
'mediawiki.jqueryMsg'
,
'mediawiki.util'
,
],
'scripts'
=>
[
'vendor/jquery.ui.multiselect/ui.multiselect.js'
,
'vendor/jquery.jstree/jstree.js'
,
'infrastructure/centralnotice.js'
,
],
'styles'
=>
[
'vendor/jquery.ui.multiselect/ui.multiselect.css'
,
'vendor/jquery.jstree/themes/default/style.css'
,
'infrastructure/ext.centralNotice.adminUi.less'
],
'messages'
=>
[
'centralnotice-documentwrite-error'
,
'centralnotice-close-title'
,
'centralnotice-select-all'
,
'centralnotice-remove-all'
,
'centralnotice-items-selected'
,
'centralnotice-geo-status'
]
],
'ext.centralNotice.adminUi.campaignPager'
=>
$moduleTemplate
+
[
'scripts'
=>
'infrastructure/ext.centralNotice.adminUi.campaignPager.js'
,
'styles'
=>
'infrastructure/ext.centralNotice.adminUi.campaignPager.less'
],
'ext.centralNotice.adminUi.bannerManager'
=>
$moduleTemplate
+
[
'dependencies'
=>
[
'ext.centralNotice.adminUi'
,
'jquery.ui'
,
],
'scripts'
=>
'infrastructure/bannermanager.js'
,
'styles'
=>
'infrastructure/bannermanager.less'
,
'messages'
=>
[
'centralnotice-add-notice-button'
,
'centralnotice-add-notice-cancel-button'
,
'centralnotice-archive-banner'
,
'centralnotice-archive-banner-title'
,
'centralnotice-archive-banner-confirm'
,
'centralnotice-archive-banner-cancel'
,
'centralnotice-add-new-banner-title'
,
'centralnotice-delete-banner'
,
'centralnotice-delete-banner-title'
,
'centralnotice-delete-banner-confirm'
,
'centralnotice-delete-banner-cancel'
]
],
'ext.centralNotice.adminUi.bannerEditor'
=>
$moduleTemplate
+
[
'dependencies'
=>
[
'ext.centralNotice.adminUi'
,
'jquery.ui'
,
'ext.centralNotice.kvStore'
,
'mediawiki.api'
,
'mediawiki.Title'
,
'mediawiki.user'
,
],
'scripts'
=>
'infrastructure/bannereditor.js'
,
'styles'
=>
'infrastructure/bannereditor.css'
,
'messages'
=>
[
'centralnotice-clone'
,
'centralnotice-clone-notice'
,
'centralnotice-clone-cancel'
,
'centralnotice-archive-banner'
,
'centralnotice-archive-banner-title'
,
'centralnotice-archive-banner-confirm'
,
'centralnotice-archive-banner-cancel'
,
'centralnotice-delete-banner'
,
'centralnotice-delete-banner-title'
,
'centralnotice-delete-banner-confirm'
,
'centralnotice-delete-banner-cancel'
,
'centralnotice-banner-cdn-dialog-waiting-text'
,
'centralnotice-banner-cdn-dialog-error'
,
'centralnotice-banner-cdn-dialog-success'
,
'centralnotice-fieldset-preview'
,
'centralnotice-preview-page'
,
'centralnotice-update-preview'
,
'centralnotice-preview-loader-error-dialog-title'
,
]
],
'ext.centralNotice.adminUi.campaignManager'
=>
[
'localBasePath'
=>
dirname
(
__DIR__
),
'remoteExtPath'
=>
'CentralNotice'
,
'dependencies'
=>
[
'ext.centralNotice.adminUi'
,
'oojs-ui'
,
'mediawiki.template'
,
'mediawiki.template.mustache'
],
'scripts'
=>
'resources/infrastructure/campaignManager.js'
,
'styles'
=>
'resources/infrastructure/campaignManager.less'
,
'templates'
=>
[
'campaignMixinParamControls.mustache'
=>
'templates/campaignMixinParamControls.mustache'
],
'messages'
=>
[
'centralnotice-notice-mixins-int-required'
,
'centralnotice-notice-mixins-float-required'
,
'centralnotice-notice-mixins-out-of-bound'
,
'centralnotice-banner-history-logger-rate'
,
'centralnotice-banner-history-logger-rate-help'
,
'centralnotice-banner-history-logger-max-entry-age'
,
'centralnotice-banner-history-logger-max-entry-age-help'
,
'centralnotice-banner-history-logger-max-entries'
,
'centralnotice-banner-history-logger-max-entries-help'
,
'centralnotice-banner-history-logger-wait-log-no-send-beacon'
,
'centralnotice-banner-history-logger-wait-log-no-send-beacon-help'
,
'centralnotice-set-record-impression-sample-rate'
,
'centralnotice-custom-record-impression-sample-rate'
,
'centralnotice-banners-not-guaranteed-to-display'
,
'centralnotice-impression-diet-identifier'
,
'centralnotice-impression-diet-identifier-help'
,
'centralnotice-impression-diet-maximum-seen'
,
'centralnotice-impression-diet-maximum-seen-help'
,
'centralnotice-impression-diet-restart-cycle-delay'
,
'centralnotice-impression-diet-restart-cycle-delay-help'
,
'centralnotice-impression-diet-skip-initial'
,
'centralnotice-impression-diet-skip-initial-help'
,
'centralnotice-large-banner-limit-days'
,
'centralnotice-large-banner-limit-days-help'
,
'centralnotice-large-banner-limit-randomize'
,
'centralnotice-large-banner-limit-randomize-help'
,
'centralnotice-large-banner-limit-identifier'
,
'centralnotice-large-banner-limit-identifier-help'
,
'centralnotice-impression-events-sample-rate'
,
'centralnotice-impression-events-sample-rate-help'
,
'centralnotice-impression-events-sample-rate-field'
]
],
'ext.centralNotice.adminUi.bannerSequence'
=>
$moduleTemplate
+
[
'scripts'
=>
'infrastructure/ext.centralNotice.adminUi.bannerSequence.js'
,
'styles'
=>
'infrastructure/ext.centralNotice.adminUi.bannerSequence.less'
,
'dependencies'
=>
[
'ext.centralNotice.adminUi.campaignManager'
,
'oojs-ui'
,
'oojs-ui.styles.icons-moderation'
,
'mediawiki.jqueryMsg'
],
'messages'
=>
[
'centralnotice-banner-sequence'
,
'centralnotice-banner-sequence-days'
,
'centralnotice-banner-sequence-days-error'
,
'centralnotice-banner-sequence-days-help'
,
'centralnotice-banner-sequence-help'
,
'centralnotice-banner-sequence-bucket-seq'
,
'centralnotice-banner-sequence-bucket-add-step'
,
'centralnotice-banner-sequence-banner'
,
'centralnotice-banner-sequence-page-views'
,
'centralnotice-banner-sequence-skip-with-id'
,
'centralnotice-banner-sequence-page-views-error'
,
'centralnotice-banner-sequence-skip-with-id-error'
,
'centralnotice-banner-sequence-banner-removed-error'
,
'centralnotice-banner-sequence-no-banner'
,
'centralnotice-banner-sequence-detailed-help'
]
],
];
// Register user rights for editing
$wgAvailableRights
[]
=
'centralnotice-admin'
;
if
(
$wgCentralNoticeAdminGroup
)
{
// Grant admin permissions to this group
$wgGroupPermissions
[
$wgCentralNoticeAdminGroup
][
'centralnotice-admin'
]
=
true
;
}
if
(
!
in_array
(
$wgCentralNoticeMessageProtectRight
,
$wgAvailableRights
)
)
{
$wgAvailableRights
[]
=
$wgCentralNoticeMessageProtectRight
;
}
self
::
addCascadingRestrictionRight
(
$wgCentralNoticeMessageProtectRight
);
self
::
addCascadingRestrictionRight
(
'centralnotice-admin'
);
}
}
/**
* @param string $right
*/
private
static
function
addCascadingRestrictionRight
(
$right
)
{
global
$wgCascadingRestrictionLevels
,
$wgRestrictionLevels
;
if
(
!
in_array
(
$right
,
$wgRestrictionLevels
)
)
{
$wgRestrictionLevels
[]
=
$right
;
}
if
(
!
in_array
(
$right
,
$wgCascadingRestrictionLevels
)
)
{
$wgCascadingRestrictionLevels
[]
=
$right
;
}
}
/**
* Initialization: set default values for some config globals. Invoked via
* $wgExtensionFunctions.
*/
public
static
function
initCentralNotice
()
{
global
$wgCentralBannerRecorder
,
$wgCentralSelectedBannerDispatcher
,
$wgCentralSelectedMobileBannerDispatcher
;
// Defaults for infrastructure wiki URLs
if
(
!
$wgCentralBannerRecorder
)
{
$wgCentralBannerRecorder
=
SpecialPage
::
getTitleFor
(
'RecordImpression'
)->
getLocalUrl
();
}
if
(
!
$wgCentralSelectedBannerDispatcher
)
{
$wgCentralSelectedBannerDispatcher
=
SpecialPage
::
getTitleFor
(
'BannerLoader'
)->
getLocalUrl
();
}
if
(
!
$wgCentralSelectedMobileBannerDispatcher
&&
ExtensionRegistry
::
getInstance
()->
isLoaded
(
'MobileFrontend'
)
)
{
$wgCentralSelectedMobileBannerDispatcher
=
$wgCentralSelectedBannerDispatcher
;
}
}
/**
* CanonicalNamespaces hook; adds the CentralNotice namespaces if this is an infrastructure
* wiki, and if CentralNotice is configured to use the Translate extension.
*
* We do this here because there are initialization problems wrt Translate and MW core if
* the language object is initialized before all namespaces are registered -- which would
* be the case if we just used the wgExtensionFunctions hook system.
*
* @param array &$namespaces Modifiable list of namespaces -- similar to $wgExtraNamespaces
*/
public
function
onCanonicalNamespaces
(
&
$namespaces
)
{
global
$wgExtraNamespaces
,
$wgNamespacesWithSubpages
,
$wgTranslateMessageNamespaces
;
global
$wgNoticeUseTranslateExtension
,
$wgNoticeInfrastructure
;
// TODO XXX Old doc copied from legacy follows, verify accuracy!
// When using the group review feature of translate; this
// will be the namespace ID for the banner staging area -- ie: banners
// here are world editable and will not be moved to the MW namespace
// until they are in $wgNoticeTranslateDeployStates
// TODO This may be unnecessary. Must coordinate with extension.json
if
(
!
defined
(
'NS_CN_BANNER'
)
)
{
define
(
'NS_CN_BANNER'
,
866
);
define
(
'NS_CN_BANNER_TALK'
,
867
);
}
if
(
$wgNoticeInfrastructure
&&
$wgNoticeUseTranslateExtension
)
{
$wgExtraNamespaces
[
NS_CN_BANNER
]
=
'CNBanner'
;
$wgTranslateMessageNamespaces
[]
=
NS_CN_BANNER
;
$wgExtraNamespaces
[
NS_CN_BANNER_TALK
]
=
'CNBanner_talk'
;
$wgNamespacesWithSubpages
[
NS_CN_BANNER_TALK
]
=
true
;
$namespaces
[
NS_CN_BANNER
]
=
'CNBanner'
;
$namespaces
[
NS_CN_BANNER_TALK
]
=
'CNBanner_talk'
;
}
}
/**
* BeforePageDisplay hook handler
* This function adds the startUp and geoIP modules to the page as needed,
* and if there is a forced banner preview, add CSP headers and violation
* reporting javascript.
*
* @param OutputPage $out
* @param Skin $skin
* @return bool
*/
public
static
function
onBeforePageDisplay
(
$out
,
$skin
)
{
global
$wgCentralHost
,
$wgServer
,
$wgCentralNoticeContentSecurityPolicy
,
$wgCentralNoticeESITestString
;
// Add ESI test string (see T308799)
// It is expected that only HTML comments in the form of '<!--esi ...' will be
// injected here.
// TODO Remove this once ESI tests are complete.
if
(
$wgCentralNoticeESITestString
)
{
$out
->
addHTML
(
$wgCentralNoticeESITestString
);
}
// Always add geoIP
// TODO Separate geoIP from CentralNotice
$out
->
addModules
(
'ext.centralNotice.geoIP'
);
// Banners can contain user-contributed JavaScript.
// Do not show them when executing such scripts is generally disallowed.
$isSiteJsAllowed
=
$out
->
getAllowedModules
(
RL\Module
::
TYPE_SCRIPTS
)
>=
RL\Module
::
ORIGIN_USER_SITEWIDE
;
$request
=
$skin
->
getRequest
();
// If we're on a special page (or not a normal page view at all),
// editing, viewing history or a diff, bow out now
// This is to reduce the chance of bad misclicks from delayed banner loading
if
(
!
$isSiteJsAllowed
||
!
$out
->
getTitle
()
||
$out
->
getTitle
()->
inNamespace
(
NS_SPECIAL
)
||
(
$request
->
getText
(
'action'
)
===
'edit'
)
||
(
$request
->
getText
(
'action'
)
===
'history'
)
||
$request
->
getCheck
(
'diff'
)
)
{
return
true
;
}
// Insert DNS prefetch for banner loading
if
(
$wgCentralHost
&&
$wgCentralHost
!==
$wgServer
)
{
$out
->
addHeadItem
(
'cn-dns-prefetch'
,
'<link rel="dns-prefetch" href="'
.
htmlspecialchars
(
$wgCentralHost
)
.
'" />'
);
}
// Insert the startup module
$out
->
addModules
(
'ext.centralNotice.startUp'
);
// FIXME: I80f6f469ba4c0b60 has been in core since REL1_32.
// Get rid of $wgCentralNoticeContentSecurityPolicy and use their stuff.
if
(
$wgCentralNoticeContentSecurityPolicy
&&
$request
->
getVal
(
'banner'
)
)
{
$request
->
response
()->
header
(
"content-security-policy: $wgCentralNoticeContentSecurityPolicy"
);
$out
->
addModules
(
'ext.centralNotice.cspViolationAlert'
);
}
return
true
;
}
/**
* MakeGlobalVariablesScript hook handler
* This function sets the pseudo-global JavaScript variables that are used by CentralNotice
*
* @param array &$vars
* @param OutputPage $out
* @return bool
*/
public
static
function
onMakeGlobalVariablesScript
(
&
$vars
,
$out
)
{
global
$wgNoticeProject
,
$wgCentralNoticeGeoIPBackgroundLookupModule
;
// FIXME: Is this no longer used anywhere in JS following the switch to
// client-side banner selection? If so, remove it.
$vars
[
'wgNoticeProject'
]
=
$wgNoticeProject
;
// No need to provide this variable if it's null, because mw.config.get()
// will return null if it's not there.
if
(
$wgCentralNoticeGeoIPBackgroundLookupModule
)
{
$vars
[
'wgCentralNoticeGeoIPBackgroundLookupModule'
]
=
$wgCentralNoticeGeoIPBackgroundLookupModule
;
}
// Output the user's registration date, total edit count, and past year's edit count.
// This is useful for banners that need to be targeted to specific types of users.
// Only do this for logged-in users, keeping anonymous user output equal (for Squid-cache).
$user
=
$out
->
getUser
();
if
(
$user
->
isRegistered
()
)
{
if
(
$user
->
isBot
()
)
{
$userData
=
false
;
}
else
{
$userData
=
[
// Add the user's registration date (TS_MW)
'registration'
=>
$user
->
getRegistration
()
?:
0
];
}
// Set the variable that will be output to the page
$vars
[
'wgNoticeUserData'
]
=
$userData
;
}
return
true
;
}
/**
* SiteNoticeAfter hook handler
* This function outputs the siteNotice div that the banners are loaded into.
*
* @param string &$notice
* @return bool
*/
public
static
function
onSiteNoticeAfter
(
&
$notice
)
{
// TODO Legacy comment below, likely inaccurate; check and fix
// Ensure that the div including #siteNotice is actually included
$notice
=
"<!-- CentralNotice -->$notice"
;
return
true
;
}
/**
* ResourceLoaderGetConfigVars hook handler
* Send php config vars to js via ResourceLoader
*
* @param array &$vars variables to be added to the output of the startup module
* @return bool
*/
public
static
function
onResourceLoaderGetConfigVars
(
&
$vars
)
{
global
$wgNoticeInfrastructure
,
$wgCentralBannerRecorder
,
$wgNoticeNumberOfBuckets
,
$wgNoticeBucketExpiry
,
$wgNoticeNumberOfControllerBuckets
,
$wgNoticeCookieDurations
,
$wgNoticeHideUrls
,
$wgCentralNoticeSampleRate
,
$wgCentralNoticeImpressionEventSampleRate
,
$wgCentralSelectedBannerDispatcher
,
$wgCentralSelectedMobileBannerDispatcher
,
$wgCentralNoticePerCampaignBucketExtension
,
$wgCentralNoticeCampaignMixins
,
$wgCentralNoticeMaxCampaignFallback
;
// TODO Check if the following comment still applies
// Making these calls too soon will causes issues with the namespace localisation cache.
// This seems to be just right. We require them at all because MW will 302 page requests
// made to non localised namespaces which results in wasteful extra calls.
// Set infrastructure URL variables, which change between mobile/desktop
if
(
ExtensionRegistry
::
getInstance
()->
isLoaded
(
'MobileFrontend'
)
)
{
$mc
=
MobileContext
::
singleton
();
$displayMobile
=
$mc
->
shouldDisplayMobileView
();
}
else
{
$displayMobile
=
false
;
}
if
(
$displayMobile
)
{
// @phan-suppress-next-line PhanPossiblyUndeclaredVariable
$wgCentralBannerRecorder
=
$mc
->
getMobileUrl
(
$wgCentralBannerRecorder
);
$bannerDispatcher
=
$wgCentralSelectedMobileBannerDispatcher
;
}
else
{
$bannerDispatcher
=
$wgCentralSelectedBannerDispatcher
;
}
$vars
[
'wgCentralNoticeActiveBannerDispatcher'
]
=
$bannerDispatcher
;
$vars
[
'wgCentralBannerRecorder'
]
=
$wgCentralBannerRecorder
;
$vars
[
'wgCentralNoticeSampleRate'
]
=
$wgCentralNoticeSampleRate
;
$vars
[
'wgCentralNoticeImpressionEventSampleRate'
]
=
$wgCentralNoticeImpressionEventSampleRate
;
$vars
[
'wgNoticeNumberOfBuckets'
]
=
$wgNoticeNumberOfBuckets
;
$vars
[
'wgNoticeBucketExpiry'
]
=
$wgNoticeBucketExpiry
;
$vars
[
'wgNoticeNumberOfControllerBuckets'
]
=
$wgNoticeNumberOfControllerBuckets
;
$vars
[
'wgNoticeCookieDurations'
]
=
$wgNoticeCookieDurations
;
$vars
[
'wgNoticeHideUrls'
]
=
$wgNoticeHideUrls
;
$vars
[
'wgCentralNoticeMaxCampaignFallback'
]
=
$wgCentralNoticeMaxCampaignFallback
;
$vars
[
'wgCentralNoticePerCampaignBucketExtension'
]
=
$wgCentralNoticePerCampaignBucketExtension
;
if
(
$wgNoticeInfrastructure
)
{
// Add campaign mixin defs for use in admin interface
$vars
[
'wgCentralNoticeCampaignMixins'
]
=
$wgCentralNoticeCampaignMixins
;
}
return
true
;
}
/**
* Conditionally register resource loader modules.
* @see https://www.mediawiki.org/wiki/Manual:Hooks/ResourceLoaderRegisterModules
*
* @param ResourceLoader $resourceLoader
*/
public
function
onResourceLoaderRegisterModules
(
ResourceLoader
$resourceLoader
):
void
{
global
$wgEnableJavaScriptTest
,
$wgAutoloadClasses
;
if
(
$wgEnableJavaScriptTest
)
{
// These classes are only used here or in phpunit tests
$wgAutoloadClasses
[
'CNTestFixturesResourceLoaderModule'
]
=
dirname
(
__DIR__
)
.
'/tests/phpunit/CNTestFixturesResourceLoaderModule.php'
;
$wgAutoloadClasses
[
'CentralNoticeTestFixtures'
]
=
dirname
(
__DIR__
)
.
'/tests/phpunit/CentralNoticeTestFixtures.php'
;
// Set up test fixtures module, which is added as a dependency for all QUnit
// tests.
$resourceLoader
->
register
(
'ext.centralNotice.testFixtures'
,
[
'class'
=>
'CNTestFixturesResourceLoaderModule'
]
);
}
}
/**
* Add tags defined by this extension to the list of active tags.
*
* @param array &$tags List of defined or active tags
*/
public
function
onChangeTagsListActive
(
&
$tags
)
{
$this
->
addDefinedTags
(
$tags
);
}
/**
* Add tags defined by this extension to list of defined tags.
*
* @param array &$tags List of defined or active tags
*/
public
function
onListDefinedTags
(
&
$tags
)
{
$this
->
addDefinedTags
(
$tags
);
}
/**
* @param string[] &$tags
*/
private
function
addDefinedTags
(
&
$tags
):
void
{
$tags
[]
=
'centralnotice'
;
$tags
[]
=
'centralnotice translation'
;
}
/**
* @param User $user
* @param array &$preferences
*/
public
function
onGetPreferences
(
$user
,
&
$preferences
)
{
// Explanatory text
$preferences
[
'centralnotice-intro'
]
=
[
'type'
=>
'info'
,
'default'
=>
wfMessage
(
'centralnotice-user-prefs-intro'
)->
parseAsBlock
(),
'section'
=>
'centralnotice-banners'
,
'raw'
=>
true
,
];
foreach
(
CampaignType
::
getTypes
()
as
$type
)
{
// This allows fallback languages while also showing something not-too-
// horrible if the config variable has types that don't have i18n
// messages.
// Note also that the value of 'label' will be escaped prior to output.
$message
=
Message
::
newFromKey
(
$type
->
getMessageKey
()
);
$label
=
$message
->
exists
()
?
$message
->
text
()
:
$type
->
getId
();
$preferences
[
$type
->
getPreferenceKey
()
]
=
[
'type'
=>
'toggle'
,
'section'
=>
'centralnotice-banners/centralnotice-display-banner-types'
,
'label'
=>
$label
,
'disabled'
=>
$type
->
getOnForAll
()
];
}
}
/**
* Add icon for Special:Preferences mobile layout
*
* @param array &$iconNames Array of icon names for their respective sections.
*/
public
function
onPreferencesGetIcon
(
&
$iconNames
)
{
$iconNames
[
'centralnotice-banners'
]
=
'feedback'
;
}
/**
* Adds CentralNotice specific navigation tabs to the UI.
* Implementation of SkinTemplateNavigation::Universal hook.
*
* @param Skin $skin Reference to the Skin object
* @param array &$tabs Any current skin tabs
*/
public
function
onSkinTemplateNavigation__Universal
(
$skin
,
&
$tabs
):
void
{
global
$wgNoticeTabifyPages
,
$wgNoticeInfrastructure
;
// Only show tabs if this wiki is in infrastructure mode
if
(
!
$wgNoticeInfrastructure
)
{
return
;
}
// Return if skin allows special pages to register navigation links (in which
// case this is handled by getShortDescription() and
// getAssociatedNavigationLinks()).
// See T315562, T313349.
if
(
$skin
->
supportsMenu
(
'associated-pages'
)
)
{
return
;
}
$title
=
$skin
->
getTitle
();
// Only add tabs to special pages
if
(
!
$title
||
!
$title
->
isSpecialPage
()
)
{
return
;
}
[
$alias
,
]
=
MediaWikiServices
::
getInstance
()->
getSpecialPageFactory
()->
resolveAlias
(
$title
->
getText
()
);
if
(
!
array_key_exists
(
$alias
,
$wgNoticeTabifyPages
)
)
{
return
;
}
// Clear the special page tab that's there already
$tabs
[
'namespaces'
]
=
[];
// Now add our own
foreach
(
$wgNoticeTabifyPages
as
$page
=>
$keys
)
{
$tabs
[
$keys
[
'type'
]
][
$page
]
=
[
'text'
=>
wfMessage
(
$keys
[
'message'
]
)->
parse
(),
'href'
=>
SpecialPage
::
getTitleFor
(
$page
)->
getFullURL
(),
'class'
=>
(
$alias
===
$page
)
?
'selected'
:
''
,
];
}
}
}
File Metadata
Details
Attached
Mime Type
text/x-php
Expires
Fri, Jul 3, 21:30 (11 h, 43 m)
Storage Engine
local-disk
Storage Format
Raw Data
Storage Handle
50/2f/29cc8df2b25c940e92a98c84791c
Default Alt Text
CentralNoticeHooks.php (24 KB)
Attached To
Mode
rMWPROD MediaWiki Production
Attached
Detach File
Event Timeline
Log In to Comment