r99522 MediaWiki - Code Review archive

Repository:MediaWiki
Revision:r99521‎ | r99522 | r99523 >
Date:18:30, 11 October 2011
Author:jpostlethwaite
Status:fixme (Comments)
Tags:nodeploy, todo 
Comment:
Adding new extension LastModified.
Modified paths:
  • /trunk/extensions/LastModified (added) (history)
  • /trunk/extensions/LastModified/LastModified.alias.php (added) (history)
  • /trunk/extensions/LastModified/LastModified.i18n.php (added) (history)
  • /trunk/extensions/LastModified/LastModified.php (added) (history)
  • /trunk/extensions/LastModified/modules (added) (history)
  • /trunk/extensions/LastModified/modules/lastmodified.js (added) (history)

Diff [purge]

Index: trunk/extensions/LastModified/LastModified.alias.php
@@ -0,0 +1,37 @@
 2+<?php
 3+/**
 4+ * Wikimedia Foundation
 5+ *
 6+ * LICENSE
 7+ *
 8+ * This program is free software; you can redistribute it and/or modify
 9+ * it under the terms of the GNU General Public License as published by
 10+ * the Free Software Foundation; either version 2 of the License, or
 11+ * (at your option) any later version.
 12+ *
 13+ * This program is distributed in the hope that it will be useful,
 14+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
 15+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
 16+ * GNU General Public License for more details.
 17+ *
 18+ * @author Katie Horn <khorn@wikimedia.org>, Jeremy Postlethwaite <jpostlethwaite@wikimedia.org>
 19+ */
 20+
 21+/**
 22+ * Aliases for Special:LastModified
 23+ *
 24+ * @file
 25+ * @ingroup Extensions
 26+ */
 27+
 28+$specialPageAliases = array();
 29+
 30+/** English (English) */
 31+$specialPageAliases['en'] = array(
 32+ 'LastModified' => array( 'LastModified' ),
 33+);
 34+
 35+/**
 36+ * For backwards compatibility with MediaWiki 1.15 and earlier.
 37+ */
 38+$aliases =& $specialPageAliases;
Property changes on: trunk/extensions/LastModified/LastModified.alias.php
___________________________________________________________________
Added: svn:mime-type
139 + text/plain
Added: svn:keywords
240 + Author Date HeadURL Header Id Revision
Added: svn:eol-style
341 + native
Index: trunk/extensions/LastModified/LastModified.i18n.php
@@ -0,0 +1,38 @@
 2+<?php
 3+/**
 4+ * Wikimedia Foundation
 5+ *
 6+ * LICENSE
 7+ *
 8+ * This program is free software; you can redistribute it and/or modify
 9+ * it under the terms of the GNU General Public License as published by
 10+ * the Free Software Foundation; either version 2 of the License, or
 11+ * (at your option) any later version.
 12+ *
 13+ * This program is distributed in the hope that it will be useful,
 14+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
 15+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
 16+ * GNU General Public License for more details.
 17+ *
 18+ * @author Katie Horn <khorn@wikimedia.org>, Jeremy Postlethwaite <jpostlethwaite@wikimedia.org>
 19+ */
 20+
 21+/**
 22+ * Internationalisation for LastModified extension
 23+ */
 24+
 25+$messages = array();
 26+
 27+/** English
 28+ * @author Katie Horn, Jeremy Postlethwaite
 29+ */
 30+$messages['en'] = array(
 31+ 'lastmodified-desc' => 'Generates last modified times for articles',
 32+ 'lastmodified' => 'LastModified',
 33+ 'lastmodified-seconds' => 'Last updated $1 seconds ago',
 34+ 'lastmodified-minutes' => 'Last updated $1 minutes ago',
 35+ 'lastmodified-hours' => 'Last updated $1 hours ago',
 36+ 'lastmodified-days' => 'Last updated $1 days ago',
 37+ 'lastmodified-months' => 'Last updated $1 months ago',
 38+ 'lastmodified-years' => 'Last updated $1 years ago',
 39+);
