r102386 MediaWiki - Code Review archive

Repository:MediaWiki
Revision:r102385‎ | r102386 | r102387 >
Date:10:45, 8 November 2011
Author:jeroendedauw
Status:deferred (Comments)
Tags:
Comment:
importing SemanticImageInput extension
Modified paths:
  • /trunk/extensions/SemanticImageInput (added) (history)
  • /trunk/extensions/SemanticImageInput/SemanticImageInput.i18.php (added) (history)
  • /trunk/extensions/SemanticImageInput/SemanticImageInput.php (added) (history)
  • /trunk/extensions/SemanticImageInput/SemanticImageInput.settings.php (added) (history)
  • /trunk/extensions/SemanticImageInput/includes (added) (history)
  • /trunk/extensions/SemanticImageInput/includes/InstantImageInput.php (added) (history)
  • /trunk/extensions/SemanticImageInput/resources (added) (history)
  • /trunk/extensions/SemanticImageInput/resources/jquery.instantImage.js (added) (history)
  • /trunk/extensions/SemanticImageInput/resources/sii.instantImage.js (added) (history)

Diff [purge]

Index: trunk/extensions/SemanticImageInput/includes/InstantImageInput.php
@@ -0,0 +1,151 @@
 2+<?php
 3+
 4+/**
 5+ * Form input for adding images from Wikipedia or Wikimedia Commons.
 6+ *
 7+ * @since 0.1
 8+ *
 9+ * @file InstantImageInput.php
 10+ * @ingroup SFFormInput
 11+ * @ingroup SII
 12+ *
 13+ * @licence GNU GPL v3+
 14+ * @author Jeroen De Dauw < jeroendedauw@gmail.com >
 15+ */
 16+class InstantImageInput extends SFFormInput {
 17+
 18+ public static function getName() {
 19+ return 'instantimage';
 20+ }
 21+
 22+ public static function getDefaultPropTypes() {
 23+ return array(
 24+ );
 25+ }
 26+
 27+ public static function getOtherPropTypesHandled() {
 28+ return array( '_wpg' );
 29+ }
 30+
 31+ public static function getDefaultPropTypeLists() {
 32+ return array(
 33+ );
 34+ }
 35+
 36+ public static function getOtherPropTypeListsHandled() {
 37+ return array();
 38+ }
 39+
 40+ /**
 41+ * Returns the HTML code to be included in the output page for this input.
 42+ */
 43+ public function getHtmlText() {
 44+ return self::getHTML(
 45+ $this->mCurrentValue,
 46+ $this->mInputName,
 47+ $this->mIsMandatory,
 48+ $this->mIsDisabled,
 49+ $this->mOtherArgs
 50+ );
 51+ }
 52+
 53+ public static function getParameters() {
 54+ $params = parent::getParameters();
 55+
 56+ $params[] = array(
 57+ 'name' => 'type',
 58+ 'type' => 'str',
 59+ 'description' => wfMsg( 'sii-imageinput-type' )
 60+ ); // page
 61+
 62+ $params[] = array(
 63+ 'name' => 'hide',
 64+ 'type' => 'bool',
 65+ 'description' => wfMsg( 'sii-imageinput-hide' )
 66+ ); // false
 67+
 68+ $params[] = array(
 69+ 'name' => 'width',
 70+ 'type' => 'int',
 71+ 'description' => wfMsg( 'sii-imageinput-width' )
 72+ ); // 200
 73+
 74+ $params[] = array(
 75+ 'name' => 'showdefault',
 76+ 'type' => 'bool',
 77+ 'description' => wfMsg( 'sii-imageinput-showdefault' )
 78+ ); // true
 79+
 80+ return $params;
 81+ }
 82+
 83+ public static function getHTML( $cur_value, $input_name, $is_mandatory, $is_disabled, $other_args ) {
 84+ global $wgOut;
 85+ $html = '';
 86+
 87+ $showDefault = !array_key_exists( 'showdefault', $other_args ) || $other_args['showdefault'] === 'yes';
 88+
 89+ if ( $showDefault && !array_key_exists( 'default', $other_args ) ) {
 90+ $other_args['default'] = SIISettings::get( 'defaultImage' );
 91+ }
 92+
 93+ $defImg = $other_args['default'];
 94+
 95+ $noImage = is_null( $cur_value ) || trim( $cur_value ) === '';
 96+ $showInForm = !array_key_exists( 'hide', $other_args ) || trim( $other_args['hide'] ) === 'no';
 97+
 98+ $width = array_key_exists( 'width', $other_args ) ? $other_args['width'] : SIISettings::get( 'defaultWidth' );
 99+
 100+ if ( $showInForm && !$noImage ) {
 101+ if ( $noImage ) {
 102+ $html .= wfMsg( 'sii-imageinput-loading' );
 103+ }
 104+ else {
 105+ global $wgParser;
 106+
 107+ $html .= $wgParser->parse(
 108+ '[[' . $cur_value . '|' . $width . ']]',
 109+ Title::newFromText( self::getPage() ),
 110+ ( new ParserOptions() )
 111+ )->getText();
 112+ }
 113+ }
 114+
 115+ if ( $noImage || $cur_value === $defImg ) {
 116+ $wgOut->addModules( 'sii.image' );
 117+ $cur_value = $defImg;
 118+
 119+ $args = array(
 120+ 'class' => 'instantImage',
 121+ 'data-image-type' => $other_args['type'],
 122+ 'data-input-name' => $input_name,
 123+ 'data-image-width' => $width,
 124+ );
 125+
 126+ if ( $other_args['type'] == 'page' ) {
 127+ $args['data-image-name'] = self::getPage();
 128+ }
 129+
 130+ $html = Html::rawElement(
 131+ 'div',
 132+ $args,
 133+ $html
 134+ );
 135+ }
 136+
 137+ return $html . Html::input( $input_name, $cur_value, 'hidden' );
 138+ }
 139+
 140+ protected static function getPage() {
 141+ $parts = explode( '/', $GLOBALS['wgTitle']->getFullText() );
 142+
 143+ // TODO: this will not work for non-en.
 144+ if ( $parts[0] == 'Special:FormEdit' ) {
 145+ array_shift( $parts );
 146+ array_shift( $parts );
 147+ }
 148+
 149+ return implode( '/', $parts );
 150+ }
 151+
 152+}
