Page Menu
Home
WickedGov Phorge
Search
Configure Global Search
Log In
Files
F5960766
SpecialMobileOptions.php
No One
Temporary
Actions
Download File
Edit File
Delete File
View Transforms
Subscribe
Flag For Later
Award Token
Size
12 KB
Referenced Files
None
Subscribers
None
SpecialMobileOptions.php
View Options
<?php
use
MediaWiki\Config\Config
;
use
MediaWiki\Deferred\DeferredUpdates
;
use
MediaWiki\Html\Html
;
use
MediaWiki\MediaWikiServices
;
use
MediaWiki\Request\WebRequest
;
use
MediaWiki\SpecialPage\UnlistedSpecialPage
;
use
MediaWiki\Title\Title
;
use
MediaWiki\User\Options\UserOptionsManager
;
use
MobileFrontend\Amc\UserMode
;
use
MobileFrontend\Features\IFeature
;
use
Wikimedia\Rdbms\ReadOnlyMode
;
/**
* Adds a special page with mobile specific preferences
*/
class
SpecialMobileOptions
extends
UnlistedSpecialPage
{
/** @var bool Whether this special page has a desktop version or not */
protected
$hasDesktopVersion
=
true
;
/**
* Advanced Mobile Contributions mode
* @var \MobileFrontend\Amc\Manager
*/
private
$amc
;
/**
* @var \MobileFrontend\Features\FeaturesManager
*/
private
$featuresManager
;
/** @var UserMode */
private
$userMode
;
/** @var UserOptionsManager */
private
UserOptionsManager
$userOptionsManager
;
/** @var ReadOnlyMode */
private
ReadOnlyMode
$readOnlyMode
;
/** @var MobileContext */
private
$mobileContext
;
/** @var Config MobileFrontend's config object */
protected
Config
$config
;
public
function
__construct
(
UserOptionsManager
$userOptionsManager
,
ReadOnlyMode
$readOnlyMode
,
Config
$config
)
{
parent
::
__construct
(
'MobileOptions'
);
$services
=
MediaWikiServices
::
getInstance
();
$this
->
amc
=
$services
->
getService
(
'MobileFrontend.AMC.Manager'
);
$this
->
featuresManager
=
$services
->
getService
(
'MobileFrontend.FeaturesManager'
);
$this
->
userMode
=
$services
->
getService
(
'MobileFrontend.AMC.UserMode'
);
$this
->
mobileContext
=
$services
->
getService
(
'MobileFrontend.Context'
);
$this
->
userOptionsManager
=
$userOptionsManager
;
$this
->
readOnlyMode
=
$readOnlyMode
;
$this
->
config
=
$config
;
}
/**
* @return bool
*/
public
function
doesWrites
()
{
return
true
;
}
/**
* Set the required config for the page.
*/
public
function
setJsConfigVars
()
{
$this
->
getOutput
()->
addJsConfigVars
(
[
'wgMFCollapseSectionsByDefault'
=>
$this
->
getConfig
()->
get
(
'MFCollapseSectionsByDefault'
),
'wgMFEnableFontChanger'
=>
$this
->
featuresManager
->
isFeatureAvailableForCurrentUser
(
'MFEnableFontChanger'
),
]
);
}
/**
* Render the special page
* @param string|null $par Parameter submitted as subpage
*/
public
function
execute
(
$par
=
''
)
{
parent
::
execute
(
$par
);
$out
=
$this
->
getOutput
();
$this
->
setHeaders
();
$out
->
addBodyClasses
(
'mw-mf-special-page'
);
$out
->
addModuleStyles
(
[
'mobile.special.styles'
,
'mobile.special.codex.styles'
,
'mobile.special.mobileoptions.styles'
,
]
);
$out
->
addModules
(
[
'mobile.special.mobileoptions.scripts'
,
]
);
$this
->
setJsConfigVars
();
$this
->
mobileContext
->
setForceMobileView
(
true
);
if
(
$this
->
getRequest
()->
wasPosted
()
)
{
$this
->
submitSettingsForm
();
}
else
{
$this
->
addSettingsForm
();
}
}
private
function
buildAMCToggle
()
{
$amcToggle
=
new
OOUI\CheckboxInputWidget
(
[
'name'
=>
'enableAMC'
,
'infusable'
=>
true
,
'selected'
=>
$this
->
userMode
->
isEnabled
(),
'id'
=>
'enable-amc-toggle'
,
'value'
=>
'1'
,
]
);
$layout
=
new
OOUI\FieldLayout
(
$amcToggle
,
[
'label'
=>
new
OOUI\LabelWidget
(
[
'input'
=>
$amcToggle
,
'label'
=>
new
OOUI\HtmlSnippet
(
Html
::
openElement
(
'div'
)
.
Html
::
rawElement
(
'strong'
,
[],
$this
->
msg
(
'mw-mf-amc-name'
)->
parse
()
)
.
Html
::
rawElement
(
'div'
,
[
'class'
=>
'option-description'
],
$this
->
msg
(
'mw-mf-amc-description'
)->
parse
()
)
.
Html
::
closeElement
(
'div'
)
)
]
),
'id'
=>
'amc-field'
,
]
);
// placing links inside a label reduces usability and accessibility so
// append links to $layout and outside of label instead
// https://www.w3.org/TR/html52/sec-forms.html#example-42c5e0c5
$layout
->
appendContent
(
new
OOUI\HtmlSnippet
(
Html
::
openElement
(
'ul'
,
[
'class'
=>
'hlist option-links'
]
)
.
Html
::
openElement
(
'li'
)
.
Html
::
rawElement
(
'a'
,
// phpcs:ignore Generic.Files.LineLength.TooLong
[
'href'
=>
'https://www.mediawiki.org/wiki/Special:MyLanguage/Reading/Web/Advanced_mobile_contributions'
],
$this
->
msg
(
'mobile-frontend-mobile-option-amc-learn-more'
)->
parse
()
)
.
Html
::
closeElement
(
'li'
)
.
Html
::
openElement
(
'li'
)
.
Html
::
rawElement
(
'a'
,
// phpcs:ignore Generic.Files.LineLength.TooLong
[
'href'
=>
'https://www.mediawiki.org/wiki/Special:MyLanguage/Talk:Reading/Web/Advanced_mobile_contributions'
],
$this
->
msg
(
'mobile-frontend-mobile-option-amc-send-feedback'
)->
parse
()
)
.
Html
::
closeElement
(
'li'
)
.
Html
::
closeElement
(
'ul'
)
)
);
return
$layout
;
}
/**
* Builds mobile user preferences field.
* @return \OOUI\FieldLayout
* @throws \OOUI\Exception
*/
private
function
buildMobileUserPreferences
()
{
$spacer
=
new
OOUI\LabelWidget
(
[
'name'
=>
'mobile_preference_spacer'
,
]
);
$userPreferences
=
new
OOUI\FieldLayout
(
$spacer
,
[
'label'
=>
new
OOUI\LabelWidget
(
[
'input'
=>
$spacer
,
'label'
=>
new
OOUI\HtmlSnippet
(
Html
::
openElement
(
'div'
)
.
Html
::
rawElement
(
'strong'
,
[],
$this
->
msg
(
'mobile-frontend-user-pref-option'
)->
parse
()
)
.
Html
::
rawElement
(
'div'
,
[
'class'
=>
'option-description'
],
$this
->
msg
(
'mobile-frontend-user-pref-description'
)->
parse
()
)
.
Html
::
closeElement
(
'div'
)
)
]
),
'id'
=>
'mobile-user-pref'
,
]
);
$userPreferences
->
appendContent
(
new
OOUI\HtmlSnippet
(
Html
::
openElement
(
'ul'
,
[
'class'
=>
'hlist option-links'
]
)
.
Html
::
openElement
(
'li'
)
.
Html
::
rawElement
(
'a'
,
[
'href'
=>
Title
::
newFromText
(
'Special:Preferences'
)->
getLocalURL
()
],
$this
->
msg
(
'mobile-frontend-user-pref-link'
)->
parse
()
)
.
Html
::
closeElement
(
'li'
)
.
Html
::
closeElement
(
'ul'
)
)
);
return
$userPreferences
;
}
/**
* Mark some html as being content
* @param string $html HTML content
* @param string $className additional class names
* @return string of html
*/
private
static
function
contentElement
(
$html
,
$className
=
''
)
{
return
Html
::
rawElement
(
'div'
,
[
'class'
=>
'content'
],
$html
);
}
/**
* Render the settings form (with actual set settings) and add it to the
* output as well as any supporting modules.
*/
private
function
addSettingsForm
()
{
$out
=
$this
->
getOutput
();
$user
=
$this
->
getUser
();
$isTemp
=
$user
->
isTemp
();
$out
->
setPageTitleMsg
(
$this
->
msg
(
'mobile-frontend-main-menu-settings-heading'
)
);
$out
->
enableOOUI
();
if
(
$this
->
getRequest
()->
getCheck
(
'success'
)
)
{
$out
->
wrapWikiMsg
(
self
::
contentElement
(
Html
::
successBox
(
$this
->
msg
(
'savedprefs'
)->
parse
(),
'mw-mf-mobileoptions-message'
)
)
);
}
$fields
=
[];
$form
=
new
OOUI\FormLayout
(
[
'method'
=>
'POST'
,
'id'
=>
'mobile-options'
,
'action'
=>
$this
->
getPageTitle
()->
getLocalURL
(),
]
);
$form
->
addClasses
(
[
'mw-mf-settings'
]
);
if
(
$this
->
amc
->
isAvailable
()
&&
!
$isTemp
)
{
$fields
[]
=
$this
->
buildAMCToggle
();
}
// beta settings
$isInBeta
=
$this
->
mobileContext
->
isBetaGroupMember
();
if
(
$this
->
config
->
get
(
'MFEnableBeta'
)
)
{
$input
=
new
OOUI\CheckboxInputWidget
(
[
'name'
=>
'enableBeta'
,
'infusable'
=>
true
,
'selected'
=>
$isInBeta
,
'id'
=>
'enable-beta-toggle'
,
'value'
=>
'1'
,
]
);
$fields
[]
=
new
OOUI\FieldLayout
(
$input
,
[
'label'
=>
new
OOUI\LabelWidget
(
[
'input'
=>
$input
,
'label'
=>
new
OOUI\HtmlSnippet
(
Html
::
openElement
(
'div'
)
.
Html
::
rawElement
(
'strong'
,
[],
$this
->
msg
(
'mobile-frontend-settings-beta'
)->
parse
()
)
.
Html
::
rawElement
(
'div'
,
[
'class'
=>
'option-description'
],
$this
->
msg
(
'mobile-frontend-opt-in-explain'
)->
parse
()
)
.
Html
::
closeElement
(
'div'
)
)
]
),
'id'
=>
'beta-field'
,
]
);
// TODO The userMode should know how to retrieve features assigned to that mode,
// we shouldn't do any special logic like this in anywhere else in the code
$features
=
array_diff
(
$this
->
featuresManager
->
getAvailableForMode
(
$this
->
featuresManager
->
getMode
(
IFeature
::
CONFIG_BETA
)
),
$this
->
featuresManager
->
getAvailableForMode
(
$this
->
featuresManager
->
getMode
(
IFeature
::
CONFIG_STABLE
)
)
);
$classNames
=
[
'mobile-options-beta-feature'
];
if
(
$isInBeta
)
{
$classNames
[]
=
'is-enabled'
;
$icon
=
'check'
;
}
else
{
$icon
=
'lock'
;
}
/** @var IFeature $feature */
foreach
(
$features
as
$feature
)
{
$fields
[]
=
new
OOUI\FieldLayout
(
new
OOUI\IconWidget
(
[
'icon'
=>
$icon
,
'title'
=>
$this
->
msg
(
'mobile-frontend-beta-only'
)->
text
(),
]
),
[
'classes'
=>
$classNames
,
'label'
=>
new
OOUI\LabelWidget
(
[
'label'
=>
new
OOUI\HtmlSnippet
(
Html
::
rawElement
(
'div'
,
[],
Html
::
element
(
'strong'
,
[],
$this
->
msg
(
$feature
->
getNameKey
()
)->
text
()
)
.
Html
::
element
(
'div'
,
[
'class'
=>
'option-description'
],
$this
->
msg
(
$feature
->
getDescriptionKey
()
)->
text
()
)
)
),
]
)
]
);
}
}
$fields
[]
=
new
OOUI\ButtonInputWidget
(
[
'id'
=>
'mw-mf-settings-save'
,
'infusable'
=>
true
,
'value'
=>
$this
->
msg
(
'mobile-frontend-save-settings'
)->
text
(),
'label'
=>
$this
->
msg
(
'mobile-frontend-save-settings'
)->
text
(),
'flags'
=>
[
'primary'
,
'progressive'
],
'type'
=>
'submit'
,
]
);
if
(
$user
->
isRegistered
()
&&
!
$isTemp
)
{
$fields
[]
=
new
OOUI\HiddenInputWidget
(
[
'name'
=>
'token'
,
'value'
=>
$user
->
getEditToken
()
]
);
// Special:Preferences link (https://phabricator.wikimedia.org/T327506)
$fields
[]
=
$this
->
buildMobileUserPreferences
();
}
$feedbackLink
=
$this
->
getConfig
()->
get
(
'MFBetaFeedbackLink'
);
if
(
$feedbackLink
&&
$isInBeta
)
{
$fields
[]
=
new
OOUI\ButtonWidget
(
[
'framed'
=>
false
,
'href'
=>
$feedbackLink
,
'icon'
=>
'feedback'
,
'flags'
=>
[
'progressive'
,
],
'classes'
=>
[
'mobile-options-feedback'
],
'label'
=>
$this
->
msg
(
'mobile-frontend-send-feedback'
)->
text
(),
]
);
}
$form
->
appendContent
(
...
$fields
);
$out
->
addHTML
(
$form
);
}
/**
* @param WebRequest $request
* @return string url to redirect to
*/
private
function
getRedirectUrl
(
WebRequest
$request
)
{
$returnTo
=
$request
->
getText
(
'returnto'
);
if
(
$returnTo
!==
''
)
{
$title
=
Title
::
newFromText
(
$returnTo
);
if
(
$title
!==
null
)
{
return
$title
->
getFullURL
(
$request
->
getText
(
'returntoquery'
)
);
}
}
return
$this
->
mobileContext
->
getMobileUrl
(
$this
->
getPageTitle
()->
getFullURL
(
'success'
)
);
}
/**
* Saves the settings submitted by the settings form
*/
private
function
submitSettingsForm
()
{
$request
=
$this
->
getRequest
();
$user
=
$this
->
getUser
();
if
(
$user
->
isRegistered
()
&&
!
$user
->
matchEditToken
(
$request
->
getVal
(
'token'
)
)
)
{
$errorText
=
__METHOD__
.
'(): token mismatch'
;
wfDebugLog
(
'mobile'
,
$errorText
);
$this
->
getOutput
()->
addHTML
(
Html
::
errorBox
(
$this
->
msg
(
"mobile-frontend-save-error"
)->
parse
()
)
);
$this
->
addSettingsForm
();
return
;
}
// We must treat forms that only update a single field specially because if we
// don't, all the other options will be clobbered with default values
$updateSingleOption
=
$request
->
getRawVal
(
'updateSingleOption'
);
$enableAMC
=
$request
->
getBool
(
'enableAMC'
);
$enableBetaMode
=
$request
->
getBool
(
'enableBeta'
);
$mobileMode
=
$enableBetaMode
?
MobileContext
::
MODE_BETA
:
''
;
if
(
$updateSingleOption
!==
'enableAMC'
)
{
$this
->
mobileContext
->
setMobileMode
(
$mobileMode
);
}
if
(
$this
->
amc
->
isAvailable
()
&&
$updateSingleOption
!==
'enableBeta'
)
{
$this
->
userMode
->
setEnabled
(
$enableAMC
);
}
DeferredUpdates
::
addCallableUpdate
(
function
()
use
(
$updateSingleOption
,
$mobileMode
,
$enableAMC
)
{
if
(
$this
->
readOnlyMode
->
isReadOnly
()
)
{
return
;
}
$latestUser
=
$this
->
getUser
()->
getInstanceForUpdate
();
if
(
$latestUser
===
null
||
!
$latestUser
->
isNamed
()
)
{
// The user is anon, temp user or could not be loaded from the database.
return
;
}
if
(
$updateSingleOption
!==
'enableAMC'
)
{
$this
->
userOptionsManager
->
setOption
(
$latestUser
,
MobileContext
::
USER_MODE_PREFERENCE_NAME
,
$mobileMode
);
}
if
(
$this
->
amc
->
isAvailable
()
&&
$updateSingleOption
!==
'enableBeta'
)
{
$this
->
userOptionsManager
->
setOption
(
$latestUser
,
UserMode
::
USER_OPTION_MODE_AMC
,
$enableAMC
?
UserMode
::
OPTION_ENABLED
:
UserMode
::
OPTION_DISABLED
);
}
$latestUser
->
saveSettings
();
},
DeferredUpdates
::
PRESEND
);
$this
->
getOutput
()->
redirect
(
$this
->
getRedirectUrl
(
$request
)
);
}
}
File Metadata
Details
Attached
Mime Type
text/x-php
Expires
Sat, Oct 3, 07:34 (1 w, 6 d ago)
Storage Engine
local-disk
Storage Format
Raw Data
Storage Handle
6f/91/e16c6544dc57ff10cd5ad8dbd42b
Default Alt Text
SpecialMobileOptions.php (12 KB)
Attached To
Mode
rMWPROD MediaWiki Production
Attached
Detach File
Event Timeline
Log In to Comment