Property changes on: trunk/extensions/LastModified/LastModified.i18n.php
___________________________________________________________________
Added: svn:mime-type
140 + text/plain
Added: svn:keywords
241 + Author Date HeadURL Header Id Revision
Added: svn:eol-style
342 + native
Index: trunk/extensions/LastModified/modules/lastmodified.js
@@ -0,0 +1,216 @@
 2+/**
 3+ * Wikimedia Foundation
 4+ *
 5+ * LICENSE
 6+ *
 7+ * This program is free software; you can redistribute it and/or modify
 8+ * it under the terms of the GNU General Public License as published by
 9+ * the Free Software Foundation; either version 2 of the License, or
 10+ * (at your option) any later version.
 11+ *
 12+ * This program is distributed in the hope that it will be useful,
 13+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
 14+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
 15+ * GNU General Public License for more details.
 16+ *
 17+ * @author Katie Horn <khorn@wikimedia.org>, Jeremy Postlethwaite <jpostlethwaite@wikimedia.org>
 18+ */
 19+
 20+/**
 21+ * Run the last modified helper.
 22+ *
 23+ * This is the primary function for this script.
 24+ *
 25+ */
 26+function extensionsLastModified() {
 27+
 28+ // Get the last-edit value
 29+ var lastEdited = extensionsLastModifiedGetMetaLastEdited();
 30+ //console.log( 'lastEdited: ' + lastEdited );
 31+
 32+ // Get the last-modified-range value
 33+ var displayRange = extensionsLastModifiedGetMetaRange();
 34+ //console.log( 'displayRange: ' + displayRange );
 35+
 36+ // Get the current Date object
 37+ var now = new Date();
 38+ //console.log( 'now: ' + now );
 39+
 40+ // Get the current timestamp and remove the milliseconds
 41+ var nowStamp = parseInt( now.getTime() / 1000 ) ;
 42+ //console.log( 'nowStamp: ' + nowStamp );
 43+
 44+ // Get the difference in the time from when it was last edited.
 45+ var modifiedDifference = nowStamp - lastEdited;
 46+ //console.log( 'modifiedDifference: ' + modifiedDifference );
 47+
 48+ // Get the last modified text
 49+ var lastModifiedText = extensionsLastModifiedGetLastModifiedText( modifiedDifference, displayRange );
 50+ //console.log( 'lastModifiedText: ' + lastModifiedText );
 51+
 52+ // Insert the text on the web page
 53+ extensionsLastModifiedInsertHtml( lastModifiedText );
 54+}
 55+
 56+/**
 57+ * Get the article history link
 58+ *
 59+ * @return string Return the article title
 60+ */
 61+function extensionsLastModifiedGetArticleHistoryLink() {
 62+
 63+ var href = $(location).attr('href');
 64+
 65+ var query = '';
 66+
 67+ if (href.indexOf('?') == -1) {
 68+ query += '?';
 69+ }
 70+ else {
 71+ query += '&amp;';
 72+ }
 73+
 74+ query += 'action=history';
 75+
 76+ //console.log( 'href: ' + href );
 77+
 78+ return href + query;
 79+}
 80+
 81+/**
 82+ * Get the value from the meta tag: last-edited
 83+ *
 84+ * @return integer
 85+ */
 86+function extensionsLastModifiedGetMetaLastEdited() {
 87+
 88+ // Fetch the meta tag
 89+ var metaTag = $("meta[name=last-edited]");
 90+
 91+ // If the tag was found, parse the value
 92+ if ( metaTag ) {
 93+
 94+ return parseInt( metaTag.attr( 'content' ) );
 95+ }
 96+
 97+ return 0;
 98+}
 99+
 100+/**
 101+ * Get the modified text. This takes advantage of internationalization.
 102+ *
 103+ * @param integer modifiedDifference The difference of time from now compared to last edited
 104+ * @param integer displayRange The maximum unit of time to display for last updated
 105+ *
 106+ * displayRange
 107+ * - 0: default - display: years, months, days, hours, minutes, seconds
 108+ * - 1: months - display: months, days, hours, minutes, seconds
 109+ * - 2: days - display: days, hours, minutes, seconds
 110+ * - 3: hours - display: hours, minutes, seconds
 111+ * - 4: minutes - display: minutes, seconds
 112+ * - 5: seconds - display: seconds
 113+ *
 114+ * @return string
 115+ */
 116+function extensionsLastModifiedGetLastModifiedText( modifiedDifference, displayRange ) {
 117+
 118+ // Message to return
 119+ var message = '';
 120+ var lastEdit = modifiedDifference;
 121+
 122+ if ( modifiedDifference < 60 ) {
 123+
 124+ // seconds
 125+ message = ( mw.msg( 'lastmodified-seconds', lastEdit ) );
 126+
 127+ }
 128+ else if ( modifiedDifference < 3600 ) {
 129+
 130+ // minutes
 131+ lastEdit = parseInt( modifiedDifference / 60 );
 132+ message = ( mw.msg( 'lastmodified-minutes', myLastEdit ) );
 133+
 134+ }
 135+ else if ( modifiedDifference < 86400 ) {
 136+
 137+ // hours
 138+ myLastEdit = parseInt( modifiedDifference / 3600 );
 139+ message = ( mw.msg( 'lastmodified-hours', myLastEdit ) );
 140+
 141+ }
 142+ else if ( modifiedDifference < 2592000 ) {
 143+
 144+ // days
 145+ myLastEdit = parseInt( modifiedDifference / 86400 );
 146+ message = ( mw.msg( 'lastmodified-days', myLastEdit ) );
 147+
 148+ }
 149+ else if ( modifiedDifference < 31536000 ) {
 150+
 151+ // months
 152+ myLastEdit = parseInt( modifiedDifference / 2592000 );
 153+ message = ( mw.msg( 'lastmodified-months', myLastEdit ) );
 154+
 155+ }
 156+ else {
 157+
 158+ // years
 159+ myLastEdit = parseInt( modifiedDifference / 31536000 );
 160+ message = ( mw.msg( 'lastmodified-years', myLastEdit ) );
 161+
 162+ }
 163+
 164+ return message;
 165+}
 166+
 167+/**
 168+ * Get the value from the meta tag: last-modified-range
 169+ *
 170+ * @return integer
 171+ */
 172+function extensionsLastModifiedGetMetaRange() {
 173+
 174+ // Fetch the meta tag
 175+ var metaTag = $("meta[name=last-modified-range]");
 176+
 177+ // If the tag was found, parse the value
 178+ if ( metaTag ) {
 179+
 180+ return parseInt( metaTag.attr( 'content' ) );
 181+ }
 182+
 183+ return 0;
 184+}
 185+
 186+/**
 187+ * Insert the last modified text with jQuery
 188+ *
 189+ * @param string lastModifiedText The string of text to display in the container.
 190+ */
 191+function extensionsLastModifiedInsertHtml( lastModifiedText ) {
 192+
 193+ //http://en.wikipedia.org/w/index.php?title=San_Francisco&action=history
 194+
 195+ // Get the article history link
 196+ var historyLink = extensionsLastModifiedGetArticleHistoryLink();
 197+ //console.log( 'historyLink: ' + historyLink );
 198+
 199+ var html = '';
 200+
 201+ html += '<div style="float: right;" class="lastmodified">';
 202+ html += '<a href="' + historyLink + '" title="View the revision history for this article.">';
 203+ html += lastModifiedText;
 204+ html += '</a>';
 205+ html += '</div>';
 206+
 207+ $('.mw-content-ltr').prepend( html );
 208+}
 209+
 210+/**
 211+ * Display the last modified link on the page.
 212+ *
 213+ */
 214+$(document).ready(function(){
 215+ extensionsLastModified();
 216+});
 217+