Property changes on: trunk/extensions/SemanticImageInput/includes/InstantImageInput.php
___________________________________________________________________
Added: svn:eol-style
1153 + native
Index: trunk/extensions/SemanticImageInput/resources/sii.instantImage.js
@@ -0,0 +1,54 @@
 2+/**
 3+ * JavasSript for the Semantic Image Input MediaWiki extension.
 4+ *
 5+ * TODO: this was written in a sprint; could be made less evil.
 6+ *
 7+ * @author Jeroen De Dauw <jeroendedauw at gmail dot com>
 8+ */
 9+
 10+(function( $, mw ) {
 11+
 12+ $( document ).ready( function() {
 13+ // Find all instant image inputs in the form.
 14+ $( '.instantImage' ).each( function( index, domElement ) {
 15+ $e = $( domElement );
 16+
 17+ // Those of type item bind to the first input in their multiple instance template.
 18+ if ( $e.attr( 'data-item-type' ) === 'item' ) {
 19+ $e.instantImage( {
 20+ 'iteminput': $e.closest( 'td' ).find( 'input' ).first(),
 21+ 'inputname': $e.attr( 'data-input-name' ),
 22+ 'imagewidth': $e.attr( 'data-image-width' )
 23+ } );
 24+ }
 25+ else {
 26+ // Those of type page do not bind to an input but have the image name as attribute.
 27+ $e.instantImage( {
 28+ 'imagename': $e.attr( 'data-image-name' ),
 29+ 'inputname': $e.attr( 'data-input-name' ),
 30+ 'imagewidth': $e.attr( 'data-image-width' )
 31+ } );
 32+ }
 33+ } );
 34+
 35+ // This is a serious hack to initiate instant image inputs that get added via new multuple
 36+ // instance templates. If there is a sane way to do this, it should be used.
 37+ $( '.multipleTemplateAdder' ).click( function() {
 38+ var $this = $( this );
 39+ setTimeout(
 40+ function() {
 41+ $t = $this.closest( 'fieldset' ).find( '.multipleTemplateInstance' ).last();
 42+ $e = $t.find( '.instantImage' ).first();
 43+
 44+ $e.instantImage( {
 45+ 'iteminput': $t.find( 'input' ).first(),
 46+ 'inputname': $t.find( 'input[type=hidden]' ).last().attr( 'name' ),
 47+ 'imagewidth': $e.attr( 'data-image-width' )
 48+ } );
 49+ },
 50+ 100
 51+ );
 52+ } );
 53+ } );
 54+
 55+})( window.jQuery, window.mediaWiki );
