jenkins-bot has submitted this change and it was merged.
Change subject: Beta: Add Special:History
......................................................................
Beta: Add Special:History
Provides Recent Changes and History functionality.
A basis to work off of.
Based loosely on the design in Story 184
Adding to beta as it is currently not linked to from
anywhere (this has been okayed by Kenan) - we cannot link
to it until it has paging
TODO: Design input needed on how to style deleted entries in history
(see FIXME notes in SpecialHistory)
Change-Id: I97f5aa3fb8b7a927defbababd9acc339c2611dbc
---
M MobileFrontend.i18n.php
M MobileFrontend.php
M includes/MobileFrontend.hooks.php
M includes/specials/MobileSpecialPage.php
A includes/specials/MobileSpecialPageFeed.php
A includes/specials/SpecialHistory.php
M includes/specials/SpecialMobileWatchlist.php
M includes/specials/SpecialUserProfile.php
M less/specials/watchlist.less
9 files changed, 297 insertions(+), 55 deletions(-)
Approvals:
Awjrichards: Looks good to me, approved
jenkins-bot: Verified
diff --git a/MobileFrontend.i18n.php b/MobileFrontend.i18n.php
index b8b2519..2f38963 100644
--- a/MobileFrontend.i18n.php
+++ b/MobileFrontend.i18n.php
@@ -81,6 +81,9 @@
'mobile-frontend-password-placeholder' => 'Password',
'mobile-frontend-login' => 'Sign in',
'mobile-frontend-history' => 'View edit history of this page.',
+ 'mobile-frontend-history-404-title' => 'Bad title given',
+ 'mobile-frontend-history-404-desc' => "Cannot look at history for a
page that doesn't exist. It may have been deleted or you may have followed a
bad link.",
+ 'mobile-frontend-history-summary' => 'Page history for [[$1]]',
'mobile-frontend-last-modified-date' => 'Last modified on $1, at $2',
'mobile-frontend-last-modified-seconds' => 'Last modified
{{PLURAL:$1|$1 second|$1 seconds}} ago',
'mobile-frontend-last-modified-minutes' => 'Last modified
{{PLURAL:$1|$1 minute|$1 minutes}} ago',
@@ -483,6 +486,9 @@
If not the Main Page, the following message is used:
* {{msg-mw|Mobile-frontend-last-modified-date}}',
+'mobile-frontend-history-404-title' => 'Title of the 404 error page shown when
navigate to [[Special:History/Title of page that does not exist]]',
+'mobile-frontend-history-404-desc' => 'Explain the reasons why the user may
have arrived on {{msg-mw|mobile-frontend-history-404-title}}',
+'mobile-frontend-history-summary' => 'Summary text that appears at the top of
the mobile history page for a given page',
'mobile-frontend-last-modified-date' => 'Text that displays the date
the page was last modified. Parameters:
* $1 - date
* $2 - time
diff --git a/MobileFrontend.php b/MobileFrontend.php
index eee421a..d4bac31 100644
--- a/MobileFrontend.php
+++ b/MobileFrontend.php
@@ -64,6 +64,7 @@
'SpecialUploads' => 'specials/SpecialUploads',
'SpecialUserProfile' => 'specials/SpecialUserProfile',
+ 'SpecialHistory' => 'specials/SpecialHistory',
'SpecialMobileUserlogin' => 'specials/SpecialMobileUserlogin',
'SpecialMobileDiff' => 'specials/SpecialMobileDiff',
'SpecialMobileOptions' => 'specials/SpecialMobileOptions',
@@ -72,6 +73,7 @@
'SpecialNearby' => 'specials/SpecialNearby',
'SpecialMobileNotifications' => 'specials/SpecialMobileNotifications',
'MobileSpecialPage' => 'specials/MobileSpecialPage',
+ 'MobileSpecialPageFeed' => 'specials/MobileSpecialPageFeed',
'MinervaTemplate' => 'skins/MinervaTemplate',
'MobileTemplate' => 'skins/MobileTemplate',
diff --git a/includes/MobileFrontend.hooks.php
b/includes/MobileFrontend.hooks.php
index 7dfb149..cf18ca5 100644
--- a/includes/MobileFrontend.hooks.php
+++ b/includes/MobileFrontend.hooks.php
@@ -286,6 +286,7 @@
}
$list['UserProfile'] = 'SpecialUserProfile';
+ $list['History'] = 'SpecialHistory';
}
return true;
}
diff --git a/includes/specials/MobileSpecialPage.php
b/includes/specials/MobileSpecialPage.php
index 25a4bae..5dfb3e0 100644
--- a/includes/specials/MobileSpecialPage.php
+++ b/includes/specials/MobileSpecialPage.php
@@ -1,6 +1,7 @@
<?php
class MobileSpecialPage extends SpecialPage {
+ protected $mode = 'stable';
/**
* @var bool: Whether this special page should appear on
Special:SpecialPages
*/
@@ -10,6 +11,24 @@
*/
protected $unstyledContent = true;
+ /* Executes the page when available in the current $mode */
+ public function executeWhenAvailable( $subPage ) {}
+
+ public function execute( $subPage ) {
+ $ctx = MobileContext::singleton();
+ if ( $this->mode !== 'stable' ) {
+ if ( $this->mode === 'beta' &&
!$ctx->isBetaGroupMember() ) {
+ $this->renderOptinBanner();
+ } else if ( $this->mode === 'alpha' &&
!$ctx->isAlphaGroupMember() ) {
+ $this->renderOptinBanner();
+ } else {
+ $this->executeWhenAvailable( $subPage );
+ }
+ } else {
+ $this->executeWhenAvailable( $subPage );
+ }
+ }
+
public function setHeaders() {
parent::setHeaders();
$this->addModules();
@@ -19,6 +38,15 @@
}
}
+ protected function renderOptinBanner() {
+ $out = $this->getOutput();
+ $out->setProperty( 'unstyledContent', true );
+ $out->addHTML( Html::openElement( 'div', array( 'class' =>
'alert warning' ) ) .
+ wfMessage( 'mobile-frontend-requires-optin' )->parse() .
+ Html::closeElement( 'div' )
+ );
+ }
+
protected function addModules() {
$out = $this->getOutput();
$rl = $out->getResourceLoader();
diff --git a/includes/specials/MobileSpecialPageFeed.php
b/includes/specials/MobileSpecialPageFeed.php
new file mode 100644
index 0000000..7eb6149
--- /dev/null
+++ b/includes/specials/MobileSpecialPageFeed.php
@@ -0,0 +1,76 @@
+<?php
+
+abstract class MobileSpecialPageFeed extends MobileSpecialPage {
+ public function execute( $par ) {
+ $out = $this->getOutput();
+ $out->addModuleStyles( 'mobile.watchlist.styles' );
+ $this->setHeaders();
+ $out->setProperty( 'unstyledContent', true );
+ parent::execute( $par );
+ }
+
+ /**
+ * Formats an edit comment
+ * @param string $comment: The raw comment text
+ * @param Title $title: The title of the page that was edited
+ * @fixme: Duplication with SpecialMobileWatchlist
+ *
+ * @return string: HTML code
+ */
+ protected function formatComment( $comment, $title ) {
+ if ( $comment === '' ) {
+ $comment = $this->msg(
'mobile-frontend-changeslist-nocomment' )->plain();
+ } else {
+ $comment = Linker::formatComment( $comment, $title );
+ // flatten back to text
+ $comment = Sanitizer::stripAllTags( $comment );
+ }
+ return $comment;
+ }
+
+ /**
+ * Renders an item in the feed
+ * @param {MWTimestamp} ts: The time the edit occurred
+ * @param {string} diffLink: url to the diff for the edit
+ * @param {string} username: The username of the user that made the
edit (absent if anonymous)
+ * @param {string} comment: The edit summary
+ * @param {Title} title: The title of the page that was edited
+ *
+ * @return String: HTML code
+ */
+ protected function renderFeedItemHtml( $ts, $diffLink ='', $username =
'', $comment = '', $title = false ) {
+ $out = $this->getOutput();
+ if ( $username === '' ) {
+ $username = $this->msg(
'mobile-frontend-changeslist-ip' )->plain();
+ $usernameClass = 'mw-mf-user mw-mf-anon';
+ } else {
+ $usernameClass = 'mw-mf-user';
+ }
+
+ $html = '<li>';
+ if ( $diffLink ) {
+ $html .= Html::openElement( 'a', array( 'href' =>
$diffLink, 'class' => 'title' ) );
+ } else {
+ $html .= Html::openElement( 'div', array( 'class' =>
'title' ) );
+ }
+ if ( $title ) {
+ $html .= Html::element( 'h2', array(),
$title->getPrefixedText() ) .
+ Html::element( 'div', array( 'class' =>
$usernameClass ), $username );
+ } else {
+ $html .= Html::openElement( 'h2' ) .
+ Html::element( 'span', array( 'class' =>
$usernameClass ), $username ) .
+ Html::closeElement( 'h2' );
+ }
+
+ $html .= Html::element( 'p', array( 'class' => 'mw-mf-comment'
), $comment ) .
+ Html::element( 'div', array( 'class' => 'info' ),
$ts->getHumanTimestamp() );
+
+ if ( $diffLink ) {
+ $html .= Html::closeElement( 'a' );
+ } else {
+ $html .= Html::closeElement( 'div' );
+ }
+ $html .= '</li>';
+ $out->addHtml( $html );
+ }
+}
diff --git a/includes/specials/SpecialHistory.php
b/includes/specials/SpecialHistory.php
new file mode 100644
index 0000000..b838f56
--- /dev/null
+++ b/includes/specials/SpecialHistory.php
@@ -0,0 +1,139 @@
+<?php
+
+class SpecialHistory extends MobileSpecialPageFeed {
+ const LIMIT = 50;
+ protected $mode = 'beta';
+
+ /** @var Title */
+ protected $title;
+
+ public function __construct() {
+ parent::__construct( 'History' );
+ }
+
+ public function executeWhenAvailable( $par = '' ) {
+ wfProfileIn( __METHOD__ );
+
+ $out = $this->getOutput();
+ $out->setPageTitle( $this->msg( 'history' ) );
+ if ( $par ) {
+ // enter article history view
+ $this->title = Title::newFromText( $par );
+ if ( $this->title && $this->title->exists() ) {
+ $out->addHtml(
+ Html::openElement( 'div', array(
'class' => 'page-header-bar' ) ) .
+ Html::openElement( 'div' ) .
+ $this->msg(
'mobile-frontend-history-summary', $this->title->getText() )->parse() .
+ Html::closeElement( 'div' ) .
+ Html::closeElement( 'div' )
+ );
+ } else {
+ wfHttpError( 404, $this->msg(
'mobile-frontend-history-404-title' )->text(),
+ $this->msg(
'mobile-frontend-history-404-desc' )->text() );
+ }
+ }
+ $res = $this->doQuery();
+ $this->showHistory( $res );
+
+ wfProfileOut( __METHOD__ );
+ }
+
+ protected function doQuery() {
+ wfProfileIn( __METHOD__ );
+ $table = 'revision';
+ if ( $this->title ) {
+ $conds = array(
+ 'rev_page' => $this->title->getArticleID(),
+ );
+ } else {
+ $conds = array();
+ }
+ $options = array(
+ 'ORDER BY' => 'rev_timestamp DESC',
+ 'USE INDEX' => 'page_timestamp',
+ );
+
+ $options['LIMIT'] = self::LIMIT + 1;
+
+ $tables = array( $table );
+ $dbr = wfGetDB( DB_SLAVE, $table );
+ $fields = array( '*' );
+
+ wfProfileIn( __METHOD__ . '-query' );
+ $res = $dbr->select( $tables, $fields, $conds, __METHOD__,
$options );
+ wfProfileOut( __METHOD__ . '-query' );
+
+ wfProfileOut( __METHOD__ );
+ return $res;
+ }
+
+ /**
+ * @param Revision $rev
+ * @param Revision|null $prev
+ */
+ protected function showRow( Revision $rev, $prev ) {
+ wfProfileIn( __METHOD__ );
+ $user = $this->getUser();
+ $userId = $rev->getUser( Revision::FOR_THIS_USER, $user );
+ $username = $userId === 0 ? '' : $rev->getUserText(
Revision::FOR_THIS_USER, $user );
+
+ // FIXME: Style differently user comment when this is the case
+ if ( $rev->userCan( Revision::DELETED_COMMENT, $user ) ) {
+ $comment = $rev->getComment( Revision::FOR_THIS_USER,
$user );
+ $comment = $this->formatComment( $comment, $this->title
);
+ } else {
+ $comment = $this->msg( 'rev-deleted-comment' )->plain();
+ }
+
+ $ts = new MWTimestamp( $rev->getTimestamp() );
+
+ $canSeeText = $rev->userCan( Revision::DELETED_TEXT, $user );
+ if ( $canSeeText && $prev && $prev->userCan(
Revision::DELETED_TEXT, $user ) ) {
+ $diffLink = SpecialPage::getTitleFor( 'MobileDiff',
$prev->getId() )->getLocalUrl();
+ } elseif ( $canSeeText ) {
+ $diffLink = $this->title->getLocalUrl( array( 'oldid'
=> $rev->getId() ) );
+ } else {
+ $diffLink = false;
+ }
+
+ // FIXME: Style differently user comment when this is the case
+ if ( !$rev->userCan( Revision::DELETED_USER, $user ) ) {
+ $username = $this->msg( 'rev-deleted-user' )->plain();
+ }
+
+ // When the page is named there is no need to print it in output
+ if ( $this->title ) {
+ $title = false;
+ } else {
+ $title = $rev->getTitle();
+ }
+ $this->renderFeedItemHtml( $ts, $diffLink, $username, $comment,
$title );
+
+ wfProfileOut( __METHOD__ );
+ }
+
+ protected function showHistory( ResultWrapper $res ) {
+ $rev1 = $rev2 = null;
+ $out = $this->getOutput();
+ $out->addHtml(
+ Html::openElement( 'ul',
+ array(
+ 'class' => 'page-list'
+ )
+ )
+ );
+
+ foreach ( $res as $row ) {
+ $rev1 = new Revision( $row );
+ if ( $rev2 ) {
+ $this->showRow( $rev2, $rev1 );
+ }
+ $rev2 = $rev1;
+ }
+ if ( $rev1 && $res->numRows() < self::LIMIT + 1 ) {
+ $this->showRow( $rev1, null );
+ }
+ $out->addHtml( '</ul>' );
+ // @todo: paging
+ }
+}
diff --git a/includes/specials/SpecialMobileWatchlist.php
b/includes/specials/SpecialMobileWatchlist.php
index 83dbcad..e6d5801 100644
--- a/includes/specials/SpecialMobileWatchlist.php
+++ b/includes/specials/SpecialMobileWatchlist.php
@@ -1,10 +1,14 @@
<?php
-class SpecialMobileWatchlist extends SpecialWatchlist {
+class SpecialMobileWatchlist extends MobileSpecialPageFeed {
const LIMIT = 50; // Performance-safe value with PageImages
const THUMB_SIZE = 150;
const VIEW_OPTION_NAME = 'mfWatchlistView';
const FILTER_OPTION_NAME = 'mfWatchlistFilter';
+
+ public function __construct() {
+ parent::__construct( 'Watchlist' );
+ }
private $filter,
$usePageImages,
@@ -13,30 +17,42 @@
/** @var Title */
private $fromPageTitle;
+ protected function renderAnonBanner() {
+ $out = $this->getOutput();
+ $out->setPageTitle( $this->msg( 'watchnologin' ) );
+ $out->setRobotPolicy( 'noindex,nofollow' );
+ $link = Linker::linkKnown(
+ SpecialPage::getTitleFor( 'Userlogin' ),
+ $this->msg( 'loginreqlink' )->escaped(),
+ array(),
+ array( 'returnto' =>
$this->getTitle()->getPrefixedText() )
+ );
+ $out->addHTML(
+ Html::openElement( 'div', array( 'class' => 'alert
warning' ) ) .
+ $this->msg( 'watchlistanontext' )->rawParams( $link
)->parse() .
+ Html::closeElement( 'div' )
+ );
+ }
function execute( $par ) {
wfProfileIn( __METHOD__ );
-
+ parent::execute( $par );
$ctx = MobileContext::singleton();
$this->usePageImages = !$ctx->imagesDisabled() && defined(
'PAGE_IMAGES_INSTALLED' );
$user = $this->getUser();
$output = $this->getOutput();
- $output->addModuleStyles( 'mobile.watchlist.styles' );
$output->addModules( 'mobile.watchlist.scripts' );
$req = $this->getRequest();
$view = $req->getVal( 'watchlistview', 'a-z' );
$this->fromPageTitle = Title::newFromText( $req->getVal(
'from', false ) );
- $this->setHeaders();
$output->setPageTitle( $this->msg( 'watchlist' ) );
if( $user->isAnon() ) {
// No watchlist for you.
- parent::execute( $par );
+ $this->renderAnonBanner();
wfProfileOut( __METHOD__ );
return;
- } else {
- $output->setProperty( 'unstyledContent', true );
}
if ( $view === 'feed' ) {
@@ -166,7 +182,7 @@
$output = $this->getOutput();
$output->addHtml(
- Html::openElement( 'ul', array( 'class' =>
'mw-mf-watchlist-selector' ) )
+ Html::openElement( 'ul', array( 'class' =>
'mw-mf-watchlist-selector page-header-bar' ) )
);
foreach( $filters as $filter => $msg ) {
@@ -194,7 +210,7 @@
);
}
- function doFeedQuery() {
+ protected function doFeedQuery() {
wfProfileIn( __METHOD__ );
$user = $this->getUser();
@@ -426,7 +442,7 @@
);
}
- private function showFeedResultRow( $row ) {
+ protected function showFeedResultRow( $row ) {
wfProfileIn( __METHOD__ );
if ( $row->rc_deleted ) {
@@ -437,10 +453,9 @@
$output = $this->getOutput();
$title = Title::makeTitle( $row->rc_namespace, $row->rc_title );
- $titleText = $title->getPrefixedText();
-
- $comment = $row->rc_comment;
+ $comment = $this->formatComment( $row->rc_comment , $title );
$ts = new MWTimestamp( $row->rc_timestamp );
+ $username = $row->rc_user != 0 && isset( $row->rc_user_text ) ?
htmlspecialchars( $row->rc_user_text ) : '';
$revId = $row->rc_this_oldid;
if ( $revId ) {
@@ -451,37 +466,12 @@
$diffLink = Title::makeTitle( $row->rc_namespace,
$row->rc_title )->getLocalUrl();
}
- if ( $row->rc_user == 0 ) {
- $username = $this->msg(
'mobile-frontend-changeslist-ip' )->plain();
- $usernameClass = 'mw-mf-user mw-mf-anon';
- } else {
- $username = htmlspecialchars( $row->rc_user_text );
- $usernameClass = 'mw-mf-user';
- }
-
- if ( $comment === '' ) {
- $comment = $this->msg(
'mobile-frontend-changeslist-nocomment' )->plain();
- } else {
- $comment = Linker::formatComment( $comment, $title );
- // flatten back to text
- $comment = Sanitizer::stripAllTags( $comment );
- }
-
- $output->addHtml(
- '<li>' .
- Html::openElement( 'a', array( 'href' => $diffLink,
'class' => 'title' ) ) .
- Html::element( 'h2', array(), $titleText ).
- Html::element( 'div', array( 'class' => $usernameClass
), $username ).
- Html::element( 'p', array( 'class' => 'mw-mf-comment'
), $comment ) .
- Html::element( 'div', array( 'class' => 'info' ),
$ts->getHumanTimestamp() ) .
- Html::closeElement( 'a' ) .
- '</li>'
- );
+ $this->renderFeedItemHtml( $ts, $diffLink, $username, $comment,
$title );
wfProfileOut( __METHOD__ );
}
- private function showListResultRow( $row ) {
+ protected function showListResultRow( $row ) {
wfProfileIn( __METHOD__ );
$output = $this->getOutput();
diff --git a/includes/specials/SpecialUserProfile.php
b/includes/specials/SpecialUserProfile.php
index 9c04ed4..77b9ae8 100644
--- a/includes/specials/SpecialUserProfile.php
+++ b/includes/specials/SpecialUserProfile.php
@@ -1,6 +1,8 @@
<?php
class SpecialUserProfile extends MobileSpecialPage {
+ protected $mode = 'beta';
+
/**
* @var User
*/
@@ -171,21 +173,12 @@
return $html;
}
- public function getHtmlBetaAlphaOptIn() {
- return Html::openElement( 'div', array( 'class' => 'alert
warning' ) ) .
- $this->msg( 'mobile-frontend-requires-optin' )->parse()
.
- Html::closeElement( 'div' );
- }
-
- public function execute( $par = '' ) {
+ public function executeWhenAvailable( $par ) {
wfProfileIn( __METHOD__ );
$out = $this->getOutput();
$this->addModules();
$out->setPageTitle( $this->msg( 'mobile-frontend-profile-title'
) );
- $ctx = MobileContext::singleton();
- if ( !$ctx->isBetaGroupMember() ) {
- $html = $this->getHtmlBetaAlphaOptIn();
- } else if ( $par ) {
+ if ( $par ) {
$this->targetUser = User::newFromName( $par );
// Make sure this is a valid registered user
if ( $this->targetUser->getId() ) {
diff --git a/less/specials/watchlist.less b/less/specials/watchlist.less
index 58e123e..5f49609 100644
--- a/less/specials/watchlist.less
+++ b/less/specials/watchlist.less
@@ -1,10 +1,19 @@
@import "../mixins.less";
-.mw-mf-watchlist-selector {
- li {
+.page-header-bar {
+
+ li,
+ div {
+ line-height: 1.5;
+ padding: 5px 0 0;
border-bottom: 1px solid #e2e2e2;
text-align: center;
+ }
+}
+
+.mw-mf-watchlist-selector {
+ li {
display: inline-block;
border-left: 1px solid #e2e2e2;
width: 25%;
@@ -18,10 +27,8 @@
}
a {
- line-height: 1.5;
display: block;
color: #58595b;
- padding: 5px 0 0;
margin: 0 1px 0 0;
border-bottom: 3px solid transparent;
}
--
To view, visit https://gerrit.wikimedia.org/r/89283
To unsubscribe, visit https://gerrit.wikimedia.org/r/settings
Gerrit-MessageType: merged
Gerrit-Change-Id: I97f5aa3fb8b7a927defbababd9acc339c2611dbc
Gerrit-PatchSet: 15
Gerrit-Project: mediawiki/extensions/MobileFrontend
Gerrit-Branch: master
Gerrit-Owner: Jdlrobson <[email protected]>
Gerrit-Reviewer: Awjrichards <[email protected]>
Gerrit-Reviewer: Brion VIBBER <[email protected]>
Gerrit-Reviewer: JGonera <[email protected]>
Gerrit-Reviewer: Jdlrobson <[email protected]>
Gerrit-Reviewer: MaxSem <[email protected]>
Gerrit-Reviewer: jenkins-bot
_______________________________________________
MediaWiki-commits mailing list
[email protected]
https://lists.wikimedia.org/mailman/listinfo/mediawiki-commits