Property changes on: trunk/extensions/LastModified/modules/lastmodified.js
___________________________________________________________________
Added: svn:mime-type
1218 + text/plain
Added: svn:keywords
2219 + Author Date HeadURL Header Id Revision
Added: svn:eol-style
3220 + native
Index: trunk/extensions/LastModified/LastModified.php
@@ -0,0 +1,84 @@
 2+<?php
 3+/**
 4+ * Wikimedia Foundation
 5+ *
 6+ * LICENSE
 7+ *
 8+ * This program is free software; you can redistribute it and/or modify
 9+ * it under the terms of the GNU General Public License as published by
 10+ * the Free Software Foundation; either version 2 of the License, or
 11+ * (at your option) any later version.
 12+ *
 13+ * This program is distributed in the hope that it will be useful,
 14+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
 15+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
 16+ * GNU General Public License for more details.
 17+ *
 18+ * @author Katie Horn <khorn@wikimedia.org>, Jeremy Postlethwaite <jpostlethwaite@wikimedia.org>
 19+ */
 20+
 21+# Alert the user that this is not a valid entry point to MediaWiki if they try to access the special pages file directly.
 22+if ( !defined( 'MEDIAWIKI' ) ) {
 23+ echo <<<EOT
 24+To install this extension, put the following line in LocalSettings.php:
 25+require_once( "\$IP/extensions/LastModified/LastModified.php" );
 26+EOT;
 27+ exit( 1 );
 28+}
 29+
 30+// Extension credits that will show up on Special:Version
 31+$wgExtensionCredits['specialpage'][] = array(
 32+ 'path' => __FILE__,
 33+ 'name' => 'LastModified',
 34+ 'version' => '1.0',
 35+ 'url' => 'http://www.mediawiki.org/wiki/Extension:LastModified',
 36+ 'author' => 'Katie Horn, Jeremy Postlethwaite',
 37+ 'descriptionmsg' => 'lastmodified-desc',
 38+);
 39+
 40+$dir = dirname( __FILE__ ) . '/';
 41+
 42+$wgExtensionMessagesFiles['LastModified'] = $dir . 'LastModified.i18n.php';
 43+$wgExtensionAliasesFiles['LastModified'] = $dir . 'LastModified.alias.php';
 44+
 45+/**
 46+ * ADDITIONAL MAGICAL GLOBALS
 47+ */
 48+
 49+// Resource modules
 50+$wgResourceTemplate = array(
 51+ 'localBasePath' => $dir . 'modules',
 52+ 'remoteExtPath' => 'LastModified/modules',
 53+);
 54+
 55+$wgResourceModules['last.modified'] = array(
 56+ 'scripts' => 'lastmodified.js',
 57+ 'position' => 'top',
 58+ 'messages' => array(
 59+ 'lastmodified-seconds',
 60+ 'lastmodified-hours',
 61+ 'lastmodified-minutes',
 62+ 'lastmodified-hours',
 63+ 'lastmodified-days',
 64+ 'lastmodified-months',
 65+ 'lastmodified-years',
 66+ ),
 67+) + $wgResourceTemplate;
 68+
 69+$wgHooks['BeforePageDisplay'][] = 'fnLastModified';
 70+
 71+$wgLastModifiedRange = isset( $wgLastModifiedRange ) ? (integer) $wgLastModifiedRange : 0;
 72+
 73+function fnLastModified() {
 74+ global $wgOut, $wgResourceModules, $wgArticle, $wgLastModifiedRange;
 75+
 76+ if (isset( $wgArticle ) && !empty( $wgArticle ) ){
 77+ $timestamp = $wgArticle->getTimestamp();
 78+ $wgOut->addMeta( 'last-edited', wfTimestamp ( TS_UNIX, $timestamp ) );
 79+ $wgOut->addMeta( 'last-modified-range', $wgLastModifiedRange );
 80+ $wgOut->addModules( 'last.modified' );
 81+ }
 82+
 83+ return true;
 84+}
 85+