\ No newline at end of file
Property changes on: trunk/extensions/SemanticImageInput/resources/sii.instantImage.js
___________________________________________________________________
Added: svn:eol-style
156 + native
Index: trunk/extensions/SemanticImageInput/resources/jquery.instantImage.js
@@ -0,0 +1,212 @@
 2+/**
 3+ * JavasSript for the Semantic Image Input MediaWiki extension.
 4+ *
 5+ * TODO: this was written in a sprint; could be made less evil.
 6+ *
 7+ * @author Jeroen De Dauw <jeroendedauw at gmail dot com>
 8+ */
 9+
 10+(function( $, mw ) {
 11+
 12+ $.fn.instantImage = function( opts ) {
 13+
 14+ var _this = this;
 15+ var $this = $( this );
 16+
 17+ this.loadedFirstReq = null;
 18+ this.images = null;
 19+ this.raw = null;
 20+
 21+ this.options = {
 22+ 'imagename': 'Beatles',
 23+ 'inputname': '',
 24+ 'apipath': 'https://en.wikipedia.org/w/api.php?callback=?',
 25+ 'imagewidth': 200
 26+ };
 27+
 28+ this.getMainTitle = function( callback ) {
 29+ $.getJSON(
 30+ this.options.apipath,
 31+ {
 32+ 'action': 'query',
 33+ 'format': 'json',
 34+ 'titles': this.options.imagename,
 35+ 'redirects': 1,
 36+ },
 37+ function( data ) {
 38+ if ( data.query && data.query.redirects ) {
 39+ _this.options.imagename = data.query.redirects[0].to;
 40+ }
 41+
 42+ callback();
 43+ }
 44+ );
 45+ };
 46+
 47+ this.getImages = function( callback ) {
 48+ $.getJSON(
 49+ this.options.apipath,
 50+ {
 51+ 'action': 'query',
 52+ 'format': 'json',
 53+ 'prop': 'images',
 54+ 'titles': this.options.imagename,
 55+ 'redirects': 1,
 56+ 'imlimit': 500
 57+ },
 58+ function( data ) {
 59+ var imgNames = [];
 60+
 61+ if ( data.query && data.query.pages ) {
 62+ for ( pageid in data.query.pages ) {
 63+ var images = data.query.pages[pageid].images;
 64+
 65+ if ( typeof images !== 'undefined' ) {
 66+ for ( var i = images.length - 1; i >= 0; i-- ) {
 67+ imgNames.push( images[i].title );
 68+ }
 69+ }
 70+
 71+ _this.images = imgNames;
 72+ callback();
 73+ return;
 74+ }
 75+ }
 76+
 77+ _this.showNoImage();
 78+ }
 79+ );
 80+ };
 81+
 82+ this.getRaw = function( callback ) {
 83+ $.getJSON(
 84+ this.options.apipath,
 85+ {
 86+ 'action': 'query',
 87+ 'format': 'json',
 88+ 'prop': 'revisions',
 89+ 'rvprop': 'content',
 90+ 'titles': this.options.imagename
 91+ },
 92+ function( data ) {
 93+ if ( data.query ) {
 94+ for ( pageWikiID in data.query.pages ) {
 95+ if ( data.query.pages[pageWikiID].revisions ) {
 96+ _this.raw = data.query.pages[pageWikiID].revisions[0]["*"];
 97+ callback();
 98+ return;
 99+ }
 100+ }
 101+ }
 102+
 103+ _this.showNoImage();
 104+ }
 105+ );
 106+ };
 107+
 108+ this.getFirstImage = function() {
 109+ var image = false;
 110+ var lowest = this.raw.length;
 111+
 112+ for ( var i = this.images.length - 1; i >= 0; i-- ) {
 113+ var img = this.images[i].split( ':', 2 );
 114+ var index = this.raw.indexOf( img[img.length > 1 ? 1 : 0] );
 115+
 116+ if ( index !== -1 && index < lowest ) {
 117+ lowest = index;
 118+ image = this.images[i];
 119+ }
 120+ }
 121+
 122+ return image;
 123+ };
 124+
 125+ this.showNoImage = function() {
 126+ $this.html( 'No image found.' );
 127+ };
 128+
 129+ this.showImage = function( image ) {
 130+ if ( image === false ) {
 131+ this.showNoImage();
 132+ return;
 133+ }
 134+
 135+ $.getJSON(
 136+ this.options.apipath,
 137+ {
 138+ 'action': 'query',
 139+ 'format': 'json',
 140+ 'prop': 'imageinfo',
 141+ 'iiprop': 'url',
 142+ 'titles': image,
 143+ 'iiurlwidth': this.options.imagewidth
 144+ },
 145+ function( data ) {
 146+ if ( data.query && data.query.pages ) {
 147+ var pages = data.query.pages;
 148+
 149+ for ( p in pages ) {
 150+ var info = pages[p].imageinfo;
 151+ for ( i in info ) {
 152+ if ( info[i].thumburl.indexOf( '/wikipedia/commons/' ) !== -1 ) {
 153+ $( 'input[name="' + _this.options.inputname + '"]' ).val( image );
 154+
 155+ $this.html( $( '<img />' ).attr( {
 156+ 'src': info[i].thumburl,
 157+ 'width': _this.options.imagewidth + 'px'
 158+ } ) );
 159+
 160+ return;
 161+ }
 162+ }
 163+
 164+ _this.showNoImage();
 165+ }
 166+ }
 167+ }
 168+ );
 169+ };
 170+
 171+ this.dispReqResult = function( images ) {
 172+ if ( !_this.loadedFirstReq ) {
 173+ _this.loadedFirstReq = true;
 174+ }
 175+ else {
 176+ _this.showImage( _this.getFirstImage() );
 177+ }
 178+ };
 179+
 180+ this.start = function() {
 181+ this.loadedFirstReq = false;
 182+
 183+ if ( this.options.iteminput ) {
 184+ this.options.imagename = this.options.iteminput.val();
 185+ }
 186+
 187+ if ( this.options.imagename.trim() === '' ) {
 188+ $this.html( '' );
 189+ }
 190+ else {
 191+ this.getMainTitle( function() {
 192+ _this.getImages( _this.dispReqResult );
 193+ _this.getRaw( _this.dispReqResult );
 194+ } );
 195+ }
 196+ }
 197+
 198+ this.init = function() {
 199+ $.extend( this.options, opts );
 200+
 201+ if ( this.options.iteminput ) {
 202+ this.options.iteminput.change( function() { _this.start(); } );
 203+ }
 204+
 205+ this.start();
 206+ };
 207+
 208+ this.init();
 209+
 210+ return this;
 211+ };
 212+
 213+})( window.jQuery, window.mediaWiki );
