2014-08-07 11:38:34 +00:00
|
|
|
<?php
|
|
|
|
/**
|
|
|
|
* Vector - Modern version of MonoBook with fresh look and many usability
|
|
|
|
* improvements.
|
|
|
|
*
|
|
|
|
* 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
|
|
|
|
*
|
|
|
|
* @file
|
|
|
|
* @ingroup Skins
|
|
|
|
*/
|
|
|
|
|
2019-04-27 23:07:20 +00:00
|
|
|
use MediaWiki\MediaWikiServices;
|
|
|
|
|
2014-08-07 11:38:34 +00:00
|
|
|
/**
|
2018-01-30 23:56:42 +00:00
|
|
|
* QuickTemplate subclass for Vector
|
2014-08-07 11:38:34 +00:00
|
|
|
* @ingroup Skins
|
|
|
|
*/
|
|
|
|
class VectorTemplate extends BaseTemplate {
|
2020-04-03 20:05:22 +00:00
|
|
|
/* @var int */
|
|
|
|
private const MENU_TYPE_DEFAULT = 0;
|
|
|
|
/* @var int */
|
|
|
|
private const MENU_TYPE_TABS = 1;
|
|
|
|
/* @var int */
|
|
|
|
private const MENU_TYPE_DROPDOWN = 2;
|
|
|
|
|
Add opt-out link to Sidebar for Vector/Logged-in Users Without Abstractions
This commit is singularly focused on adding a link to the sidebar for
Vector, logged-in users. It does the bare minimum to fulfill the
requirements of T243281.
Additionally, it will help to answer the question "Do we need to use
abstractions (other than maybe different templates) to separate Legacy
Vector from Vector" by intentionally leaving out any abstractions in
order to make it easier to compare with a follow-up patch
(Ib2ef15180df73360cc1de25b893e49d415d23e1a) which does use abstractions.
It is a good thing to question whether or not we need addtional
abstractions in VectorTemplate and if they will help us as unnecessary
abstractions can have the opposite effect and just lead to further
frustrations down the road.
Therefore, I urge you, the reviewer, to let me know your thoughts! If
abstractions are viewed as not making our lives any easier, the
follow-up patches may be completely discarded and that's totally okay
with me. :) I think it's a good think to talk about now though.
Important changes:
* The VectorTemplate constructor was changed to allow injecting the
config, templateParser, and isLegacy boolean (only the config was
allowed before this commit). According to MediaWiki's Stable Interface
Policy, "Constructor signatures are generally considered unstable unless
explicitly declared stable for calling" [3]. Given that VecorTemplate's
constructor is not marked as stable, it is justified to do this without
warning according to the policy.
* Due to the above, the 'setTemplate' method is no longer needed and was
marked as deprecated.
* VectorTemplateTest was made to adapt to the new VectorTemplate
constructor. Additionally, it now extends from
MediaWikiIntegrationTestCase which my intelliphense server can pick up.
I *think* MediaWikiTestCase is just an alias to
MediaWikiIntegrationTestCase [1] and MediaWikiTestCase file was renamed
to MediaWikiIntegrationTestCase in [2], but I'm willing to change it
back if there is pushback to this.
Open questions:
* What are VectorTemplate's responsibilities? To me, it acts right now
as a controller (because it echos the full HTML string from the
template), a model (because SkinTemplate::prepareQuickTemplate sets data
on it which it later retrieves through `$this->get()`), a presenter
(because it adds data tailored for a web-centric view), and a view
(because it renders HTML strings instead of letting the view/template be
solely responsible for that). Arguably, some business logic might be
mixed in there as well (because it checks to see if a User is logged
in/has necessary permissions to show x which my changes here add to).
This might not be a problem if we keep VectorTemplate relatively small,
but will it remain this way as we progress further in Desktop
Improvements?
* How do we write tests for VectorTemplate without exposing unnecessary
public methods? For example, if I want to test the `getSkinData()`
method to see what state will be sent to the template, how should I do
this? One option might be to use `TestingAccessWrapper` to expose these
private methods which is what
`VectorTemplateTest::testbuildViewsProps()` does. Another option is to
accept this method as public. Is there a better way? Keep in mind that
even with access to this method, there might be many things to mock.
[1] https://github.com/wikimedia/mediawiki/blob/0030cb525be6cabc1d63de80586b2017d4bbe354/tests/common/TestsAutoLoader.php#L64
[2] Ie717b0ecf4fcfd089d46248f14853c80b7ef4a76
[3] https://www.mediawiki.org/wiki/Stable_interface_policy
Bug: T243281
Change-Id: I0571b041bcd7f19bec9f103fa7bccdd093f6394d
2020-03-17 20:21:33 +00:00
|
|
|
/**
|
|
|
|
* T243281: Code used to track clicks to opt-out link.
|
|
|
|
*
|
|
|
|
* The "vct" substring is used to describe the newest "Vector" (non-legacy)
|
|
|
|
* feature. The "w" describes the web platform. The "1" describes the version
|
|
|
|
* of the feature.
|
|
|
|
*
|
|
|
|
* @see https://wikitech.wikimedia.org/wiki/Provenance
|
|
|
|
* @var string
|
|
|
|
*/
|
|
|
|
private const OPT_OUT_LINK_TRACKING_CODE = 'vctw1';
|
2014-08-07 11:38:34 +00:00
|
|
|
|
2020-01-13 09:23:59 +00:00
|
|
|
/** @var TemplateParser */
|
|
|
|
private $templateParser;
|
2020-04-01 23:55:55 +00:00
|
|
|
/** @var string File name of the root (master) template without folder path and extension */
|
|
|
|
private $templateRoot;
|
2020-01-13 09:23:59 +00:00
|
|
|
|
Add opt-out link to Sidebar for Vector/Logged-in Users Without Abstractions
This commit is singularly focused on adding a link to the sidebar for
Vector, logged-in users. It does the bare minimum to fulfill the
requirements of T243281.
Additionally, it will help to answer the question "Do we need to use
abstractions (other than maybe different templates) to separate Legacy
Vector from Vector" by intentionally leaving out any abstractions in
order to make it easier to compare with a follow-up patch
(Ib2ef15180df73360cc1de25b893e49d415d23e1a) which does use abstractions.
It is a good thing to question whether or not we need addtional
abstractions in VectorTemplate and if they will help us as unnecessary
abstractions can have the opposite effect and just lead to further
frustrations down the road.
Therefore, I urge you, the reviewer, to let me know your thoughts! If
abstractions are viewed as not making our lives any easier, the
follow-up patches may be completely discarded and that's totally okay
with me. :) I think it's a good think to talk about now though.
Important changes:
* The VectorTemplate constructor was changed to allow injecting the
config, templateParser, and isLegacy boolean (only the config was
allowed before this commit). According to MediaWiki's Stable Interface
Policy, "Constructor signatures are generally considered unstable unless
explicitly declared stable for calling" [3]. Given that VecorTemplate's
constructor is not marked as stable, it is justified to do this without
warning according to the policy.
* Due to the above, the 'setTemplate' method is no longer needed and was
marked as deprecated.
* VectorTemplateTest was made to adapt to the new VectorTemplate
constructor. Additionally, it now extends from
MediaWikiIntegrationTestCase which my intelliphense server can pick up.
I *think* MediaWikiTestCase is just an alias to
MediaWikiIntegrationTestCase [1] and MediaWikiTestCase file was renamed
to MediaWikiIntegrationTestCase in [2], but I'm willing to change it
back if there is pushback to this.
Open questions:
* What are VectorTemplate's responsibilities? To me, it acts right now
as a controller (because it echos the full HTML string from the
template), a model (because SkinTemplate::prepareQuickTemplate sets data
on it which it later retrieves through `$this->get()`), a presenter
(because it adds data tailored for a web-centric view), and a view
(because it renders HTML strings instead of letting the view/template be
solely responsible for that). Arguably, some business logic might be
mixed in there as well (because it checks to see if a User is logged
in/has necessary permissions to show x which my changes here add to).
This might not be a problem if we keep VectorTemplate relatively small,
but will it remain this way as we progress further in Desktop
Improvements?
* How do we write tests for VectorTemplate without exposing unnecessary
public methods? For example, if I want to test the `getSkinData()`
method to see what state will be sent to the template, how should I do
this? One option might be to use `TestingAccessWrapper` to expose these
private methods which is what
`VectorTemplateTest::testbuildViewsProps()` does. Another option is to
accept this method as public. Is there a better way? Keep in mind that
even with access to this method, there might be many things to mock.
[1] https://github.com/wikimedia/mediawiki/blob/0030cb525be6cabc1d63de80586b2017d4bbe354/tests/common/TestsAutoLoader.php#L64
[2] Ie717b0ecf4fcfd089d46248f14853c80b7ef4a76
[3] https://www.mediawiki.org/wiki/Stable_interface_policy
Bug: T243281
Change-Id: I0571b041bcd7f19bec9f103fa7bccdd093f6394d
2020-03-17 20:21:33 +00:00
|
|
|
/** @var bool */
|
|
|
|
private $isLegacy;
|
|
|
|
|
2020-01-13 09:23:59 +00:00
|
|
|
/**
|
Add opt-out link to Sidebar for Vector/Logged-in Users Without Abstractions
This commit is singularly focused on adding a link to the sidebar for
Vector, logged-in users. It does the bare minimum to fulfill the
requirements of T243281.
Additionally, it will help to answer the question "Do we need to use
abstractions (other than maybe different templates) to separate Legacy
Vector from Vector" by intentionally leaving out any abstractions in
order to make it easier to compare with a follow-up patch
(Ib2ef15180df73360cc1de25b893e49d415d23e1a) which does use abstractions.
It is a good thing to question whether or not we need addtional
abstractions in VectorTemplate and if they will help us as unnecessary
abstractions can have the opposite effect and just lead to further
frustrations down the road.
Therefore, I urge you, the reviewer, to let me know your thoughts! If
abstractions are viewed as not making our lives any easier, the
follow-up patches may be completely discarded and that's totally okay
with me. :) I think it's a good think to talk about now though.
Important changes:
* The VectorTemplate constructor was changed to allow injecting the
config, templateParser, and isLegacy boolean (only the config was
allowed before this commit). According to MediaWiki's Stable Interface
Policy, "Constructor signatures are generally considered unstable unless
explicitly declared stable for calling" [3]. Given that VecorTemplate's
constructor is not marked as stable, it is justified to do this without
warning according to the policy.
* Due to the above, the 'setTemplate' method is no longer needed and was
marked as deprecated.
* VectorTemplateTest was made to adapt to the new VectorTemplate
constructor. Additionally, it now extends from
MediaWikiIntegrationTestCase which my intelliphense server can pick up.
I *think* MediaWikiTestCase is just an alias to
MediaWikiIntegrationTestCase [1] and MediaWikiTestCase file was renamed
to MediaWikiIntegrationTestCase in [2], but I'm willing to change it
back if there is pushback to this.
Open questions:
* What are VectorTemplate's responsibilities? To me, it acts right now
as a controller (because it echos the full HTML string from the
template), a model (because SkinTemplate::prepareQuickTemplate sets data
on it which it later retrieves through `$this->get()`), a presenter
(because it adds data tailored for a web-centric view), and a view
(because it renders HTML strings instead of letting the view/template be
solely responsible for that). Arguably, some business logic might be
mixed in there as well (because it checks to see if a User is logged
in/has necessary permissions to show x which my changes here add to).
This might not be a problem if we keep VectorTemplate relatively small,
but will it remain this way as we progress further in Desktop
Improvements?
* How do we write tests for VectorTemplate without exposing unnecessary
public methods? For example, if I want to test the `getSkinData()`
method to see what state will be sent to the template, how should I do
this? One option might be to use `TestingAccessWrapper` to expose these
private methods which is what
`VectorTemplateTest::testbuildViewsProps()` does. Another option is to
accept this method as public. Is there a better way? Keep in mind that
even with access to this method, there might be many things to mock.
[1] https://github.com/wikimedia/mediawiki/blob/0030cb525be6cabc1d63de80586b2017d4bbe354/tests/common/TestsAutoLoader.php#L64
[2] Ie717b0ecf4fcfd089d46248f14853c80b7ef4a76
[3] https://www.mediawiki.org/wiki/Stable_interface_policy
Bug: T243281
Change-Id: I0571b041bcd7f19bec9f103fa7bccdd093f6394d
2020-03-17 20:21:33 +00:00
|
|
|
* @param Config $config
|
|
|
|
* @param TemplateParser $templateParser
|
|
|
|
* @param bool $isLegacy
|
2020-01-13 09:23:59 +00:00
|
|
|
*/
|
Add opt-out link to Sidebar for Vector/Logged-in Users Without Abstractions
This commit is singularly focused on adding a link to the sidebar for
Vector, logged-in users. It does the bare minimum to fulfill the
requirements of T243281.
Additionally, it will help to answer the question "Do we need to use
abstractions (other than maybe different templates) to separate Legacy
Vector from Vector" by intentionally leaving out any abstractions in
order to make it easier to compare with a follow-up patch
(Ib2ef15180df73360cc1de25b893e49d415d23e1a) which does use abstractions.
It is a good thing to question whether or not we need addtional
abstractions in VectorTemplate and if they will help us as unnecessary
abstractions can have the opposite effect and just lead to further
frustrations down the road.
Therefore, I urge you, the reviewer, to let me know your thoughts! If
abstractions are viewed as not making our lives any easier, the
follow-up patches may be completely discarded and that's totally okay
with me. :) I think it's a good think to talk about now though.
Important changes:
* The VectorTemplate constructor was changed to allow injecting the
config, templateParser, and isLegacy boolean (only the config was
allowed before this commit). According to MediaWiki's Stable Interface
Policy, "Constructor signatures are generally considered unstable unless
explicitly declared stable for calling" [3]. Given that VecorTemplate's
constructor is not marked as stable, it is justified to do this without
warning according to the policy.
* Due to the above, the 'setTemplate' method is no longer needed and was
marked as deprecated.
* VectorTemplateTest was made to adapt to the new VectorTemplate
constructor. Additionally, it now extends from
MediaWikiIntegrationTestCase which my intelliphense server can pick up.
I *think* MediaWikiTestCase is just an alias to
MediaWikiIntegrationTestCase [1] and MediaWikiTestCase file was renamed
to MediaWikiIntegrationTestCase in [2], but I'm willing to change it
back if there is pushback to this.
Open questions:
* What are VectorTemplate's responsibilities? To me, it acts right now
as a controller (because it echos the full HTML string from the
template), a model (because SkinTemplate::prepareQuickTemplate sets data
on it which it later retrieves through `$this->get()`), a presenter
(because it adds data tailored for a web-centric view), and a view
(because it renders HTML strings instead of letting the view/template be
solely responsible for that). Arguably, some business logic might be
mixed in there as well (because it checks to see if a User is logged
in/has necessary permissions to show x which my changes here add to).
This might not be a problem if we keep VectorTemplate relatively small,
but will it remain this way as we progress further in Desktop
Improvements?
* How do we write tests for VectorTemplate without exposing unnecessary
public methods? For example, if I want to test the `getSkinData()`
method to see what state will be sent to the template, how should I do
this? One option might be to use `TestingAccessWrapper` to expose these
private methods which is what
`VectorTemplateTest::testbuildViewsProps()` does. Another option is to
accept this method as public. Is there a better way? Keep in mind that
even with access to this method, there might be many things to mock.
[1] https://github.com/wikimedia/mediawiki/blob/0030cb525be6cabc1d63de80586b2017d4bbe354/tests/common/TestsAutoLoader.php#L64
[2] Ie717b0ecf4fcfd089d46248f14853c80b7ef4a76
[3] https://www.mediawiki.org/wiki/Stable_interface_policy
Bug: T243281
Change-Id: I0571b041bcd7f19bec9f103fa7bccdd093f6394d
2020-03-17 20:21:33 +00:00
|
|
|
public function __construct(
|
|
|
|
Config $config,
|
|
|
|
TemplateParser $templateParser,
|
|
|
|
bool $isLegacy
|
|
|
|
) {
|
|
|
|
parent::__construct( $config );
|
|
|
|
|
|
|
|
$this->templateParser = $templateParser;
|
|
|
|
$this->isLegacy = $isLegacy;
|
2020-04-01 23:55:55 +00:00
|
|
|
$this->templateRoot = $isLegacy ? 'legacy' : 'index';
|
2020-01-16 21:11:54 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
/**
|
|
|
|
* The template parser might be undefined. This function will check if it set first
|
|
|
|
*
|
|
|
|
* @return TemplateParser
|
|
|
|
*/
|
|
|
|
protected function getTemplateParser() {
|
|
|
|
if ( $this->templateParser === null ) {
|
|
|
|
throw new \LogicException(
|
|
|
|
'TemplateParser has to be set first via setTemplateParser method'
|
|
|
|
);
|
|
|
|
}
|
|
|
|
return $this->templateParser;
|
2020-01-13 09:23:59 +00:00
|
|
|
}
|
|
|
|
|
2014-08-07 11:38:34 +00:00
|
|
|
/**
|
Add opt-out link to Sidebar for Vector/Logged-in Users Without Abstractions
This commit is singularly focused on adding a link to the sidebar for
Vector, logged-in users. It does the bare minimum to fulfill the
requirements of T243281.
Additionally, it will help to answer the question "Do we need to use
abstractions (other than maybe different templates) to separate Legacy
Vector from Vector" by intentionally leaving out any abstractions in
order to make it easier to compare with a follow-up patch
(Ib2ef15180df73360cc1de25b893e49d415d23e1a) which does use abstractions.
It is a good thing to question whether or not we need addtional
abstractions in VectorTemplate and if they will help us as unnecessary
abstractions can have the opposite effect and just lead to further
frustrations down the road.
Therefore, I urge you, the reviewer, to let me know your thoughts! If
abstractions are viewed as not making our lives any easier, the
follow-up patches may be completely discarded and that's totally okay
with me. :) I think it's a good think to talk about now though.
Important changes:
* The VectorTemplate constructor was changed to allow injecting the
config, templateParser, and isLegacy boolean (only the config was
allowed before this commit). According to MediaWiki's Stable Interface
Policy, "Constructor signatures are generally considered unstable unless
explicitly declared stable for calling" [3]. Given that VecorTemplate's
constructor is not marked as stable, it is justified to do this without
warning according to the policy.
* Due to the above, the 'setTemplate' method is no longer needed and was
marked as deprecated.
* VectorTemplateTest was made to adapt to the new VectorTemplate
constructor. Additionally, it now extends from
MediaWikiIntegrationTestCase which my intelliphense server can pick up.
I *think* MediaWikiTestCase is just an alias to
MediaWikiIntegrationTestCase [1] and MediaWikiTestCase file was renamed
to MediaWikiIntegrationTestCase in [2], but I'm willing to change it
back if there is pushback to this.
Open questions:
* What are VectorTemplate's responsibilities? To me, it acts right now
as a controller (because it echos the full HTML string from the
template), a model (because SkinTemplate::prepareQuickTemplate sets data
on it which it later retrieves through `$this->get()`), a presenter
(because it adds data tailored for a web-centric view), and a view
(because it renders HTML strings instead of letting the view/template be
solely responsible for that). Arguably, some business logic might be
mixed in there as well (because it checks to see if a User is logged
in/has necessary permissions to show x which my changes here add to).
This might not be a problem if we keep VectorTemplate relatively small,
but will it remain this way as we progress further in Desktop
Improvements?
* How do we write tests for VectorTemplate without exposing unnecessary
public methods? For example, if I want to test the `getSkinData()`
method to see what state will be sent to the template, how should I do
this? One option might be to use `TestingAccessWrapper` to expose these
private methods which is what
`VectorTemplateTest::testbuildViewsProps()` does. Another option is to
accept this method as public. Is there a better way? Keep in mind that
even with access to this method, there might be many things to mock.
[1] https://github.com/wikimedia/mediawiki/blob/0030cb525be6cabc1d63de80586b2017d4bbe354/tests/common/TestsAutoLoader.php#L64
[2] Ie717b0ecf4fcfd089d46248f14853c80b7ef4a76
[3] https://www.mediawiki.org/wiki/Stable_interface_policy
Bug: T243281
Change-Id: I0571b041bcd7f19bec9f103fa7bccdd093f6394d
2020-03-17 20:21:33 +00:00
|
|
|
* @return array Returns an array of data shared between Vector and legacy
|
|
|
|
* Vector.
|
2014-08-07 11:38:34 +00:00
|
|
|
*/
|
Add opt-out link to Sidebar for Vector/Logged-in Users Without Abstractions
This commit is singularly focused on adding a link to the sidebar for
Vector, logged-in users. It does the bare minimum to fulfill the
requirements of T243281.
Additionally, it will help to answer the question "Do we need to use
abstractions (other than maybe different templates) to separate Legacy
Vector from Vector" by intentionally leaving out any abstractions in
order to make it easier to compare with a follow-up patch
(Ib2ef15180df73360cc1de25b893e49d415d23e1a) which does use abstractions.
It is a good thing to question whether or not we need addtional
abstractions in VectorTemplate and if they will help us as unnecessary
abstractions can have the opposite effect and just lead to further
frustrations down the road.
Therefore, I urge you, the reviewer, to let me know your thoughts! If
abstractions are viewed as not making our lives any easier, the
follow-up patches may be completely discarded and that's totally okay
with me. :) I think it's a good think to talk about now though.
Important changes:
* The VectorTemplate constructor was changed to allow injecting the
config, templateParser, and isLegacy boolean (only the config was
allowed before this commit). According to MediaWiki's Stable Interface
Policy, "Constructor signatures are generally considered unstable unless
explicitly declared stable for calling" [3]. Given that VecorTemplate's
constructor is not marked as stable, it is justified to do this without
warning according to the policy.
* Due to the above, the 'setTemplate' method is no longer needed and was
marked as deprecated.
* VectorTemplateTest was made to adapt to the new VectorTemplate
constructor. Additionally, it now extends from
MediaWikiIntegrationTestCase which my intelliphense server can pick up.
I *think* MediaWikiTestCase is just an alias to
MediaWikiIntegrationTestCase [1] and MediaWikiTestCase file was renamed
to MediaWikiIntegrationTestCase in [2], but I'm willing to change it
back if there is pushback to this.
Open questions:
* What are VectorTemplate's responsibilities? To me, it acts right now
as a controller (because it echos the full HTML string from the
template), a model (because SkinTemplate::prepareQuickTemplate sets data
on it which it later retrieves through `$this->get()`), a presenter
(because it adds data tailored for a web-centric view), and a view
(because it renders HTML strings instead of letting the view/template be
solely responsible for that). Arguably, some business logic might be
mixed in there as well (because it checks to see if a User is logged
in/has necessary permissions to show x which my changes here add to).
This might not be a problem if we keep VectorTemplate relatively small,
but will it remain this way as we progress further in Desktop
Improvements?
* How do we write tests for VectorTemplate without exposing unnecessary
public methods? For example, if I want to test the `getSkinData()`
method to see what state will be sent to the template, how should I do
this? One option might be to use `TestingAccessWrapper` to expose these
private methods which is what
`VectorTemplateTest::testbuildViewsProps()` does. Another option is to
accept this method as public. Is there a better way? Keep in mind that
even with access to this method, there might be many things to mock.
[1] https://github.com/wikimedia/mediawiki/blob/0030cb525be6cabc1d63de80586b2017d4bbe354/tests/common/TestsAutoLoader.php#L64
[2] Ie717b0ecf4fcfd089d46248f14853c80b7ef4a76
[3] https://www.mediawiki.org/wiki/Stable_interface_policy
Bug: T243281
Change-Id: I0571b041bcd7f19bec9f103fa7bccdd093f6394d
2020-03-17 20:21:33 +00:00
|
|
|
private function getSkinData() : array {
|
2020-02-28 20:53:44 +00:00
|
|
|
$contentNavigation = $this->get( 'content_navigation', [] );
|
|
|
|
$this->set( 'namespace_urls', $contentNavigation[ 'namespaces' ] );
|
|
|
|
$this->set( 'view_urls', $contentNavigation[ 'views' ] );
|
|
|
|
$this->set( 'action_urls', $contentNavigation[ 'actions' ] );
|
|
|
|
$this->set( 'variant_urls', $contentNavigation[ 'variants' ] );
|
2014-08-07 11:38:34 +00:00
|
|
|
|
2017-07-26 17:15:27 +00:00
|
|
|
// Move the watch/unwatch star outside of the collapsed "actions" menu to the main "views" menu
|
2014-08-13 18:39:38 +00:00
|
|
|
if ( $this->config->get( 'VectorUseIconWatch' ) ) {
|
2019-04-27 23:07:20 +00:00
|
|
|
$mode = ( $this->getSkin()->getRelevantTitle()->isWatchable() &&
|
|
|
|
MediaWikiServices::getInstance()->getPermissionManager()->userHasRight(
|
|
|
|
$this->getSkin()->getUser(),
|
|
|
|
'viewmywatchlist'
|
|
|
|
) &&
|
|
|
|
MediaWikiServices::getInstance()->getWatchedItemStore()->isWatched(
|
|
|
|
$this->getSkin()->getUser(),
|
|
|
|
$this->getSkin()->getRelevantTitle()
|
|
|
|
)
|
|
|
|
) ? 'unwatch' : 'watch';
|
2014-08-07 11:38:34 +00:00
|
|
|
|
2020-02-28 20:53:44 +00:00
|
|
|
$actionUrls = $this->get( 'action_urls', [] );
|
|
|
|
if ( array_key_exists( $mode, $actionUrls ) ) {
|
|
|
|
$viewUrls = $this->get( 'view_urls' );
|
|
|
|
$viewUrls[ $mode ] = $actionUrls[ $mode ];
|
|
|
|
unset( $actionUrls[ $mode ] );
|
|
|
|
$this->set( 'view_urls', $viewUrls );
|
|
|
|
$this->set( 'action_urls', $actionUrls );
|
2014-08-07 11:38:34 +00:00
|
|
|
}
|
|
|
|
}
|
2015-06-08 21:12:40 +00:00
|
|
|
|
2020-01-16 22:11:53 +00:00
|
|
|
ob_start();
|
2020-01-24 11:50:21 +00:00
|
|
|
Hooks::run( 'VectorBeforeFooter', [], '1.35' );
|
2020-01-16 22:11:53 +00:00
|
|
|
$htmlHookVectorBeforeFooter = ob_get_contents();
|
|
|
|
ob_end_clean();
|
|
|
|
|
2020-03-06 22:53:04 +00:00
|
|
|
// Naming conventions for Mustache parameters.
|
|
|
|
//
|
|
|
|
// Value type (first segment):
|
2020-04-14 22:44:33 +00:00
|
|
|
// - Prefix "is" or "has" for boolean values.
|
2020-03-06 22:53:04 +00:00
|
|
|
// - Prefix "msg-" for interface message text.
|
|
|
|
// - Prefix "html-" for raw HTML.
|
|
|
|
// - Prefix "data-" for an array of template parameters that should be passed directly
|
2020-02-17 19:49:43 +00:00
|
|
|
// to a template partial.
|
2020-03-06 22:53:04 +00:00
|
|
|
// - Prefix "array-" for lists of any values.
|
|
|
|
//
|
|
|
|
// Source of value (first or second segment)
|
|
|
|
// - Segment "page-" for data relating to the current page (e.g. Title, WikiPage, or OutputPage).
|
|
|
|
// - Segment "hook-" for any thing generated from a hook.
|
|
|
|
// It should be followed by the name of the hook in hyphenated lowercase.
|
|
|
|
//
|
|
|
|
// Conditionally used values must use null to indicate absence (not false or '').
|
Add opt-out link to Sidebar for Vector/Logged-in Users Without Abstractions
This commit is singularly focused on adding a link to the sidebar for
Vector, logged-in users. It does the bare minimum to fulfill the
requirements of T243281.
Additionally, it will help to answer the question "Do we need to use
abstractions (other than maybe different templates) to separate Legacy
Vector from Vector" by intentionally leaving out any abstractions in
order to make it easier to compare with a follow-up patch
(Ib2ef15180df73360cc1de25b893e49d415d23e1a) which does use abstractions.
It is a good thing to question whether or not we need addtional
abstractions in VectorTemplate and if they will help us as unnecessary
abstractions can have the opposite effect and just lead to further
frustrations down the road.
Therefore, I urge you, the reviewer, to let me know your thoughts! If
abstractions are viewed as not making our lives any easier, the
follow-up patches may be completely discarded and that's totally okay
with me. :) I think it's a good think to talk about now though.
Important changes:
* The VectorTemplate constructor was changed to allow injecting the
config, templateParser, and isLegacy boolean (only the config was
allowed before this commit). According to MediaWiki's Stable Interface
Policy, "Constructor signatures are generally considered unstable unless
explicitly declared stable for calling" [3]. Given that VecorTemplate's
constructor is not marked as stable, it is justified to do this without
warning according to the policy.
* Due to the above, the 'setTemplate' method is no longer needed and was
marked as deprecated.
* VectorTemplateTest was made to adapt to the new VectorTemplate
constructor. Additionally, it now extends from
MediaWikiIntegrationTestCase which my intelliphense server can pick up.
I *think* MediaWikiTestCase is just an alias to
MediaWikiIntegrationTestCase [1] and MediaWikiTestCase file was renamed
to MediaWikiIntegrationTestCase in [2], but I'm willing to change it
back if there is pushback to this.
Open questions:
* What are VectorTemplate's responsibilities? To me, it acts right now
as a controller (because it echos the full HTML string from the
template), a model (because SkinTemplate::prepareQuickTemplate sets data
on it which it later retrieves through `$this->get()`), a presenter
(because it adds data tailored for a web-centric view), and a view
(because it renders HTML strings instead of letting the view/template be
solely responsible for that). Arguably, some business logic might be
mixed in there as well (because it checks to see if a User is logged
in/has necessary permissions to show x which my changes here add to).
This might not be a problem if we keep VectorTemplate relatively small,
but will it remain this way as we progress further in Desktop
Improvements?
* How do we write tests for VectorTemplate without exposing unnecessary
public methods? For example, if I want to test the `getSkinData()`
method to see what state will be sent to the template, how should I do
this? One option might be to use `TestingAccessWrapper` to expose these
private methods which is what
`VectorTemplateTest::testbuildViewsProps()` does. Another option is to
accept this method as public. Is there a better way? Keep in mind that
even with access to this method, there might be many things to mock.
[1] https://github.com/wikimedia/mediawiki/blob/0030cb525be6cabc1d63de80586b2017d4bbe354/tests/common/TestsAutoLoader.php#L64
[2] Ie717b0ecf4fcfd089d46248f14853c80b7ef4a76
[3] https://www.mediawiki.org/wiki/Stable_interface_policy
Bug: T243281
Change-Id: I0571b041bcd7f19bec9f103fa7bccdd093f6394d
2020-03-17 20:21:33 +00:00
|
|
|
$commonSkinData = [
|
2019-02-26 18:44:10 +00:00
|
|
|
'html-headelement' => $this->get( 'headelement', '' ),
|
|
|
|
'html-sitenotice' => $this->get( 'sitenotice', null ),
|
2020-04-08 02:01:32 +00:00
|
|
|
'html-indicators' => $this->getIndicators(),
|
2019-02-26 18:44:10 +00:00
|
|
|
'page-langcode' => $this->getSkin()->getTitle()->getPageViewLanguage()->getHtmlCode(),
|
2020-02-28 20:53:44 +00:00
|
|
|
'page-isarticle' => (bool)$this->get( 'isarticle' ),
|
2019-02-26 18:44:10 +00:00
|
|
|
|
2019-04-02 18:42:01 +00:00
|
|
|
// Remember that the string '0' is a valid title.
|
|
|
|
// From OutputPage::getPageTitle, via ::setPageTitle().
|
|
|
|
'html-title' => $this->get( 'title', '' ),
|
2015-06-08 21:12:40 +00:00
|
|
|
|
2019-02-26 18:44:10 +00:00
|
|
|
'html-prebodyhtml' => $this->get( 'prebodyhtml', '' ),
|
|
|
|
'msg-tagline' => $this->getMsg( 'tagline' )->text(),
|
|
|
|
// TODO: mediawiki/SkinTemplate should expose langCode and langDir properly.
|
|
|
|
'html-userlangattributes' => $this->get( 'userlangattributes', '' ),
|
|
|
|
// From OutputPage::getSubtitle()
|
|
|
|
'html-subtitle' => $this->get( 'subtitle', '' ),
|
2019-01-23 02:51:20 +00:00
|
|
|
|
2019-02-26 18:44:10 +00:00
|
|
|
// TODO: Use directly Skin::getUndeleteLink() directly.
|
|
|
|
// Always returns string, cast to null if empty.
|
|
|
|
'html-undelete' => $this->get( 'undelete', null ) ?: null,
|
2019-01-23 02:51:20 +00:00
|
|
|
|
2019-02-26 18:44:10 +00:00
|
|
|
// From Skin::getNewtalks(). Always returns string, cast to null if empty.
|
|
|
|
'html-newtalk' => $this->get( 'newtalk', '' ) ?: null,
|
2019-01-23 02:51:20 +00:00
|
|
|
|
2019-02-26 18:44:10 +00:00
|
|
|
'msg-jumptonavigation' => $this->getMsg( 'vector-jumptonavigation' )->text(),
|
|
|
|
'msg-jumptosearch' => $this->getMsg( 'vector-jumptosearch' )->text(),
|
|
|
|
|
|
|
|
// Result of OutputPage::addHTML calls
|
|
|
|
'html-bodycontent' => $this->get( 'bodycontent' ),
|
|
|
|
|
|
|
|
'html-printfooter' => $this->get( 'printfooter', null ),
|
|
|
|
'html-catlinks' => $this->get( 'catlinks', '' ),
|
|
|
|
'html-dataAfterContent' => $this->get( 'dataAfterContent', '' ),
|
|
|
|
// From MWDebug::getHTMLDebugLog (when $wgShowDebug is enabled)
|
|
|
|
'html-debuglog' => $this->get( 'debughtml', '' ),
|
|
|
|
// From BaseTemplate::getTrail (handles bottom JavaScript)
|
2020-01-16 21:52:56 +00:00
|
|
|
'html-printtail' => $this->getTrail() . '</body></html>',
|
2020-02-17 19:49:43 +00:00
|
|
|
'data-footer' => [
|
2020-01-16 22:11:53 +00:00
|
|
|
'html-userlangattributes' => $this->get( 'userlangattributes', '' ),
|
|
|
|
'html-hook-vector-before-footer' => $htmlHookVectorBeforeFooter,
|
|
|
|
'array-footer-rows' => $this->getTemplateFooterRows(),
|
2020-02-17 19:49:43 +00:00
|
|
|
],
|
2020-03-25 20:57:46 +00:00
|
|
|
'html-navigation-heading' => $this->getMsg( 'navigation-heading' ),
|
|
|
|
'data-namespace-tabs' => $this->buildNamespacesProps(),
|
|
|
|
'data-variants' => $this->buildVariantsProps(),
|
|
|
|
'data-page-actions' => $this->buildViewsProps(),
|
|
|
|
'data-page-actions-more' => $this->buildActionsProps(),
|
|
|
|
'data-search-box' => $this->buildSearchProps(),
|
|
|
|
'data-sidebar' => [
|
2020-04-17 20:23:56 +00:00
|
|
|
'has-logo' => true,
|
|
|
|
'html-logo-attributes' => Xml::expandAttributes(
|
|
|
|
Linker::tooltipAndAccesskeyAttribs( 'p-logo' ) + [
|
|
|
|
'class' => 'mw-wiki-logo',
|
|
|
|
'href' => Skin::makeMainPageUrl(),
|
|
|
|
]
|
|
|
|
)
|
2020-03-25 20:57:46 +00:00
|
|
|
] + $this->buildSidebarProps( $this->get( 'sidebar', [] ) ),
|
2020-04-03 20:05:22 +00:00
|
|
|
] + $this->getMenuProps();
|
2019-02-26 18:44:10 +00:00
|
|
|
|
Add opt-out link to Sidebar for Vector/Logged-in Users Without Abstractions
This commit is singularly focused on adding a link to the sidebar for
Vector, logged-in users. It does the bare minimum to fulfill the
requirements of T243281.
Additionally, it will help to answer the question "Do we need to use
abstractions (other than maybe different templates) to separate Legacy
Vector from Vector" by intentionally leaving out any abstractions in
order to make it easier to compare with a follow-up patch
(Ib2ef15180df73360cc1de25b893e49d415d23e1a) which does use abstractions.
It is a good thing to question whether or not we need addtional
abstractions in VectorTemplate and if they will help us as unnecessary
abstractions can have the opposite effect and just lead to further
frustrations down the road.
Therefore, I urge you, the reviewer, to let me know your thoughts! If
abstractions are viewed as not making our lives any easier, the
follow-up patches may be completely discarded and that's totally okay
with me. :) I think it's a good think to talk about now though.
Important changes:
* The VectorTemplate constructor was changed to allow injecting the
config, templateParser, and isLegacy boolean (only the config was
allowed before this commit). According to MediaWiki's Stable Interface
Policy, "Constructor signatures are generally considered unstable unless
explicitly declared stable for calling" [3]. Given that VecorTemplate's
constructor is not marked as stable, it is justified to do this without
warning according to the policy.
* Due to the above, the 'setTemplate' method is no longer needed and was
marked as deprecated.
* VectorTemplateTest was made to adapt to the new VectorTemplate
constructor. Additionally, it now extends from
MediaWikiIntegrationTestCase which my intelliphense server can pick up.
I *think* MediaWikiTestCase is just an alias to
MediaWikiIntegrationTestCase [1] and MediaWikiTestCase file was renamed
to MediaWikiIntegrationTestCase in [2], but I'm willing to change it
back if there is pushback to this.
Open questions:
* What are VectorTemplate's responsibilities? To me, it acts right now
as a controller (because it echos the full HTML string from the
template), a model (because SkinTemplate::prepareQuickTemplate sets data
on it which it later retrieves through `$this->get()`), a presenter
(because it adds data tailored for a web-centric view), and a view
(because it renders HTML strings instead of letting the view/template be
solely responsible for that). Arguably, some business logic might be
mixed in there as well (because it checks to see if a User is logged
in/has necessary permissions to show x which my changes here add to).
This might not be a problem if we keep VectorTemplate relatively small,
but will it remain this way as we progress further in Desktop
Improvements?
* How do we write tests for VectorTemplate without exposing unnecessary
public methods? For example, if I want to test the `getSkinData()`
method to see what state will be sent to the template, how should I do
this? One option might be to use `TestingAccessWrapper` to expose these
private methods which is what
`VectorTemplateTest::testbuildViewsProps()` does. Another option is to
accept this method as public. Is there a better way? Keep in mind that
even with access to this method, there might be many things to mock.
[1] https://github.com/wikimedia/mediawiki/blob/0030cb525be6cabc1d63de80586b2017d4bbe354/tests/common/TestsAutoLoader.php#L64
[2] Ie717b0ecf4fcfd089d46248f14853c80b7ef4a76
[3] https://www.mediawiki.org/wiki/Stable_interface_policy
Bug: T243281
Change-Id: I0571b041bcd7f19bec9f103fa7bccdd093f6394d
2020-03-17 20:21:33 +00:00
|
|
|
// The following logic is unqiue to Vector (not used by legacy Vector) and
|
|
|
|
// is planned to be moved in a follow-up patch.
|
|
|
|
if ( !$this->isLegacy && $this->getSkin()->getUser()->isLoggedIn() ) {
|
2020-03-25 20:57:46 +00:00
|
|
|
$commonSkinData['data-sidebar']['data-emphasized-sidebar-action'] = [
|
Add opt-out link to Sidebar for Vector/Logged-in Users Without Abstractions
This commit is singularly focused on adding a link to the sidebar for
Vector, logged-in users. It does the bare minimum to fulfill the
requirements of T243281.
Additionally, it will help to answer the question "Do we need to use
abstractions (other than maybe different templates) to separate Legacy
Vector from Vector" by intentionally leaving out any abstractions in
order to make it easier to compare with a follow-up patch
(Ib2ef15180df73360cc1de25b893e49d415d23e1a) which does use abstractions.
It is a good thing to question whether or not we need addtional
abstractions in VectorTemplate and if they will help us as unnecessary
abstractions can have the opposite effect and just lead to further
frustrations down the road.
Therefore, I urge you, the reviewer, to let me know your thoughts! If
abstractions are viewed as not making our lives any easier, the
follow-up patches may be completely discarded and that's totally okay
with me. :) I think it's a good think to talk about now though.
Important changes:
* The VectorTemplate constructor was changed to allow injecting the
config, templateParser, and isLegacy boolean (only the config was
allowed before this commit). According to MediaWiki's Stable Interface
Policy, "Constructor signatures are generally considered unstable unless
explicitly declared stable for calling" [3]. Given that VecorTemplate's
constructor is not marked as stable, it is justified to do this without
warning according to the policy.
* Due to the above, the 'setTemplate' method is no longer needed and was
marked as deprecated.
* VectorTemplateTest was made to adapt to the new VectorTemplate
constructor. Additionally, it now extends from
MediaWikiIntegrationTestCase which my intelliphense server can pick up.
I *think* MediaWikiTestCase is just an alias to
MediaWikiIntegrationTestCase [1] and MediaWikiTestCase file was renamed
to MediaWikiIntegrationTestCase in [2], but I'm willing to change it
back if there is pushback to this.
Open questions:
* What are VectorTemplate's responsibilities? To me, it acts right now
as a controller (because it echos the full HTML string from the
template), a model (because SkinTemplate::prepareQuickTemplate sets data
on it which it later retrieves through `$this->get()`), a presenter
(because it adds data tailored for a web-centric view), and a view
(because it renders HTML strings instead of letting the view/template be
solely responsible for that). Arguably, some business logic might be
mixed in there as well (because it checks to see if a User is logged
in/has necessary permissions to show x which my changes here add to).
This might not be a problem if we keep VectorTemplate relatively small,
but will it remain this way as we progress further in Desktop
Improvements?
* How do we write tests for VectorTemplate without exposing unnecessary
public methods? For example, if I want to test the `getSkinData()`
method to see what state will be sent to the template, how should I do
this? One option might be to use `TestingAccessWrapper` to expose these
private methods which is what
`VectorTemplateTest::testbuildViewsProps()` does. Another option is to
accept this method as public. Is there a better way? Keep in mind that
even with access to this method, there might be many things to mock.
[1] https://github.com/wikimedia/mediawiki/blob/0030cb525be6cabc1d63de80586b2017d4bbe354/tests/common/TestsAutoLoader.php#L64
[2] Ie717b0ecf4fcfd089d46248f14853c80b7ef4a76
[3] https://www.mediawiki.org/wiki/Stable_interface_policy
Bug: T243281
Change-Id: I0571b041bcd7f19bec9f103fa7bccdd093f6394d
2020-03-17 20:21:33 +00:00
|
|
|
'href' => SpecialPage::getTitleFor(
|
|
|
|
'Preferences',
|
|
|
|
false,
|
2020-04-15 17:26:19 +00:00
|
|
|
'mw-prefsection-rendering-skin-skin-prefs'
|
Add opt-out link to Sidebar for Vector/Logged-in Users Without Abstractions
This commit is singularly focused on adding a link to the sidebar for
Vector, logged-in users. It does the bare minimum to fulfill the
requirements of T243281.
Additionally, it will help to answer the question "Do we need to use
abstractions (other than maybe different templates) to separate Legacy
Vector from Vector" by intentionally leaving out any abstractions in
order to make it easier to compare with a follow-up patch
(Ib2ef15180df73360cc1de25b893e49d415d23e1a) which does use abstractions.
It is a good thing to question whether or not we need addtional
abstractions in VectorTemplate and if they will help us as unnecessary
abstractions can have the opposite effect and just lead to further
frustrations down the road.
Therefore, I urge you, the reviewer, to let me know your thoughts! If
abstractions are viewed as not making our lives any easier, the
follow-up patches may be completely discarded and that's totally okay
with me. :) I think it's a good think to talk about now though.
Important changes:
* The VectorTemplate constructor was changed to allow injecting the
config, templateParser, and isLegacy boolean (only the config was
allowed before this commit). According to MediaWiki's Stable Interface
Policy, "Constructor signatures are generally considered unstable unless
explicitly declared stable for calling" [3]. Given that VecorTemplate's
constructor is not marked as stable, it is justified to do this without
warning according to the policy.
* Due to the above, the 'setTemplate' method is no longer needed and was
marked as deprecated.
* VectorTemplateTest was made to adapt to the new VectorTemplate
constructor. Additionally, it now extends from
MediaWikiIntegrationTestCase which my intelliphense server can pick up.
I *think* MediaWikiTestCase is just an alias to
MediaWikiIntegrationTestCase [1] and MediaWikiTestCase file was renamed
to MediaWikiIntegrationTestCase in [2], but I'm willing to change it
back if there is pushback to this.
Open questions:
* What are VectorTemplate's responsibilities? To me, it acts right now
as a controller (because it echos the full HTML string from the
template), a model (because SkinTemplate::prepareQuickTemplate sets data
on it which it later retrieves through `$this->get()`), a presenter
(because it adds data tailored for a web-centric view), and a view
(because it renders HTML strings instead of letting the view/template be
solely responsible for that). Arguably, some business logic might be
mixed in there as well (because it checks to see if a User is logged
in/has necessary permissions to show x which my changes here add to).
This might not be a problem if we keep VectorTemplate relatively small,
but will it remain this way as we progress further in Desktop
Improvements?
* How do we write tests for VectorTemplate without exposing unnecessary
public methods? For example, if I want to test the `getSkinData()`
method to see what state will be sent to the template, how should I do
this? One option might be to use `TestingAccessWrapper` to expose these
private methods which is what
`VectorTemplateTest::testbuildViewsProps()` does. Another option is to
accept this method as public. Is there a better way? Keep in mind that
even with access to this method, there might be many things to mock.
[1] https://github.com/wikimedia/mediawiki/blob/0030cb525be6cabc1d63de80586b2017d4bbe354/tests/common/TestsAutoLoader.php#L64
[2] Ie717b0ecf4fcfd089d46248f14853c80b7ef4a76
[3] https://www.mediawiki.org/wiki/Stable_interface_policy
Bug: T243281
Change-Id: I0571b041bcd7f19bec9f103fa7bccdd093f6394d
2020-03-17 20:21:33 +00:00
|
|
|
)->getLinkURL( 'wprov=' . self::OPT_OUT_LINK_TRACKING_CODE ),
|
|
|
|
'text' => $this->getMsg( 'vector-opt-out' )->text()
|
|
|
|
];
|
|
|
|
}
|
|
|
|
|
|
|
|
return $commonSkinData;
|
|
|
|
}
|
|
|
|
|
|
|
|
/**
|
|
|
|
* Renders the entire contents of the HTML page.
|
|
|
|
*/
|
|
|
|
public function execute() {
|
|
|
|
$tp = $this->getTemplateParser();
|
2020-03-31 17:51:48 +00:00
|
|
|
echo $tp->processTemplate( $this->templateRoot, $this->getSkinData() );
|
2014-08-07 11:38:34 +00:00
|
|
|
}
|
|
|
|
|
2020-01-16 22:11:53 +00:00
|
|
|
/**
|
|
|
|
* Get rows that make up the footer
|
|
|
|
* @return array for use in Mustache template describing the footer elements.
|
|
|
|
*/
|
2020-02-14 20:33:54 +00:00
|
|
|
private function getTemplateFooterRows() : array {
|
2020-01-16 22:11:53 +00:00
|
|
|
$footerRows = [];
|
|
|
|
foreach ( $this->getFooterLinks() as $category => $links ) {
|
|
|
|
$items = [];
|
|
|
|
$rowId = "footer-$category";
|
|
|
|
|
|
|
|
foreach ( $links as $link ) {
|
|
|
|
$items[] = [
|
|
|
|
'id' => "$rowId-$link",
|
|
|
|
'html' => $this->get( $link, '' ),
|
|
|
|
];
|
|
|
|
}
|
|
|
|
|
|
|
|
$footerRows[] = [
|
|
|
|
'id' => $rowId,
|
|
|
|
'className' => '',
|
|
|
|
'array-items' => $items
|
|
|
|
];
|
|
|
|
}
|
|
|
|
|
|
|
|
// If footer icons are enabled append to the end of the rows
|
|
|
|
$footerIcons = $this->getFooterIcons( 'icononly' );
|
|
|
|
if ( count( $footerIcons ) > 0 ) {
|
|
|
|
$items = [];
|
|
|
|
foreach ( $footerIcons as $blockName => $blockIcons ) {
|
|
|
|
$html = '';
|
|
|
|
foreach ( $blockIcons as $icon ) {
|
|
|
|
$html .= $this->getSkin()->makeFooterIcon( $icon );
|
|
|
|
}
|
|
|
|
$items[] = [
|
|
|
|
'id' => 'footer-' . htmlspecialchars( $blockName ) . 'ico',
|
|
|
|
'html' => $html,
|
|
|
|
];
|
|
|
|
}
|
|
|
|
|
|
|
|
$footerRows[] = [
|
|
|
|
'id' => 'footer-icons',
|
|
|
|
'className' => 'noprint',
|
|
|
|
'array-items' => $items,
|
|
|
|
];
|
|
|
|
}
|
|
|
|
|
|
|
|
return $footerRows;
|
|
|
|
}
|
|
|
|
|
2014-08-07 11:38:34 +00:00
|
|
|
/**
|
|
|
|
* Render a series of portals
|
|
|
|
*
|
|
|
|
* @param array $portals
|
2020-02-14 20:33:54 +00:00
|
|
|
* @return array
|
2014-08-07 11:38:34 +00:00
|
|
|
*/
|
2020-02-14 20:33:54 +00:00
|
|
|
private function buildSidebarProps( array $portals ) : array {
|
|
|
|
$props = [];
|
2014-08-07 11:38:34 +00:00
|
|
|
// Force the rendering of the following portals
|
|
|
|
if ( !isset( $portals['TOOLBOX'] ) ) {
|
|
|
|
$portals['TOOLBOX'] = true;
|
|
|
|
}
|
|
|
|
if ( !isset( $portals['LANGUAGES'] ) ) {
|
|
|
|
$portals['LANGUAGES'] = true;
|
|
|
|
}
|
|
|
|
// Render portals
|
|
|
|
foreach ( $portals as $name => $content ) {
|
|
|
|
if ( $content === false ) {
|
|
|
|
continue;
|
|
|
|
}
|
|
|
|
|
2015-01-10 20:38:46 +00:00
|
|
|
// Numeric strings gets an integer when set as key, cast back - T73639
|
|
|
|
$name = (string)$name;
|
|
|
|
|
2014-08-07 11:38:34 +00:00
|
|
|
switch ( $name ) {
|
|
|
|
case 'SEARCH':
|
|
|
|
break;
|
|
|
|
case 'TOOLBOX':
|
2020-02-14 20:33:54 +00:00
|
|
|
$portal = $this->buildPortalProps( 'tb', $this->getToolbox(), 'toolbox',
|
|
|
|
'SkinTemplateToolboxEnd' );
|
2020-01-14 18:47:30 +00:00
|
|
|
ob_start();
|
2020-01-24 11:50:21 +00:00
|
|
|
Hooks::run( 'VectorAfterToolbox', [], '1.35' );
|
2020-02-14 20:33:54 +00:00
|
|
|
$props[] = $portal + [
|
|
|
|
'html-hook-vector-after-toolbox' => ob_get_clean(),
|
|
|
|
];
|
2014-08-07 11:38:34 +00:00
|
|
|
break;
|
|
|
|
case 'LANGUAGES':
|
2020-02-28 20:53:44 +00:00
|
|
|
if ( $this->get( 'language_urls' ) !== false ) {
|
2020-02-14 20:33:54 +00:00
|
|
|
$props[] = $this->buildPortalProps(
|
2020-02-28 20:53:44 +00:00
|
|
|
'lang', $this->get( 'language_urls' ), 'otherlanguages'
|
2020-01-14 18:47:30 +00:00
|
|
|
);
|
2014-08-07 11:38:34 +00:00
|
|
|
}
|
|
|
|
break;
|
|
|
|
default:
|
2020-02-14 20:33:54 +00:00
|
|
|
$props[] = $this->buildPortalProps( $name, $content );
|
2014-08-07 11:38:34 +00:00
|
|
|
break;
|
|
|
|
}
|
|
|
|
}
|
2020-03-11 18:58:05 +00:00
|
|
|
|
2020-04-15 18:10:17 +00:00
|
|
|
$firstPortal = $props[0] ?? null;
|
|
|
|
if ( $firstPortal ) {
|
|
|
|
$firstPortal[ 'class' ] .= ' portal-first';
|
|
|
|
}
|
|
|
|
|
2020-02-14 20:33:54 +00:00
|
|
|
return [
|
2020-03-11 18:58:05 +00:00
|
|
|
'array-portals-rest' => array_slice( $props, 1 ),
|
2020-04-15 18:10:17 +00:00
|
|
|
'array-portals-first' => $firstPortal,
|
2020-02-14 20:33:54 +00:00
|
|
|
];
|
2014-08-07 11:38:34 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
/**
|
|
|
|
* @param string $name
|
2018-01-30 23:59:35 +00:00
|
|
|
* @param array|string $content
|
2014-08-07 11:38:34 +00:00
|
|
|
* @param null|string $msg
|
|
|
|
* @param null|string|array $hook
|
2020-02-14 20:33:54 +00:00
|
|
|
* @return array
|
2014-08-07 11:38:34 +00:00
|
|
|
*/
|
2020-02-14 20:33:54 +00:00
|
|
|
private function buildPortalProps( $name, $content, $msg = null, $hook = null ) : array {
|
2014-08-07 11:38:34 +00:00
|
|
|
if ( $msg === null ) {
|
|
|
|
$msg = $name;
|
|
|
|
}
|
2020-01-10 15:00:54 +00:00
|
|
|
|
2018-06-12 14:39:57 +00:00
|
|
|
$msgObj = $this->getMsg( $msg );
|
2014-08-07 11:38:34 +00:00
|
|
|
|
2020-01-10 15:00:54 +00:00
|
|
|
$props = [
|
|
|
|
'portal-id' => "p-$name",
|
2020-04-15 18:10:17 +00:00
|
|
|
'class' => 'portal',
|
2020-01-10 15:00:54 +00:00
|
|
|
'html-tooltip' => Linker::tooltip( 'p-' . $name ),
|
|
|
|
'msg-label' => $msgObj->exists() ? $msgObj->text() : $msg,
|
|
|
|
'msg-label-id' => "p-$name-label",
|
2020-02-28 20:53:44 +00:00
|
|
|
'html-userlangattributes' => $this->get( 'userlangattributes', '' ),
|
2020-01-10 15:00:54 +00:00
|
|
|
'html-portal-content' => '',
|
|
|
|
'html-after-portal' => $this->getAfterPortlet( $name ),
|
|
|
|
];
|
|
|
|
|
|
|
|
if ( is_array( $content ) ) {
|
|
|
|
$props['html-portal-content'] .= '<ul>';
|
|
|
|
foreach ( $content as $key => $val ) {
|
|
|
|
$props['html-portal-content'] .= $this->makeListItem( $key, $val );
|
|
|
|
}
|
|
|
|
if ( $hook !== null ) {
|
|
|
|
// Avoid PHP 7.1 warning
|
|
|
|
$skin = $this;
|
|
|
|
ob_start();
|
|
|
|
Hooks::run( $hook, [ &$skin, true ] );
|
2020-01-14 22:35:50 +00:00
|
|
|
$props['html-portal-content'] .= ob_get_contents();
|
2020-01-10 15:00:54 +00:00
|
|
|
ob_end_clean();
|
|
|
|
}
|
|
|
|
$props['html-portal-content'] .= '</ul>';
|
|
|
|
} else {
|
|
|
|
// Allow raw HTML block to be defined by extensions
|
|
|
|
$props['html-portal-content'] = $content;
|
|
|
|
}
|
|
|
|
|
2020-02-14 20:33:54 +00:00
|
|
|
return $props;
|
2014-08-07 11:38:34 +00:00
|
|
|
}
|
|
|
|
|
2017-07-26 17:15:27 +00:00
|
|
|
/**
|
2017-09-09 10:03:21 +00:00
|
|
|
* @inheritDoc
|
2017-07-26 17:15:27 +00:00
|
|
|
*/
|
|
|
|
public function makeListItem( $key, $item, $options = [] ) {
|
|
|
|
// For fancy styling of watch/unwatch star
|
|
|
|
if (
|
|
|
|
$this->config->get( 'VectorUseIconWatch' )
|
|
|
|
&& ( $key === 'watch' || $key === 'unwatch' )
|
|
|
|
) {
|
2019-12-22 18:38:53 +00:00
|
|
|
if ( !isset( $item['class'] ) ) {
|
|
|
|
$item['class'] = '';
|
|
|
|
}
|
2017-07-26 17:15:27 +00:00
|
|
|
$item['class'] = rtrim( 'icon ' . $item['class'], ' ' );
|
|
|
|
$item['primary'] = true;
|
|
|
|
}
|
|
|
|
|
|
|
|
// Add CSS class 'collapsible' to links which are not marked as "primary"
|
|
|
|
if (
|
2017-07-31 15:11:29 +00:00
|
|
|
isset( $options['vector-collapsible'] ) && $options['vector-collapsible'] ) {
|
2019-12-22 18:38:53 +00:00
|
|
|
if ( !isset( $item['class'] ) ) {
|
|
|
|
$item['class'] = '';
|
|
|
|
}
|
2017-07-26 17:15:27 +00:00
|
|
|
$item['class'] = rtrim( 'collapsible ' . $item['class'], ' ' );
|
|
|
|
}
|
|
|
|
|
|
|
|
return parent::makeListItem( $key, $item, $options );
|
|
|
|
}
|
2019-11-18 20:23:48 +00:00
|
|
|
|
2020-01-14 18:47:30 +00:00
|
|
|
/**
|
2020-02-14 20:33:54 +00:00
|
|
|
* @return array
|
2020-01-14 18:47:30 +00:00
|
|
|
*/
|
2020-02-14 20:33:54 +00:00
|
|
|
private function buildNamespacesProps() : array {
|
2019-12-03 13:02:11 +00:00
|
|
|
$props = [
|
2020-04-21 21:56:39 +00:00
|
|
|
'id' => 'p-namespaces',
|
|
|
|
'class' => ( count( $this->get( 'namespace_urls', [] ) ) == 0 ) ?
|
|
|
|
'emptyPortlet vectorTabs' : 'vectorTabs',
|
2019-12-03 13:02:11 +00:00
|
|
|
'label-id' => 'p-namespaces-label',
|
2020-04-21 21:56:39 +00:00
|
|
|
'label' => $this->getMsg( 'namespaces' )->text(),
|
2020-02-28 20:53:44 +00:00
|
|
|
'html-userlangattributes' => $this->get( 'userlangattributes', '' ),
|
2019-12-03 13:02:11 +00:00
|
|
|
'html-items' => '',
|
|
|
|
];
|
|
|
|
|
2020-02-28 20:53:44 +00:00
|
|
|
foreach ( $this->get( 'namespace_urls', [] ) as $key => $item ) {
|
2019-12-03 13:02:11 +00:00
|
|
|
$props[ 'html-items' ] .= $this->makeListItem( $key, $item );
|
2020-01-13 06:06:44 +00:00
|
|
|
}
|
2019-12-03 13:02:11 +00:00
|
|
|
|
2020-02-14 20:33:54 +00:00
|
|
|
return $props;
|
2019-11-18 20:23:48 +00:00
|
|
|
}
|
|
|
|
|
2020-01-14 18:47:30 +00:00
|
|
|
/**
|
2020-02-14 20:33:54 +00:00
|
|
|
* @return array
|
2020-01-14 18:47:30 +00:00
|
|
|
*/
|
2020-02-14 20:33:54 +00:00
|
|
|
private function buildVariantsProps() : array {
|
2020-01-08 13:47:25 +00:00
|
|
|
$props = [
|
2020-04-21 21:35:11 +00:00
|
|
|
'class' => ( count( $this->get( 'variant_urls', [] ) ) == 0 ) ?
|
|
|
|
'emptyPortlet vectorMenu' : 'vectorMenu',
|
|
|
|
'id' => 'p-variants',
|
|
|
|
'label-id' => 'p-variants-label',
|
|
|
|
'label' => $this->getMsg( 'variants' )->text(),
|
2020-01-08 13:47:25 +00:00
|
|
|
'html-items' => '',
|
|
|
|
];
|
|
|
|
|
|
|
|
// Replace the label with the name of currently chosen variant, if any
|
2020-02-28 20:53:44 +00:00
|
|
|
$variantUrls = $this->get( 'variant_urls', [] );
|
|
|
|
foreach ( $variantUrls as $item ) {
|
2020-01-08 13:47:25 +00:00
|
|
|
if ( isset( $item['class'] ) && stripos( $item['class'], 'selected' ) !== false ) {
|
|
|
|
$props['msg-label'] = $item['text'];
|
|
|
|
break;
|
2019-11-18 20:23:48 +00:00
|
|
|
}
|
2020-01-08 13:47:25 +00:00
|
|
|
}
|
|
|
|
|
2020-02-28 20:53:44 +00:00
|
|
|
foreach ( $variantUrls as $key => $item ) {
|
2020-01-08 13:47:25 +00:00
|
|
|
$props['html-items'] .= $this->makeListItem( $key, $item );
|
|
|
|
}
|
|
|
|
|
2020-02-14 20:33:54 +00:00
|
|
|
return $props;
|
2019-11-18 20:23:48 +00:00
|
|
|
}
|
|
|
|
|
2020-01-14 18:47:30 +00:00
|
|
|
/**
|
2020-02-14 20:33:54 +00:00
|
|
|
* @return array
|
2020-01-14 18:47:30 +00:00
|
|
|
*/
|
2020-02-14 20:33:54 +00:00
|
|
|
private function buildViewsProps() : array {
|
2019-12-03 13:02:11 +00:00
|
|
|
$props = [
|
2020-04-21 21:56:39 +00:00
|
|
|
'id' => 'p-views',
|
|
|
|
'class' => ( count( $this->get( 'view_urls', [] ) ) == 0 ) ?
|
|
|
|
'emptyPortlet vectorTabs' : 'vectorTabs',
|
2019-12-03 13:02:11 +00:00
|
|
|
'label-id' => 'p-views-label',
|
2020-04-21 21:56:39 +00:00
|
|
|
'label' => $this->getMsg( 'views' )->text(),
|
2020-02-28 20:53:44 +00:00
|
|
|
'html-userlangattributes' => $this->get( 'userlangattributes', '' ),
|
2019-12-03 13:02:11 +00:00
|
|
|
'html-items' => '',
|
|
|
|
];
|
2020-02-28 20:53:44 +00:00
|
|
|
$viewUrls = $this->get( 'view_urls', [] );
|
|
|
|
foreach ( $viewUrls as $key => $item ) {
|
2019-12-03 13:02:11 +00:00
|
|
|
$props[ 'html-items' ] .= $this->makeListItem( $key, $item, [
|
|
|
|
'vector-collapsible' => true,
|
|
|
|
] );
|
2020-01-13 06:06:44 +00:00
|
|
|
}
|
2019-12-03 13:02:11 +00:00
|
|
|
|
2020-02-14 20:33:54 +00:00
|
|
|
return $props;
|
2019-11-18 20:23:48 +00:00
|
|
|
}
|
|
|
|
|
2020-01-14 18:47:30 +00:00
|
|
|
/**
|
2020-02-14 20:33:54 +00:00
|
|
|
* @return array
|
2020-01-14 18:47:30 +00:00
|
|
|
*/
|
2020-02-14 20:33:54 +00:00
|
|
|
private function buildActionsProps() : array {
|
2020-01-08 13:47:25 +00:00
|
|
|
$props = [
|
2020-04-21 21:35:11 +00:00
|
|
|
'class' => ( count( $this->get( 'action_urls', [] ) ) == 0 ) ?
|
|
|
|
'emptyPortlet vectorMenu' : 'vectorMenu',
|
|
|
|
'label' => $this->getMsg( 'vector-more-actions' )->text(),
|
|
|
|
'id' => 'p-cactions',
|
|
|
|
'label-id' => 'p-cactions-label',
|
2020-02-28 20:53:44 +00:00
|
|
|
'html-userlangattributes' => $this->get( 'userlangattributes', '' ),
|
2020-01-08 13:47:25 +00:00
|
|
|
'html-items' => '',
|
|
|
|
];
|
|
|
|
|
2020-02-28 20:53:44 +00:00
|
|
|
$actionUrls = $this->get( 'action_urls', [] );
|
|
|
|
foreach ( $actionUrls as $key => $item ) {
|
2020-01-08 13:47:25 +00:00
|
|
|
$props['html-items'] .= $this->makeListItem( $key, $item );
|
2019-11-18 20:23:48 +00:00
|
|
|
}
|
2020-01-08 13:47:25 +00:00
|
|
|
|
2020-02-14 20:33:54 +00:00
|
|
|
return $props;
|
2019-11-18 20:23:48 +00:00
|
|
|
}
|
|
|
|
|
2020-01-14 18:47:30 +00:00
|
|
|
/**
|
2020-04-03 20:05:22 +00:00
|
|
|
* @param string $label to be used to derive the id and human readable label of the menu
|
|
|
|
* @param array $urls to convert to list items stored as string in html-items key
|
|
|
|
* @param int $type of menu (optional) - a plain list (MENU_TYPE_DEFAULT),
|
|
|
|
* a tab (MENU_TYPE_TABS) or a dropdown (MENU_TYPE_DROPDOWN)
|
|
|
|
* @param array $options (optional) to be passed to makeListItem
|
2020-02-14 20:33:54 +00:00
|
|
|
* @return array
|
2020-01-14 18:47:30 +00:00
|
|
|
*/
|
2020-04-03 20:05:22 +00:00
|
|
|
private function getMenuData(
|
|
|
|
string $label, array $urls = [],
|
|
|
|
int $type = self::MENU_TYPE_DEFAULT, array $options = []
|
|
|
|
) : array {
|
|
|
|
$class = ( count( $urls ) == 0 ) ? 'emptyPortlet' : '';
|
|
|
|
$extraClasses = [
|
|
|
|
self::MENU_TYPE_DROPDOWN => 'vectorMenu',
|
|
|
|
self::MENU_TYPE_TABS => 'vectorTabs',
|
|
|
|
self::MENU_TYPE_DEFAULT => '',
|
|
|
|
];
|
|
|
|
|
2020-01-09 10:59:09 +00:00
|
|
|
$props = [
|
2020-04-03 20:05:22 +00:00
|
|
|
'id' => "p-$label",
|
|
|
|
'label-id' => "p-{$label}-label",
|
|
|
|
'label' => $this->getMsg( $label )->text(),
|
2020-02-28 20:53:44 +00:00
|
|
|
'html-userlangattributes' => $this->get( 'userlangattributes', '' ),
|
2020-04-03 20:05:22 +00:00
|
|
|
'html-items' => '',
|
|
|
|
'class' => trim( "$class $extraClasses[$type]" ),
|
2020-01-09 10:59:09 +00:00
|
|
|
];
|
2019-11-18 20:23:48 +00:00
|
|
|
|
2020-04-03 20:05:22 +00:00
|
|
|
foreach ( $urls as $key => $item ) {
|
|
|
|
$props['html-items'] .= $this->makeListItem( $key, $item, $options );
|
|
|
|
}
|
|
|
|
return $props;
|
|
|
|
}
|
|
|
|
|
|
|
|
/**
|
|
|
|
* @return array
|
|
|
|
*/
|
|
|
|
private function getMenuProps() : array {
|
|
|
|
$personalTools = $this->getPersonalTools();
|
|
|
|
|
|
|
|
// For logged out users Vector shows a "Not logged in message"
|
|
|
|
// This should be upstreamed to core, with instructions for how to hide it for skins
|
|
|
|
// that do not want it.
|
|
|
|
// For now we create a dedicated list item to avoid having to sync the API internals
|
|
|
|
// of makeListItem.
|
2020-01-09 10:59:09 +00:00
|
|
|
if ( !$this->getSkin()->getUser()->isLoggedIn() && User::groupHasPermission( '*', 'edit' ) ) {
|
2020-04-03 20:05:22 +00:00
|
|
|
$loggedIn =
|
2020-01-09 10:59:09 +00:00
|
|
|
Html::element( 'li',
|
|
|
|
[ 'id' => 'pt-anonuserpage' ],
|
|
|
|
$this->getMsg( 'notloggedin' )->text()
|
|
|
|
);
|
2020-04-03 20:05:22 +00:00
|
|
|
} else {
|
|
|
|
$loggedIn = '';
|
2020-01-13 06:06:44 +00:00
|
|
|
}
|
2019-11-18 20:23:48 +00:00
|
|
|
|
2020-04-03 20:05:22 +00:00
|
|
|
// This code doesn't belong here, it belongs in the UniversalLanguageSelector
|
|
|
|
// It is here to workaround the fact that it wants to be the first item in the personal menus.
|
2020-01-09 10:59:09 +00:00
|
|
|
if ( array_key_exists( 'uls', $personalTools ) ) {
|
2020-04-03 20:05:22 +00:00
|
|
|
$uls = $this->makeListItem( 'uls', $personalTools[ 'uls' ] );
|
2020-01-09 10:59:09 +00:00
|
|
|
unset( $personalTools[ 'uls' ] );
|
2020-04-03 20:05:22 +00:00
|
|
|
} else {
|
|
|
|
$uls = '';
|
2020-01-09 10:59:09 +00:00
|
|
|
}
|
|
|
|
|
2020-04-03 20:05:22 +00:00
|
|
|
$ptools = $this->getMenuData( 'personal', $personalTools );
|
|
|
|
// Append additional link items if present.
|
|
|
|
$ptools['html-items'] = $uls . $loggedIn . $ptools['html-items'];
|
|
|
|
// Unlike other menu items, there is no language key corresponding with its menu key.
|
|
|
|
// Inconsistently this language key lives inside `personaltools`
|
|
|
|
// This line can be removed once the core message `personal` has been added.
|
|
|
|
$ptools['label'] = $this->getMsg( 'personaltools' )->text();
|
2020-01-09 10:59:09 +00:00
|
|
|
|
2020-04-03 20:05:22 +00:00
|
|
|
return [
|
|
|
|
'data-personal-menu' => $ptools,
|
|
|
|
];
|
2019-11-18 20:23:48 +00:00
|
|
|
}
|
|
|
|
|
2020-02-14 20:33:54 +00:00
|
|
|
/**
|
|
|
|
* @return array
|
|
|
|
*/
|
|
|
|
private function buildSearchProps() : array {
|
2019-11-20 19:43:07 +00:00
|
|
|
$props = [
|
2020-02-28 20:53:44 +00:00
|
|
|
'searchHeaderAttrsHTML' => $this->get( 'userlangattributes', '' ),
|
|
|
|
'searchActionURL' => $this->get( 'wgScript', '' ),
|
2019-11-20 19:43:07 +00:00
|
|
|
'searchDivID' => $this->config->get( 'VectorUseSimpleSearch' ) ? 'simpleSearch' : '',
|
|
|
|
'searchInputHTML' => $this->makeSearchInput( [ 'id' => 'searchInput' ] ),
|
2020-02-28 20:53:44 +00:00
|
|
|
'titleHTML' => Html::hidden( 'title', $this->get( 'searchtitle', null ) ),
|
2019-11-20 19:43:07 +00:00
|
|
|
'fallbackSearchButtonHTML' => $this->makeSearchButton(
|
|
|
|
'fulltext',
|
|
|
|
[ 'id' => 'mw-searchButton', 'class' => 'searchButton mw-fallbackSearchButton' ]
|
|
|
|
),
|
|
|
|
'searchButtonHTML' => $this->makeSearchButton(
|
|
|
|
'go',
|
|
|
|
[ 'id' => 'searchButton', 'class' => 'searchButton' ]
|
|
|
|
),
|
|
|
|
'searchInputLabel' => $this->getMsg( 'search' )
|
|
|
|
];
|
2020-02-14 20:33:54 +00:00
|
|
|
return $props;
|
2019-11-18 20:23:48 +00:00
|
|
|
}
|
2014-08-07 11:38:34 +00:00
|
|
|
}
|