r58370 MediaWiki - Code Review archive

Repository:MediaWiki
Revision:r58369‎ | r58370 | r58371 >
Date:19:05, 30 October 2009
Author:ariel
Status:resolved (Comments)
Tags:
Comment:
Initial checkin of ExternalPages extension for 2009 fundraiser
Modified paths:
  • /trunk/extensions/ExternalPages (added) (history)
  • /trunk/extensions/ExternalPages/ExternalPages.alias.php (added) (history)
  • /trunk/extensions/ExternalPages/ExternalPages.i18n.php (added) (history)
  • /trunk/extensions/ExternalPages/ExternalPages_body.php (added) (history)
  • /trunk/extensions/ExternalPages/SpecialExternalPages.php (added) (history)

Diff [purge]

Index: trunk/extensions/ExternalPages/ExternalPages.alias.php
@@ -0,0 +1,22 @@
 2+<?php
 3+ /**
 4+ * Aliases for Special:ExternalPages
 5+ *
 6+ * @addtogroup Extensions
 7+ */
 8+
 9+$aliases = array();
 10+
 11+/** English
 12+ * @author ArielGlenn
 13+ */
 14+$aliases['en'] = array(
 15+ 'ExternalPages' => array( 'ExternalPages' ),
 16+);
 17+
 18+/** Greek */
 19+$aliases['el'] = array(
 20+ 'ExternalPages' => array( 'ΕξωτερικέςΣελίδες' ),
 21+);
 22+
 23+?>
Property changes on: trunk/extensions/ExternalPages/ExternalPages.alias.php
___________________________________________________________________
Added: svn:eol-style
124 + native
Index: trunk/extensions/ExternalPages/ExternalPages_body.php
@@ -0,0 +1,154 @@
 2+<?php
 3+
 4+if ( !defined( 'MEDIAWIKI' ) ) {
 5+ echo "ExternalPages extension\n";
 6+ exit( 1 );
 7+}
 8+
 9+$base = dirname( __FILE__ );
 10+
 11+/**
 12+ * Special page allows retrieval and display of pages from remote WMF sites
 13+ * with year, lang and project specifable
 14+ */
 15+class ExternalPages extends SpecialPage {
 16+
 17+ private $mYear = '';
 18+ private $mLang = '';
 19+ private $mProject = '';
 20+ private $mPage = false;
 21+
 22+ function __construct() {
 23+ SpecialPage::SpecialPage( 'ExternalPages' );
 24+ wfLoadExtensionMessages( 'ExternalPages' );
 25+ }
 26+
 27+ /*
 28+ * entry point (retrieve parsed page, convert rel links to full
 29+ * urls that direct to the remote site
 30+ * $par would be the subpage. we don't need it
 31+ */
 32+ function execute( $par ) {
 33+ global $wgUser, $wgRequest;
 34+
 35+ wfLoadExtensionMessages( 'ExternalPages' );
 36+ $this->setHeaders();
 37+ if ( ! $this->parseParams() ) {
 38+ return(false);
 39+ }
 40+ if ( ! $this->userCanExecute( $wgUser ) ) {
 41+ $this->displayRestrictionError();
 42+ return(false);
 43+ }
 44+
 45+ $this->retrieveExternalPage( $this->constructURL() );
 46+
 47+ }
 48+
 49+ /*
 50+ * process parameters of the request
 51+ */
 52+ private function parseParams() {
 53+ global $wgRequest, $wgServer;
 54+
 55+ if (!$wgRequest->getVal( 'EPyear') ) {
 56+ $this->mYear=false;
 57+ }
 58+ else {
 59+ $this->mYear = $wgRequest->getInt( 'EPyear' );
 60+ // if this code is still being used 50 years from now, replace it :-P
 61+ if (! (( $this->mYear > 2000 ) && ( $this->mYear < 2050 ))) {
 62+ ExternalPagesErrors::showError( 'externalpages-bad-year' );
 63+ return(false);
 64+ }
 65+ }
 66+
 67+ if ( !$wgRequest->getVal( 'EPlanguage' ) ) {
 68+ $this->mLang=false;
 69+ }
 70+ else {
 71+ $this->mLang = $wgRequest->getVal( 'EPlanguage' );
 72+ $knownLanguages = Language::getLanguageNames( false );
 73+ if ( !array_key_exists( $code, $knownLanguages ) ) {
 74+ ExternalPagesErrors::showError( 'externalpages-bad-language' );
 75+ return(false);
 76+ }
 77+ }
 78+
 79+ if ( !$wgRequest->getVal( 'EPproject' ) ) {
 80+ ExternalPagesErrors::showError( 'externalpages-no-project' );
 81+ return(false);
 82+ }
 83+ else {
 84+ $this->mProject = $wgRequest->getVal( 'EPproject' );
 85+ // for initial fundraiser rollout, just allow pages from one project. this
 86+ // can be generalized later
 87+ if ( 'wikimediafoundation.org' != $this->mProject ) {
 88+ ExternalPagesErrors::showError( 'externalpages-bad-project' );
 89+ return(false);
 90+ }
 91+ }
 92+
 93+ if ( !$wgRequest->getVal( 'EPpage' ) ) {
 94+ ExternalPagesErrors::showError( 'externalpages-no-page' );
 95+ return(false);
 96+ }
 97+ $this->mPage = $wgRequest->getVal( 'EPpage' );
 98+ return(true);
 99+ }
 100+
 101+ private function constructURL() {
 102+ $url = "http://" . $this->mProject . "/w/api.php?action=parse&page=";
 103+ $title = ( $this->mYear ? $this->mYear."/" : "" ) . $this->mPage;
 104+ $title .= $this->mLang ? "/".$this->mLang : "" ;
 105+ $title = urlencode( $title );
 106+ $url = $url . $title . '&format=xml';
 107+ return( $url );
 108+ }
 109+
 110+ private function retrieveExternalPage( $url ) {
 111+ global $wgOut, $wgRequest;
 112+
 113+ $url_text = @file_get_contents( $url );
 114+ if ( empty( $url_text ) ) {
 115+ ExternalPagesErrors::showError( 'externalpages-bad-url' );
 116+ return(false);
 117+ }
 118+ else {
 119+ if ( preg_match('/<text[^>]*>([^<]*)<\/text>/',$url_text,$matches) ) {
 120+ $text = $matches[1];
 121+ $text = html_entity_decode( $text );
 122+ $absurl = '<a href="http://'.$this->mProject."/";
 123+ $text = str_replace( '<a href="https://www.mediawiki.org/', $absurl, $text );
 124+ $wgOut->addHTML( $text );
 125+ }
 126+ else {
 127+ ExternalPagesErrors::showError( 'externalpages-bad-url-data' );
 128+ return(false);
 129+ }
 130+ }
 131+ return;
 132+ }
 133+}
 134+
 135+/*
 136+ * error handler for some formatting of error messages
 137+ */
 138+class ExternalPagesErrors {
 139+
 140+ static function showError( $errorText='externalpages-error-generic', $phpErrorText=false ) {
 141+ global $wgOut;
 142+
 143+ $args = func_get_args();
 144+
 145+ array_shift( $args );
 146+ $msg = wfMsg( $errorText, $args );
 147+
 148+ $wgOut->addWikiText( "<div class=\"errorbox\" style=\"float:none;\">" .
 149+ $msg .
 150+ "</div>" );
 151+ }
 152+
 153+}
 154+
 155+?>