Property changes on: trunk/extensions/SemanticImageInput/resources/jquery.instantImage.js
___________________________________________________________________
Added: svn:eol-style
1214 + native
Index: trunk/extensions/SemanticImageInput/SemanticImageInput.settings.php
@@ -0,0 +1,75 @@
 2+<?php
 3+
 4+/**
 5+ * File defining the settings for the Semantic Image Input extension.
 6+ *
 7+ * NOTICE:
 8+ * Changing one of these settings can be done by assigning to $egSIISettings,
 9+ * AFTER the inclusion of the extension itself.
 10+ *
 11+ * @since 0.1
 12+ *
 13+ * @file SemanticImageInput.settings.php
 14+ * @ingroup SII
 15+ *
 16+ * @licence GNU GPL v3+
 17+ * @author Jeroen De Dauw < jeroendedauw@gmail.com >
 18+ */
 19+class SIISettings {
 20+
 21+ /**
 22+ * Returns the default values for the settings.
 23+ * setting name (string) => setting value (mixed)
 24+ *
 25+ * @since 0.1
 26+ *
 27+ * @return array
 28+ */
 29+ protected static function getDefaultSettings() {
 30+ return array(
 31+ );
 32+ }
 33+
 34+ /**
 35+ * Retruns an array with all settings after making sure they are
 36+ * initialized (ie set settings have been merged with the defaults).
 37+ * setting name (string) => setting value (mixed)
 38+ *
 39+ * @since 0.1
 40+ *
 41+ * @return array
 42+ */
 43+ public static function getSettings() {
 44+ static $settings = false;
 45+
 46+ if ( $settings === false ) {
 47+ $settings = array_merge(
 48+ self::getDefaultSettings(),
 49+ $GLOBALS['egSIISettings']
 50+ );
 51+ }
 52+
 53+ return $settings;
 54+ }
 55+
 56+ /**
 57+ * Gets the value of the specified setting.
 58+ *
 59+ * @since 0.1
 60+ *
 61+ * @param string $settingName
 62+ *
 63+ * @throws MWException
 64+ * @return mixed
 65+ */
 66+ public static function get( $settingName ) {
 67+ $settings = self::getSettings();
 68+
 69+ if ( !array_key_exists( $settingName, $settings ) ) {
 70+ throw new MWException( 'Attempt to get non-existing setting "' . $settingName . '"' );
 71+ }
 72+
 73+ return $settings[$settingName];
 74+ }
 75+
 76+}