Property changes on: trunk/extensions/LastModified/LastModified.php
___________________________________________________________________
Added: svn:mime-type
186 + text/plain
Added: svn:keywords
287 + Author Date HeadURL Header Id Revision
Added: svn:eol-style
388 + native

Follow-up revisions

RevisionCommit summaryAuthorDate
r99527Followup r99522, fix author to use array so that it will locali[sz]e list bui...reedy18:35, 11 October 2011
r99533Don't abuse globalsreedy18:50, 11 October 2011
r99553Fixed a bad variable name. Removed UTC code.jpostlethwaite20:03, 11 October 2011
r99582Added skeleton special page for LastModified.jpostlethwaite22:04, 11 October 2011
r99616Added title tag for history link. Changed to prepend link on #content. Limite...jpostlethwaite01:58, 12 October 2011
r99725Added i18n message. Renamed javascript variables to be more intuitive. Checki...jpostlethwaite19:55, 13 October 2011
r99734Added message documentation for extension LastModified.jpostlethwaite20:49, 13 October 2011
r99776Variable does not need to check for global value. It will be updated in Local...jpostlethwaite15:54, 14 October 2011
r111475Updating english messages to use PLURAL for LastModified extension. See r99522.jpostlethwaite19:57, 14 February 2012

Comments

