Sophivorus has uploaded a new change for review. ( https://gerrit.wikimedia.org/r/334050 )
Change subject: Requested fixes ...................................................................... Requested fixes - Break code into smaller methods - Add error handling - Build <span> with Html::rawElement - Short array syntax - Add Parser typehint - Remove extract() - API requests to formatversion=2 - Add user agent to API requests - Validate language codes - Remove <WikipediaExtract> tag and duplicate code - Declare public and private variables and methods - Add wgWikipediaExtractsAddCredits config variable - Add \n to EOF Bug: T149766 Change-Id: I33d016e0ca0c2b7a68d8760c6835efb19ea713f2 --- M WikipediaExtracts.php M extension.json 2 files changed, 199 insertions(+), 147 deletions(-) git pull ssh://gerrit.wikimedia.org:29418/mediawiki/extensions/WikipediaExtracts refs/changes/50/334050/1 diff --git a/WikipediaExtracts.php b/WikipediaExtracts.php index cdfa55a..bfc36b3 100644 --- a/WikipediaExtracts.php +++ b/WikipediaExtracts.php @@ -2,174 +2,222 @@ class WikipediaExtracts { - static function onParserFirstCallInit( &$parser ) { - $parser->setHook( 'WikipediaExtract', 'WikipediaExtracts::onHook' ); + /** + * User agent for querying the API + */ + private static $userAgent = 'User-Agent: Extension:WikipediaExtracts/2.0 (https://www.mediawiki.org/wiki/Extension:WikipediaExtracts)'; + + /** + * Parser object + */ + private static $parser; + + /** + * Language code of the local wiki + */ + public static $contentLanguage; + + /** + * Associative array of the parameters passed to the parser function + */ + private static $params; + + /** + * Title of the Wikipedia article to extract + */ + private static $wikipediaTitle; + + /** + * Language code of the Wikipedia to query + */ + private static $wikipediaLanguage; + + /** + * Main hook + */ + public static function onParserFirstCallInit( Parser &$parser ) { $parser->setFunctionHook( 'WikipediaExtract', 'WikipediaExtracts::onFunctionHook' ); - return true; } - static function onHook( $input, array $args, Parser $parser, PPFrame $frame ) { - // Set the defaults - $title = $parser->getTitle()->getRootText(); - $language = $parser->getTargetLanguage()->getCode(); - $chars = null; - $sentences = null; - $limit = null; - $intro = null; - $plaintext = null; - $sectionformat = null; - $continue = null; - $variant = null; + /** + * Parser function hook + */ + public static function onFunctionHook( Parser $parser, $input = null ) { + try { + self::$parser = $parser; + self::$contentLanguage = $parser->getTargetLanguage(); + self::$params = self::parseParams( array_slice( func_get_args(), 2 ) ); + self::$wikipediaTitle = self::getWikipediaTitle( $input ); + self::$wikipediaLanguage = self::getWikipediaLanguage( $input ); - // Override with user input - extract( $args ); - if ( $input ) { - if ( filter_var( $input, FILTER_VALIDATE_URL ) ) { - // Extract the title - $path = parse_url( $input, PHP_URL_PATH ); - $PATH = explode( '/', $path ); - $title = $PATH[2]; + $html = self::getExtract(); - // Extract the language - $host = parse_url( $input, PHP_URL_HOST ); - $HOST = explode( '.', $host ); - $language = $HOST[0]; - } else { - $title = $input; + global $wgWikipediaExtractsAddCredits; + if ( $wgWikipediaExtractsAddCredits ) { + $html .= self::getCredits(); } + } catch ( WikipediaExtractsError $error ) { + $html = $error->getHtmlMessage(); } - - // Validate language code - if ( !Language::isValidCode( $language ) ) { - return '<span class="error">' . wfMessage( 'wikipediaextracts-invalid-language', $language ) . '</span>'; - } - - // Query the Wikipedia API - $data = array( - 'action' => 'query', - 'titles' => urldecode( $title ), - 'prop' => 'extracts', - 'exchars' => $chars, - 'exsentences' => $sentences, - 'exlimit' => $limit, - 'exintro' => $intro, - 'explaintext' => $plaintext, - 'exsectionformat' => $sectionformat, - 'excontinue' => $continue, - 'exvariant' => $variant, - 'redirects' => true, - 'format' => 'json' - ); - $query = 'https://' . $language . '.wikipedia.org/w/api.php?' . http_build_query( $data ); - $contents = file_get_contents( $query ); - $contents = json_decode( $contents ); - $pages = $contents->query->pages; - foreach ( $pages as $key => $value ) { - if ( $key === '-1' ) { - return '<span class="error">' . wfMessage( 'wikipediaextracts-404', $title ) . '</span>'; - } - $extract = $value->extract; - $url = 'https://' . $language . '.wikipedia.org/wiki/' . urlencode( $title ); - $extract .= wfMessage( 'wikipediaextracts-credits', $url )->parse(); - return $extract; - } + return $html; } - static function onFunctionHook( $parser, $input = null ) { - // Set the defaults - $title = $parser->getTitle()->getRootText(); - $language = $parser->getTargetLanguage()->getCode(); - $chars = null; - $sentences = null; - $limit = null; - $intro = null; - $plaintext = null; - $sectionformat = null; - $continue = null; - $variant = null; - - // Override with user input - $options = WikipediaExtracts::extractOptions( array_slice( func_get_args(), 2 ) ); - extract( $options ); + /** + * Get the title of the Wikipedia article to extract + */ + private static function getWikipediaTitle( $input ) { if ( $input ) { if ( filter_var( $input, FILTER_VALIDATE_URL ) ) { - // Extract the title - $path = parse_url( $input, PHP_URL_PATH ); + $path = parse_url( $input, PHP_URL_PATH ); // Example path "/wiki/Article_title" $PATH = explode( '/', $path ); - $title = $PATH[2]; - - // Extract the language - $host = parse_url( $input, PHP_URL_HOST ); - $HOST = explode( '.', $host ); - $language = $HOST[0]; + $wikipediaTitle = urldecode( $PATH[2] ); } else { - $title = $input; + $wikipediaTitle = $input; + } + } else { + $wikipediaTitle = self::getParam( 'title', self::$parser->getTitle()->getRootText() ); + } + return $wikipediaTitle; + } + + /** + * Get the language code of the Wikipedia to query + */ + private static function getWikipediaLanguage( $input ) { + if ( $input and filter_var( $input, FILTER_VALIDATE_URL ) ) { + $host = parse_url( $input, PHP_URL_HOST ); // Example host "en.wikipedia.org" + $HOST = explode( '.', $host ); + $wikipediaLanguage = $HOST[0]; + } else { + $wikipediaLanguage = self::getParam( 'language', self::$contentLanguage->getCode() ); + } + if ( !Language::isValidCode( $wikipediaLanguage ) ) { + throw new WikipediaExtractsError( 'invalid-language', $wikipediaLanguage ); + } + return $wikipediaLanguage; + } + + /** + * Get a param value out of the $params array + * + * @param string $key of the param + * @param string $default if no value is found + * @return string param value + */ + private static function getParam( $key, $default = null ) { + if ( array_key_exists( $key, self::$params ) ) { + return self::$params[ $key ]; + } + return $default; + } + + /** + * Convert an array of values in form [0] => "name=value" + * into a real associative array in form [name] => value. + * If no = is provided, true is assumed like this: [name] => true + * + * @param array string $params + * @return array $params + */ + private static function parseParams( $params ) { + $array = []; + foreach ( $params as $param ) { + $pair = explode( '=', $param, 2 ); + if ( count( $pair ) === 2 ) { + $name = trim( $pair[0] ); + $value = trim( $pair[1] ); + $array[ $name ] = $value; + } else if ( count( $pair ) === 1 ) { + $name = trim( $pair[0] ); + $array[ $name ] = true; } } + return $array; + } - // Validate language code - if ( !Language::isValidCode( $language ) ) { - return '<span class="error">' . wfMessage( 'wikipediaextracts-invalid-language', $language ) . '</span>'; - } - - // Query the Wikipedia API - $data = array( + /** + * Build the query to Wikipedia and get the extract + */ + private static function getExtract() { + $data = [ 'action' => 'query', - 'titles' => urldecode( $title ), + 'titles' => self::$wikipediaTitle, 'prop' => 'extracts', - 'exchars' => $chars, - 'exsentences' => $sentences, - 'exlimit' => $limit, - 'exintro' => $intro, - 'explaintext' => $plaintext, - 'exsectionformat' => $sectionformat, - 'excontinue' => $continue, - 'exvariant' => $variant, + 'exchars' => self::getParam( 'chars' ), + 'exsentences' => self::getParam( 'sentences' ), + 'exlimit' => self::getParam( 'limit' ), + 'exintro' => self::getParam( 'intro' ), + 'explaintext' => self::getParam( 'plaintext' ), + 'exsectionformat' => self::getParam( 'sectionformat' ), + 'excontinue' => self::getParam( 'continue' ), + 'exvariant' => self::getParam( 'variant' ), 'redirects' => true, - 'format' => 'json' - ); - $query = 'https://' . $language . '.wikipedia.org/w/api.php?' . http_build_query( $data ); - $contents = file_get_contents( $query ); - $contents = json_decode( $contents ); - $pages = $contents->query->pages; - foreach ( $pages as $key => $value ) { - if ( $key === '-1' ) { - return '<span class="error">' . wfMessage( 'wikipediaextracts-404', $title ) . '</span>'; + 'format' => 'json', + 'formatversion' => 2 + ]; + $query = 'https://' . self::$wikipediaLanguage . '.wikipedia.org/w/api.php?' . http_build_query( $data ); + $request = MWHttpRequest::factory( $query ); + $request->setUserAgent( self::$userAgent ); + $status = $request->execute(); + if ( !$status->isOK() ) { + if ( $status->getValue() === 100 ) { + throw new WikipediaExtractsError( 'invalid-language', self::$wikipediaLanguage ); } - $extract = $value->extract; - $url = 'https://' . $language . '.wikipedia.org/wiki/' . urlencode( $title ); - $extract .= wfMessage( 'wikipediaextracts-credits', $url )->plain(); - return $extract; + throw new WikipediaExtractsError( 'error' ); + } + $content = FormatJson::decode( $request->getContent() ); + if ( !$content ) { + throw new WikipediaExtractsError( 'error' ); + } + if ( array_key_exists( 'error-codes', $content ) ) { + throw new WikipediaExtractsError( 'error' ); + } + foreach ( $content->query->pages as $page ) { + if ( property_exists( $page, 'missing' ) ) { + throw new WikipediaExtractsError( '404', self::$wikipediaTitle ); + } + return $page->extract; } } /** - * Converts an array of values in form [0] => "name=value" into a real - * associative array in form [name] => value. If no = is provided, - * true is assumed like this: [name] => true - * - * @param array string $options - * @return array $results + * Get a span with a link to Wikipedia */ - static function extractOptions( $options ) { - $results = array(); - - foreach ( $options as $option ) { - $pair = explode( '=', $option, 2 ); - if ( count( $pair ) === 2 ) { - $name = trim( $pair[0] ); - $value = trim( $pair[1] ); - $results[ $name ] = $value; - } - if ( count( $pair ) === 1 ) { - $name = trim( $pair[0] ); - $results[ $name ] = true; - } - } - // Now you've got an array that looks like this: - // [foo] => "bar" - // [apple] => "orange" - // [banana] => true - return $results; + private static function getCredits() { + $title = Title::newFromText( self::$wikipediaTitle ); + $url = 'https://' . self::$wikipediaLanguage . '.wikipedia.org/wiki/' . $title->getPartialUrl(); + return Html::rawElement( + 'small', [ + 'lang' => self::$contentLanguage->getHtmlCode(), + 'dir' => self::$contentLanguage->getDir() + ], + wfMessage( 'wikipediaextracts-credits', $url )->plain() + ); } -} \ No newline at end of file +} + +/** + * Error handler + */ +class WikipediaExtractsError extends Exception { + + public $messageKey; + + public $messageParam; + + public function __construct( $messageKey, $messageParam = null ) { + $this->messageKey = $messageKey; + $this->messageParam = $messageParam; + } + + public function getHtmlMessage() { + return Html::rawElement( + 'span', [ + 'class' => 'error mw-ext-cite-error', + 'lang' => WikipediaExtracts::$contentLanguage->getHtmlCode(), + 'dir' => WikipediaExtracts::$contentLanguage->getDir() + ], + wfMessage( 'wikipediaextracts-' . $this->messageKey, $this->messageParam ) + ); + } +} diff --git a/extension.json b/extension.json index 4ba8bdc..dc85cee 100644 --- a/extension.json +++ b/extension.json @@ -1,6 +1,6 @@ { "name": "WikipediaExtracts", - "version": "1.3", + "version": "2.0", "author": "[http://mediawiki.org/wiki/User:Felipe_Schenone Felipe Schenone]", "url": "https://www.mediawiki.org/wiki/Extension:WikipediaExtracts", "descriptionmsg": "wikipediaextracts-desc", @@ -14,10 +14,14 @@ "WikipediaExtractsAlias": "WikipediaExtracts.magic.php" }, "AutoloadClasses": { - "WikipediaExtracts": "WikipediaExtracts.php" + "WikipediaExtracts": "WikipediaExtracts.php", + "WikipediaExtractsError": "WikipediaExtracts.php" }, "Hooks": { "ParserFirstCallInit": "WikipediaExtracts::onParserFirstCallInit" }, + "config": { + "WikipediaExtractsAddCredits": true + }, "manifest_version": 1 } -- To view, visit https://gerrit.wikimedia.org/r/334050 To unsubscribe, visit https://gerrit.wikimedia.org/r/settings Gerrit-MessageType: newchange Gerrit-Change-Id: I33d016e0ca0c2b7a68d8760c6835efb19ea713f2 Gerrit-PatchSet: 1 Gerrit-Project: mediawiki/extensions/WikipediaExtracts Gerrit-Branch: master Gerrit-Owner: Sophivorus <scheno...@gmail.com> _______________________________________________ MediaWiki-commits mailing list MediaWiki-commits@lists.wikimedia.org https://lists.wikimedia.org/mailman/listinfo/mediawiki-commits