Property changes on: trunk/extensions/ExternalPages/ExternalPages_body.php
___________________________________________________________________
Added: svn:eol-style
1156 + native
Index: trunk/extensions/ExternalPages/ExternalPages.i18n.php
@@ -0,0 +1,24 @@
 2+<?php
 3+ /**
 4+ * Internationalizations for extension ExternalPages.
 5+ *
 6+ * @addtogroup Extensions
 7+ */
 8+
 9+$messages = array();
 10+
 11+$messages['en'] = array(
 12+ 'externalpages' => 'External Pages',
 13+ 'externalpages-desc' => 'Retrieves and displays pages from remote WMF sites',
 14+ 'externalpages-bad-year' => 'Bad year specified',
 15+ 'externalpages-bad-language' => 'Bad language specified',
 16+ 'externalpages-bad-project' => 'Bad project specified',
 17+ 'externalpages-no-project' => 'No project specified',
 18+ 'externalpages-bad-page' => 'Bad page specified',
 19+ 'externalpages-no-page' => 'No page specified',
 20+ 'externalpages-error-generic' => 'Error encountered',
 21+ 'externalpages-bad-url' => 'Failed to retrieve url',
 22+ 'externalpages-bad-url-data' => 'Failed to retrieve page contents',
 23+);
 24+
 25+?>
Property changes on: trunk/extensions/ExternalPages/ExternalPages.i18n.php
___________________________________________________________________
Added: svn:eol-style
126 + native
Index: trunk/extensions/ExternalPages/SpecialExternalPages.php
@@ -0,0 +1,52 @@
 2+<?php
 3+/**
 4+ * A Special Page extension to retrieve and display a page
 5+ * from a specified external WMF site, with optional year,
 6+ * project
 7+ * and language parameters
 8+ *
 9+ * @addtogroup Extensions
 10+ *
 11+ * @author Ariel Glenn <ariel@wikimedia.org>
 12+ * @license http://www.gnu.org/copyleft/gpl.html GNU General Public License 3.0 or later
 13+ */
 14+
 15+if ( !defined( 'MEDIAWIKI' ) ) {
 16+ echo <<<EOT
 17+To install the ExternalPages extension, put the following line in LocalSettings.php:
 18+require_once( "\$IP/extensions/SpecialExternalPages.php" );
 19+EOT;
 20+ exit(1);
 21+}
 22+
 23+$wgExtensionCredits['specialpage'][] = array(
 24+ 'name' => 'ExternalPages',
 25+ 'version' => '0.1',
 26+ 'author' => 'Ariel Glenn',
 27+ 'url' => 'http://www.mediawiki.org/wiki/Extension:ExternalPages',
 28+ 'description' => 'Retrieve and display page from a remote WMF site',
 29+ 'descriptionmsg' => 'externalpages-desc',
 30+);
 31+
 32+$dir = dirname( __FILE__ ) . '/';
 33+
 34+$wgExtensionMessagesFiles['ExternalPages'] = $dir . 'ExternalPages.i18n.php';
 35+$wgExtensionAliasesFiles['ExternalPages'] = $dir . 'ExternalPages.alias.php';
 36+
 37+$wgAutoloadClasses['ExternalPages'] = $dir . 'ExternalPages_body.php';
 38+
 39+$wgSpecialPages['ExternalPages'] = 'ExternalPages';
 40+$wgSpecialPageGroups['ExternalPages'] = 'users';
 41+$wgHooks['LanguageGetSpecialPageAliases'][] = 'externalPagesLocalizedPageName';
 42+
 43+function externalPagesLocalizedPageName( &$specialPageArray, $code ) {
 44+ wfLoadExtensionMessages( 'ExternalPages' );
 45+ $text = wfMsg( 'externalpages' );
 46+
 47+ # Convert from title in text form to DBKey and put it into the alias array:
 48+ $title = Title::newFromText( $text );
 49+ $specialPageArray['ExternalPages'][] = $title->getDBKey();
 50+ return true;
 51+}
 52+
 53+?>