#Comment by Jpostlethwaite (talk | contribs)   18:33, 11 October 2011

This extension was created during Tech Days at San Francisco.

A wiki page for this extension will created shortly.

#Comment by Reedy (talk | contribs)   18:34, 11 October 2011

Nooooo $wgArticle!

#Comment by Jpostlethwaite (talk | contribs)   18:34, 11 October 2011

Will add a special page for this extension.

#Comment by Siebrand (talk | contribs)   18:36, 11 October 2011

Please add message documentation for the newly added messages. Thanks.

Plurals are missing for many messages.

#Comment by Jpostlethwaite (talk | contribs)   18:39, 11 October 2011

We added plurals to the messages but we removed them.

There is an extension that will be added soon so we can use the syntax:

Template:PLURAL $1

within the messages.

#Comment by Jpostlethwaite (talk | contribs)   18:40, 11 October 2011

That did not come out right :) not a template

#Comment by Siebrand (talk | contribs)   18:48, 11 October 2011

I'm sorry, you lost me there for a second. You're stating that proper i18n is not needed here?

#Comment by Jpostlethwaite (talk | contribs)   19:02, 11 October 2011

No, we talked with someone yesterday about implementing the PLURAL macro:

PLURAL $1 | one second | $1 seconds

#Comment by Jpostlethwaite (talk | contribs)   19:07, 11 October 2011

It says that mediawiki supports plurals, but it does not:

http://www.mediawiki.org/wiki/I18n#.E2.80.A6on_numbers_via_PLURAL

#Comment by Nikerabbit (talk | contribs)   19:55, 11 October 2011

Javascript doesn't support plurals yet.

#Comment by Siebrand (talk | contribs)   22:31, 11 October 2011

Not sure if this will be used on all or many pages, but if so, I think implementing plural in the standard JS message handling should have it's priority upped.

#Comment by Aaron Schulz (talk | contribs)   00:45, 12 October 2011

Likewise for GENDER, which came up in FlaggedRevs.

#Comment by Nikerabbit (talk | contribs)   05:32, 14 October 2011

You can't read a configuration variable before it is set. That is a potential register_globals vulnerability.

+$wgLastModifiedRange = isset( $wgLastModifiedRange ) ? (integer) $wgLastModifiedRange : 0;
#Comment by Jpostlethwaite (talk | contribs)   15:13, 14 October 2011

Do we require register_globals to be off?

How do you recommend this should be set?

This value needs to be set in LocalSettings.php. If it is not there, I need to initialize it.

The variable is always cast as an integer so it is properly sanitized.

#Comment by Nikerabbit (talk | contribs)   15:23, 14 October 2011

You set the value unconditionally, and then it can be overwritten in LocalSettings.php

#Comment by Jpostlethwaite (talk | contribs)   15:57, 14 October 2011

Thanks, that was a mistake.

I added documentation to the global variable as well.

#Comment by Siebrand (talk | contribs)   17:05, 23 December 2011

This needs plural support. Plural for JavaScript is now present in both 1.18-wmf1 as well as trunk. NielK merged this recently. Unknown where to find documentation on this yet.

#Comment by Jpostlethwaite (talk | contribs)   20:03, 14 February 2012

I tested this out and it did not seem to work properly. See r111475.

Status & tagging log