Property changes on: trunk/extensions/SemanticImageInput/SemanticImageInput.settings.php
___________________________________________________________________
Added: svn:eol-style
177 + native
Index: trunk/extensions/SemanticImageInput/SemanticImageInput.i18.php
@@ -0,0 +1,24 @@
 2+<?php
 3+
 4+/**
 5+ * Internationalization file for the Semantic Image Input extension.
 6+ *
 7+ * @since 0.1
 8+ *
 9+ * @file SemanticImageInput.i18n.php
 10+ * @ingroup SII
 11+ *
 12+ * @licence GNU GPL v3+
 13+ * @author Jeroen De Dauw < jeroendedauw@gmail.com >
 14+ */
 15+
 16+$messages = array();
 17+
 18+/** English
 19+ * @author Jeroen De Dauw
 20+ */
 21+$messages['en'] = array(
 22+ 'sii-desc' => 'Adds an image input that pulls images from Wikipedia to [https://www.mediawiki.org/wiki/Extension:Semantic_Forms Semantic Forms].',
 23+
 24+ 'sii-imageinput-loading' => 'Loading image...'
 25+);
Property changes on: trunk/extensions/SemanticImageInput/SemanticImageInput.i18.php
___________________________________________________________________
Added: svn:eol-style
126 + native
Index: trunk/extensions/SemanticImageInput/SemanticImageInput.php
@@ -0,0 +1,78 @@
 2+<?php
 3+
 4+/**
 5+ * Initialization file for the Semantic Image Input extension.
 6+ *
 7+ * @file SemanticImageInput.php
 8+ * @ingroup SII
 9+ *
 10+ * @licence GNU GPL v3+
 11+ * @author Jeroen De Dauw < jeroendedauw@gmail.com >
 12+ */
 13+
 14+/**
 15+ * This documentation group collects source code files belonging to Semantic Image Input.
 16+ *
 17+ * @defgroup SII Semantic Image Input
 18+ */
 19+
 20+if ( !defined( 'MEDIAWIKI' ) ) {
 21+ die( 'Not an entry point.' );
 22+}
 23+
 24+if ( version_compare( $wgVersion, '1.17c', '<' ) ) { // Needs to be 1.17c because version_compare() works in confusing ways
 25+ die( '<b>Error:</b> Semantic Image Input requires MediaWiki 1.17 or above.' );
 26+}
 27+
 28+// Show an error if Semantic MediaWiki is not loaded.
 29+if ( ! defined( 'SMW_VERSION' ) ) {
 30+ die( '<b>Error:</b> You need to have <a href="http://semantic-mediawiki.org/wiki/Semantic_MediaWiki">Semantic MediaWiki</a> installed in order to use Semantic Image Input.<br />' );
 31+}
 32+
 33+// Show an error if Semantic MediaWiki is not loaded.
 34+if ( ! defined( 'SF_VERSION' ) ) {
 35+ die( '<b>Error:</b> You need to have <a href="https://www.mediawiki.org/wiki/Extension:Semantic_Forms">Semantic Forms</a> installed in order to use Semantic Image Input.<br />' );
 36+}
 37+
 38+define( 'SII_VERSION', '0.1 alpha' );
 39+
 40+$wgExtensionCredits['semantic'][] = array(
 41+ 'path' => __FILE__,
 42+ 'name' => 'Semantic Image Input',
 43+ 'version' => SII_VERSION,
 44+ 'author' => array(
 45+ '[http://www.mediawiki.org/wiki/User:Jeroen_De_Dauw Jeroen De Dauw]',
 46+ ),
 47+ 'url' => 'https://www.mediawiki.org/wiki/Extension:Semantic_Image_input',
 48+ 'descriptionmsg' => 'sii-desc'
 49+);
 50+
 51+// i18n
 52+$wgExtensionMessagesFiles['SII'] = dirname( __FILE__ ) . '/SemanticImageInput.i18n.php';
 53+
 54+// Autoloading
 55+$wgAutoloadClasses['SIISettings'] = dirname( __FILE__ ) . '/SemanticImageInput.settings.php';
 56+
 57+$wgAutoloadClasses['InstantImageInput'] = dirname( __FILE__ ) . '/includes/InstantImageInput.php';
 58+
 59+$wgExtensionFunctions[] = function() {
 60+ global $sfgFormPrinter;
 61+ $sfgFormPrinter->registerInputType( 'WikiImageInput' );
 62+};
 63+
 64+// Resource loader modules
 65+$moduleTemplate = array(
 66+ 'localBasePath' => dirname( __FILE__ ) . '/resources',
 67+ 'remoteExtPath' => 'SemanticImageInput/resources'
 68+);
 69+
 70+$wgResourceModules['sii.image'] = $moduleTemplate + array(
 71+ 'scripts' => array(
 72+ 'jquery.instantImage.js',
 73+ 'sii.instantImage.js'
 74+ ),
 75+);
 76+
 77+unset( $moduleTemplate );
 78+
 79+$egSIISettings = array();
Property changes on: trunk/extensions/SemanticImageInput/SemanticImageInput.php
___________________________________________________________________
Added: svn:eol-style
180 + native

Follow-up revisions

RevisionCommit summaryAuthorDate
r102400r102386: Consistency tweaks in preparation for adding extension to translatew...raymond14:31, 8 November 2011
r102401r102386: Adding extension to translatewiki.netraymond14:32, 8 November 2011
r102402r102386: Fix file nameraymond14:36, 8 November 2011

Comments

#Comment by Nikerabbit (talk | contribs)   11:08, 8 November 2011

Will this work with images from the local wiki at some point too?

#Comment by Jeroen De Dauw (talk | contribs)   14:53, 8 November 2011

Err.. I don't quite see why you'd want to put the first image of a page on that same page, and if you'd want to do that, there are easier ways.

However, I think I'd be cool if this supported other repos/wikis as well. Esp if an input that actually allows you to choose the image (the current one gives you no control at all (by design)).

In any case, I copied this from a custom extension I wrote for some client, and it probably needs some fixing before it actually works (I still have to test it, but that's for tomorrow).

#Comment by Nikerabbit (talk | contribs)   15:02, 8 November 2011

Maybe I misunderstood what this extension does.