Property changes on: trunk/extensions/ExternalPages/SpecialExternalPages.php
___________________________________________________________________
Added: svn:eol-style
154 + native

Comments

#Comment by Tim Starling (talk | contribs)   06:25, 2 December 2009

What is this for?

#Comment by ArielGlenn (talk | contribs)   07:53, 2 December 2009

It's an extension requested for the fundraising effort; it will retrieve a deisgnated page (for now just from wikimediafoundation.org) and display the text on the user's current wiki.

#Comment by Tim Starling (talk | contribs)   07:57, 2 December 2009

What's wrong with a link?

#Comment by ArielGlenn (talk | contribs)   07:59, 2 December 2009

it's supposed to display the text, not be a link to it. the point is instead of moving people to the foundation wiki we keep them on their home wiki for a page longer.

#Comment by Tim Starling (talk | contribs)   05:04, 5 January 2010

Well, put me down as skeptical. But besides that, please allow me to make a few comments on the code.

Your functions have a bit of a problem with not doing what their name says they do, and with inelegant data flow. And some of your variables don't contain what their name says they contain.

constructURL() has a problem of odd data flow, since it doesn't just return the URL, it stores it into a member variable and expects the caller to somehow work out where to find it (despite the lack of documentation). It would be easier to understand if you used the usual lazy-initialisation convention:

function getPageURL() {
   if ( is_null( $this->mPageURL ) ) {
       ...
   }
   return $this->mPageURL;
}

And then instead of

private $mPageURL = '';

you would have

private $mPageURL;

which is a nice habit to get into since PHP considers strings like "0.0" to be false, breaking code like yours that converts strings to boolean if such strings happen to be input by the user.

cacheHeaders() doesn't do what it says it does. It actually sets the cache headers, it doesn't cache the headers itself. It should probably be called setCacheHeaders().

Similarly, getPageFromCache() should return a page, not true or false. This is a weakly typed language you're working in now, so it's not necessary to dedicate the return value to a success/failure value and nothing else. You can return the page if it works, or false if it doesn't. Then instead of:

$this->getPageFromCache();
if ( !$this->mPageText ) {
	$serializedText = Http::get( $this->mPageURL );

you will have (avoiding conversion from string to boolean again):

$pageText = $this->getPageFromCache();
if ( $pageText === false ) {
	$serializedText = Http::get( $this->mPageURL );


$absurl = '<a href="http://' . $this->mProject . '/';

This is not a URL, it is half a link. Maybe it could be called $linkStart.

savePageToCache() should accept the text as a parameter rather than getting it from a member variable.

In ExternalPagesErrors::showError():

 $msg = wfMsg( $errorText, $args );
 
 $wgOut->addWikiText(
 	'<div class="errorbox" style="float:none;">' .
 	$msg .
 	'</div>'

This is incorrect, because wfMsg() has already parsed the message once, and addWikiText() will parse it again. The double parsing will screw up various kinds of markup. Instead, you should use wfMsgNoTrans(), or OutputPage::wrapWikiMsg():

 array_unshift( $args, $errorText );
 $wgOut->wrapWikiMsg( '<div class="errorbox" style="float:none;">$1</div>', $args );
#Comment by 😂 (talk | contribs)   12:59, 5 January 2010

I was skeptical of the idea when I first heard of it several weeks back. As I understood it, it was basically scary transclusion as an extension.

#Comment by Bryan (talk | contribs)   18:46, 5 January 2010

Instead of using regexes to parse XML, request the page data in format=php and unserialize() it, or if you don't trust the remote server in format=json and use json_decode()

#Comment by Bryan (talk | contribs)   18:50, 5 January 2010

Oh well, that was already done in r58636.

#Comment by Tim Starling (talk | contribs)   06:14, 9 February 2010

Rewritten in r62165.

Status & tagging log