Index: trunk/extensions/WikiLove/WikiLove.php |
— | — | @@ -45,6 +45,11 @@ |
46 | 46 | 'descriptionmsg' => 'wikilove-desc', |
47 | 47 | ); |
48 | 48 | |
| 49 | +// default user options |
| 50 | +$wgWikiLoveGlobal = false; // enable the extension for all users, removing the user preference |
| 51 | +$wgWikiLoveTabIcon = true; // use an icon for skins that support them (i.e. Vector) |
| 52 | +$wgWikiLoveLogging = false; // enable logging of giving of WikiLove |
| 53 | + |
49 | 54 | // current directory including trailing slash |
50 | 55 | $dir = dirname( __FILE__ ) . '/'; |
51 | 56 | |
— | — | @@ -60,17 +65,11 @@ |
61 | 66 | $wgHooks['SkinTemplateNavigation'][] = 'WikiLoveHooks::skinTemplateNavigation'; |
62 | 67 | $wgHooks['SkinTemplateTabs'][] = 'WikiLoveHooks::skinTemplateTabs'; |
63 | 68 | $wgHooks['BeforePageDisplay'][] = 'WikiLoveHooks::beforePageDisplay'; |
64 | | -//$wgHooks['LoadExtensionSchemaUpdates'][] = 'WikiLoveHooks::loadExtensionSchemaUpdates'; |
65 | | -// Not a final schema, please apply patches/WikiLoveLog.sql manually for now! |
| 69 | +$wgHooks['LoadExtensionSchemaUpdates'][] = 'WikiLoveHooks::loadExtensionSchemaUpdates'; |
66 | 70 | |
67 | 71 | // api modules |
68 | | -$wgAPIModules['wikiLove'] = 'WikiLoveApi'; |
| 72 | +$wgAPIModules['wikilove'] = 'WikiLoveApi'; |
69 | 73 | |
70 | | -// default user options |
71 | | -$wgWikiLoveGlobal = false; |
72 | | -$wgWikiLoveTabIcon = true; |
73 | | -$wgWikiLoveLogging = false; |
74 | | - |
75 | 74 | // resources |
76 | 75 | $wikiLoveTpl = array( |
77 | 76 | 'localBasePath' => dirname( __FILE__ ), |
— | — | @@ -100,6 +99,7 @@ |
101 | 100 | 'wikilove-omit-sig', |
102 | 101 | 'wikilove-button-preview', |
103 | 102 | 'wikilove-preview', |
| 103 | + 'wikilove-notify', |
104 | 104 | 'wikilove-button-send', |
105 | 105 | 'wikilove-type-makeyourown', |
106 | 106 | 'wikilove-err-header', |
— | — | @@ -113,6 +113,7 @@ |
114 | 114 | 'jquery.ui.dialog', |
115 | 115 | 'jquery.ui.button', |
116 | 116 | 'jquery.elastic', |
| 117 | + 'jquery.localize', |
117 | 118 | ), |
118 | 119 | ), |
119 | 120 | 'jquery.elastic' => $wikiLoveTpl + array( |
Index: trunk/extensions/WikiLove/defaultTypes.js |
— | — | @@ -2,44 +2,45 @@ |
3 | 3 | // example type, could be removed later (also no i18n) |
4 | 4 | 'barnstar': { |
5 | 5 | name: 'Barnstar', // name of the type (appears in the types menu) |
6 | | - fields: [ 'header', 'title', 'image' ], // fields to ask for in form if not specified in config |
7 | 6 | select: 'Select a barnstar:', // subtype select label |
8 | 7 | subtypes: { // some different subtypes |
9 | 8 | // note that when not using subtypes you should use these subtype options |
10 | 9 | // for the top-level type |
11 | 10 | 'original': { |
| 11 | + fields: [ 'notify' ], // fields to ask for in form |
12 | 12 | option: 'Original barnstar', // option listed in the select list |
13 | 13 | descr: 'This barnstar is given to recognize particularly fine contributions to Wikipedia, to let people know that their hard work is seen and appreciated.', // description |
14 | | - header: mw.msg( 'wikilove-barnstar-header' ), // header that appears at the top of the talk page post (optional) |
| 14 | + header: 'A barnstar for you!', // header that appears at the top of the talk page post (optional) |
15 | 15 | title: 'The Original Barnstar', // title that appears inside the award box (optional) |
16 | 16 | image: 'Original Barnstar Hires.png', // image for the award |
17 | 17 | mail: 'Hello $7!\n\nI just awarded you a barnstar.' // message to use in email notification; $7 is replaced by the recipient's username |
18 | 18 | }, |
19 | 19 | 'editors': { |
| 20 | + fields: [ 'notify' ], |
20 | 21 | option: 'Editor\'s barnstar', |
21 | 22 | descr: 'The Editor\'s Barnstar is awarded to individuals who display particularly fine decisions in general editing.', |
22 | | - header: mw.msg( 'wikilove-barnstar-header' ), |
| 23 | + header: 'A barnstar for you!', |
23 | 24 | title: 'The Editor\'s Barnstar', |
24 | 25 | image: 'Editors Barnstar Hires.png', |
25 | 26 | mail: 'Hello $7!\n\nI just awarded you a barnstar.' |
26 | 27 | }, |
27 | 28 | 'tireless': { |
| 29 | + fields: [ 'title', 'notify' ], |
28 | 30 | option: 'Tireless contributor barnstar', |
29 | 31 | descr: 'The Tireless Contributor Barnstar is awarded to especially tireless Wikipedians who contribute an especially large body of work without sacrificing quality.', |
30 | | - header: mw.msg( 'wikilove-barnstar-header' ), |
31 | | - title: 'The Editor\'s Barnstar', |
| 32 | + header: 'A barnstar for you!', |
| 33 | + title: 'Tireless contributor barnstar', |
32 | 34 | image: 'Tireless Contributor Barnstar Hires.gif', |
33 | 35 | mail: 'Hello $7!\n\nI just awarded you a barnstar.' |
34 | 36 | } |
35 | 37 | }, |
36 | | - showNotify: true, // add email notices as an option for each award of this type |
37 | 38 | icon: mw.config.get( 'wgServer' ) + mw.config.get( 'wgScriptPath' ) + '/extensions/WikiLove/images/icons/wikilove-icon-barnstar.png' // icon for left-side menu |
38 | 39 | }, |
39 | 40 | 'cats': { |
40 | 41 | name: 'Cat', |
41 | 42 | fields: [ 'header' ], |
42 | 43 | header: 'A kitten for you!', |
43 | | - text: '[[$3|left|150px]]\n$1\n\n~~~~\n<br style="clear: both"/>', // $3 is the image filename |
| 44 | + text: '[[$3|left|150px]]\n$1\n\n~~~~\n<br style="clear: both"/>', // custom text |
44 | 45 | gallery: { |
45 | 46 | // right now we can only query the local wiki (not e.g. commons) |
46 | 47 | category: 'Category:Cats', |
— | — | @@ -51,7 +52,7 @@ |
52 | 53 | // default type, nice to leave this one in place when adding other types |
53 | 54 | 'makeyourown': { |
54 | 55 | name: mw.msg( 'wikilove-type-makeyourown' ), |
55 | | - fields: [ 'header', 'title', 'image' ], |
| 56 | + fields: [ 'header', 'title', 'image', 'notify' ], |
56 | 57 | imageSize: '150px' |
57 | 58 | } |
58 | 59 | } |
\ No newline at end of file |
Index: trunk/extensions/WikiLove/wikiLove.js |
— | — | @@ -1,3 +1,4 @@ |
| 2 | +var mw; |
2 | 3 | ( function( $ ) { $.wikiLove = { |
3 | 4 | |
4 | 5 | $dialog: null, // dialog jQuery object |
— | — | @@ -24,112 +25,116 @@ |
25 | 26 | if ( $.wikiLove.$dialog === null ) { |
26 | 27 | // Load local configuration |
27 | 28 | var wikiLoveConfigUrl = wgServer + wgScript + '?' + $.param( { 'title': 'MediaWiki:WikiLove.js', 'action': 'raw', 'ctype': 'text/javascript' } ); |
28 | | - mw.loader.load( wikiLoveConfigUrl ); |
29 | | - |
30 | | - // Find out if we can email the user |
31 | | - $.wikiLove.getEmailable(); |
32 | | - |
33 | | - // Reusable spinner string |
34 | | - var spinner = '<img class="wlSpinner" src="' + mw.config.get( 'wgServer' ) + mw.config.get( 'wgScriptPath' ) |
35 | | - + '/extensions/WikiLove/images/spinner.gif"/>'; |
36 | | - |
37 | | - // Build a type list like this: |
38 | | - var $typeList = $( '<ul id="wlTypes"></ul>' ); |
39 | | - for( var typeId in $.wikiLove.types ) { |
40 | | - $button = $( '<a href="#"></a>' ); |
41 | | - $buttonInside = $( '<div class="wlInside"></div>' ); |
| 29 | + $.getScript( wikiLoveConfigUrl, function() { |
| 30 | + // Test to see if the 'E-mail this user' link exists |
| 31 | + $.wikiLove.emailable = $( '#t-emailuser' ).length ? true : false; |
42 | 32 | |
43 | | - if( typeof $.wikiLove.types[typeId].icon == 'string' ) { |
44 | | - $buttonInside.append( '<div class="wlIconBox"><img src="' |
45 | | - + $.wikiLove.types[typeId].icon + '"/></div>' ); |
| 33 | + // Reusable spinner string |
| 34 | + var spinner = '<img class="wlSpinner" src="' + mw.config.get( 'wgServer' ) + mw.config.get( 'wgScriptPath' ) + '/extensions/WikiLove/images/spinner.gif' + '"/>'; |
| 35 | + |
| 36 | + // Build a type list like this: |
| 37 | + var $typeList = $( '<ul id="wlTypes"></ul>' ); |
| 38 | + for( var typeId in $.wikiLove.types ) { |
| 39 | + var $button = $( '<a href="#"></a>' ); |
| 40 | + var $buttonInside = $( '<div class="wlInside"></div>' ); |
| 41 | + |
| 42 | + if( typeof $.wikiLove.types[typeId].icon == 'string' ) { |
| 43 | + $buttonInside.append( '<div class="wlIconBox"><img src="' |
| 44 | + + mw.html.escape( $.wikiLove.types[typeId].icon ) + '"/></div>' ); |
| 45 | + } |
| 46 | + else { |
| 47 | + $buttonInside.addClass( 'wlNoIcon' ); |
| 48 | + } |
| 49 | + |
| 50 | + $buttonInside.append( '<div class="wlLinkText">' + $.wikiLove.types[typeId].name + '</div>' ); |
| 51 | + |
| 52 | + $button.append( '<div class="wlLeftCap"></div>'); |
| 53 | + $button.append( $buttonInside ); |
| 54 | + $button.append( '<div class="wlRightCap"></div>'); |
| 55 | + $button.data( 'typeId', typeId ); |
| 56 | + $typeList.append( $( '<li tabindex="0"></li>' ).append( $button ) ); |
46 | 57 | } |
47 | | - else { |
48 | | - $buttonInside.addClass( 'wlNoIcon' ); |
49 | | - } |
50 | 58 | |
51 | | - $buttonInside.append( '<div class="wlLinkText">' + $.wikiLove.types[typeId].name + '</div>' ); |
| 59 | + $.wikiLove.$dialog = $( '\ |
| 60 | +<div id="wikiLoveDialog">\ |
| 61 | + <div id="wlSelectType">\ |
| 62 | + <span class="wlNumber">1</span>\ |
| 63 | + <h3><html:msg key="wikilove-select-type"/></h3>\ |
| 64 | + <ul id="wlTypes"></ul>\ |
| 65 | + </div>\ |
| 66 | + <div id="wlGetStarted">\ |
| 67 | + <h2><html:msg key="wikilove-get-started-header"/></h2>\ |
| 68 | + <ol>\ |
| 69 | + <li><html:msg key="wikilove-get-started-list-1"/></li>\ |
| 70 | + <li><html:msg key="wikilove-get-started-list-2"/></li>\ |
| 71 | + <li><html:msg key="wikilove-get-started-list-3"/></li>\ |
| 72 | + </ol>\ |
| 73 | + </div>\ |
| 74 | + <div id="wlAddDetails">\ |
| 75 | + <span class="wlNumber">2</span>\ |
| 76 | + <h3><html:msg key="wikilove-add-details"/></h3>\ |
| 77 | + <form id="wlPreviewForm">\ |
| 78 | + <label for="wlSubtype" id="wlSubtypeLabel"></label>\ |
| 79 | + <select id="wlSubtype"></select>\ |
| 80 | + <div id="wlSubtypeDescription"></div>\ |
| 81 | + <label id="wlGalleryLabel"><html:msg key="wikilove-image"/></label>\ |
| 82 | + <div id="wlGallerySpinner">' + spinner + '</div>\ |
| 83 | + <div id="wlGallery"></div>\ |
| 84 | + <label for="wlHeader" id="wlHeaderLabel"><html:msg key="wikilove-header"/></label>\ |
| 85 | + <input type="text" class="text" id="wlHeader"/>\ |
| 86 | + <label for="wlTitle" id="wlTitleLabel"><html:msg key="wikilove-title"/></label>\ |
| 87 | + <input type="text" class="text" id="wlTitle"/>\ |
| 88 | + <label for="wlImage" id="wlImageLabel"><html:msg key="wikilove-image"/></label>\ |
| 89 | + <input type="text" class="text" id="wlImage"/>\ |
| 90 | + <label for="wlMessage" id="wlMessageLabel"><html:msg key="wikilove-enter-message"/></label>\ |
| 91 | + <span class="wlNote"><html:msg key="wikilove-omit-sig"/></span>\ |
| 92 | + <textarea id="wlMessage"></textarea>\ |
| 93 | + <div id="wlNotify">\ |
| 94 | + <input type="checkbox" id="wlNotifyCheckbox" name="notify"/>\ |
| 95 | + <label for="wlNotifyCheckbox"><html:msg key="wikilove-notify"/></label>\ |
| 96 | + </div>\ |
| 97 | + <button class="submit" id="wlButtonPreview" type="submit"></button>\ |
| 98 | + ' + spinner + '\ |
| 99 | + </form>\ |
| 100 | + </div>\ |
| 101 | + <div id="wlPreview">\ |
| 102 | + <span class="wlNumber">3</span>\ |
| 103 | + <h3><html:msg key="wikilove-preview"/></h3>\ |
| 104 | + <div id="wlPreviewArea"></div>\ |
| 105 | + <form id="wlSendForm">\ |
| 106 | + <button class="submit" id="wlButtonSend" type="submit"></button>\ |
| 107 | + ' + spinner + '\ |
| 108 | + </form>\ |
| 109 | + </div>\ |
| 110 | +</div>' ); |
| 111 | + $.wikiLove.$dialog.localize(); |
52 | 112 | |
53 | | - $button.append( '<div class="wlLeftCap"></div>'); |
54 | | - $button.append( $buttonInside ); |
55 | | - $button.append( '<div class="wlRightCap"></div>'); |
56 | | - $button.data( 'typeId', typeId ); |
57 | | - $typeList.append( $( '<li tabindex="0"></li>' ).append( $button ) ); |
58 | | - } |
59 | | - |
60 | | - // Build the left menu for selecting a type: |
61 | | - var $selectType = $( '<div id="wlSelectType"></div>' ) |
62 | | - .append( '<span class="wlNumber">1</span>' ) |
63 | | - .append( '<h3>' + mw.msg( 'wikilove-select-type' ) + '</h3>' ) |
64 | | - .append( $typeList ); |
| 113 | + $.wikiLove.$dialog.dialog({ |
| 114 | + width: 800, |
| 115 | + position: ['center', 80], |
| 116 | + autoOpen: false, |
| 117 | + title: mw.msg( 'wikilove-dialog-title' ), |
| 118 | + modal: true, |
| 119 | + resizable: false |
| 120 | + }); |
65 | 121 | |
66 | | - var $getStarted = $( '<div id="wlGetStarted"></div>' ) |
67 | | - .append( '<h2>' + mw.msg( 'wikilove-get-started-header' ) + '</h2>' ) |
68 | | - .append( $( '<ol></ol>' ) |
69 | | - .append( '<li>' + mw.msg( 'wikilove-get-started-list-1' ) + '</li>' ) |
70 | | - .append( '<li>' + mw.msg( 'wikilove-get-started-list-2' ) + '</li>' ) |
71 | | - .append( '<li>' + mw.msg( 'wikilove-get-started-list-3' ) + '</li>' ) |
72 | | - ); |
73 | | - |
74 | | - // Build the right top section for selecting a subtype and entering a title (optional) and message |
75 | | - var $addDetails = $( '<div id="wlAddDetails"></div>' ) |
76 | | - .append( '<span class="wlNumber">2</span>' ) |
77 | | - .append( '<h3>' + mw.msg( 'wikilove-add-details' ) + '</h3>' ) |
78 | | - .append( $( '<form id="wlPreviewForm"></form>' ) |
79 | | - .append( '<label for="wlSubtype" id="wlSubtypeLabel"></label>' ) |
80 | | - .append( '<select id="wlSubtype"></select>' ) |
81 | | - .append( '<div id="wlSubtypeDescription"/>' ) |
82 | | - .append( '<label id="wlGalleryLabel">' + mw.msg( 'wikilove-image' ) + '</label>' ) |
83 | | - .append( '<div id="wlGallerySpinner">' + spinner + '</div>' ) |
84 | | - .append( '<div id="wlGallery"/>' ) |
85 | | - .append( '<label for="wlHeader" id="wlHeaderLabel">' + mw.msg( 'wikilove-header' ) + '</label>' ) |
86 | | - .append( '<input type="text" class="text" id="wlHeader"/>' ) |
87 | | - .append( '<label for="wlTitle" id="wlTitleLabel">' + mw.msg( 'wikilove-title' ) + '</label>' ) |
88 | | - .append( '<input type="text" class="text" id="wlTitle"/>' ) |
89 | | - .append( '<label for="wlImage" id="wlImageLabel">' + mw.msg( 'wikilove-image' ) + '</label>' ) |
90 | | - .append( '<input type="text" class="text" id="wlImage"/>' ) |
91 | | - .append( '<label for="wlMessage" id="wlMessageLabel">' + mw.msg( 'wikilove-enter-message' ) + '</label>' ) |
92 | | - .append( '<span class="wlNote">' + mw.msg( 'wikilove-omit-sig' ) + '</span>' ) |
93 | | - .append( '<textarea id="wlMessage"></textarea>' ) |
94 | | - .append( $('<div id="wlNotify"></div>').html('<input type="checkbox" id="wlNotifyCheckbox" name="notify"/> <label for="wlNotifyCheckbox">Notify user by email</label>') ) |
95 | | - .append( $('<button class="submit" id="wlButtonPreview" type="submit"></button>').button({ label: mw.msg( 'wikilove-button-preview' ), icons: { primary:'ui-icon-search' } }) ) |
96 | | - .append( spinner ) |
97 | | - ) |
98 | | - .hide(); |
99 | | - |
100 | | - // Build the right bottom preview section |
101 | | - var $preview = $( '<div id="wlPreview"></div>' ) |
102 | | - .append( '<span class="wlNumber">3</span>' ) |
103 | | - .append( '<h3>' + mw.msg( 'wikilove-preview' ) + '</h3>' ) |
104 | | - .append( '<div id="wlPreviewArea"></div>' ) |
105 | | - .append( $( '<form id="wlSendForm"></form>' ) |
106 | | - .append( $('<button class="submit" id="wlButtonSend" type="submit"></button>').button({ label: mw.msg( 'wikilove-button-send' ) }) ) |
107 | | - .append( spinner ) |
108 | | - ) |
109 | | - .hide(); |
110 | | - |
111 | | - // Build a modal, hidden dialog with the 3 different sections |
112 | | - $.wikiLove.$dialog = $( '<div id="wikiLoveDialog"></div>' ) |
113 | | - .append( $selectType ) |
114 | | - .append( $getStarted ) |
115 | | - .append( $addDetails ) |
116 | | - .append( $preview ) |
117 | | - .dialog({ |
118 | | - width: 800, |
119 | | - position: ['center', 80], |
120 | | - autoOpen: false, |
121 | | - title: mw.msg( 'wikilove-dialog-title' ), |
122 | | - modal: true, |
123 | | - resizable: false |
124 | | - }); |
125 | | - |
126 | | - $( '#wlTypes a' ).click( $.wikiLove.clickType ); |
127 | | - $( '#wlSubtype' ).change( $.wikiLove.changeSubtype ); |
128 | | - $( '#wlPreviewForm' ).submit( $.wikiLove.submitPreview ); |
129 | | - $( '#wlSendForm' ).click( $.wikiLove.submitSend ); |
130 | | - $( '#wlMessage' ).elastic(); // have the message textarea grow automatically |
| 122 | + $( '#wlButtonPreview' ).button( { label: mw.msg( 'wikilove-button-preview' ), icons: { primary:'ui-icon-search' } } ); |
| 123 | + $( '#wlButtonSend' ).button( { label: mw.msg( 'wikilove-button-send' ) } ); |
| 124 | + $( '#wlAddDetails' ).hide(); |
| 125 | + $( '#wlPreview' ).hide(); |
| 126 | + $( '#wlTypes' ).replaceWith( $typeList ); |
| 127 | + |
| 128 | + $( '#wlTypes a' ).click( $.wikiLove.clickType ); |
| 129 | + $( '#wlSubtype' ).change( $.wikiLove.changeSubtype ); |
| 130 | + $( '#wlPreviewForm' ).submit( $.wikiLove.submitPreview ); |
| 131 | + $( '#wlSendForm' ).click( $.wikiLove.submitSend ); |
| 132 | + $( '#wlMessage' ).elastic(); // have the message textarea grow automatically |
| 133 | + |
| 134 | + $.wikiLove.$dialog.dialog( 'open' ); |
| 135 | + }); |
| 136 | + } else { |
| 137 | + $.wikiLove.$dialog.dialog( 'open' ); |
131 | 138 | } |
132 | | - |
133 | | - $.wikiLove.$dialog.dialog( 'open' ); |
134 | 139 | }, |
135 | 140 | |
136 | 141 | /* |
— | — | @@ -157,13 +162,13 @@ |
158 | 163 | // add all the subtypes to the menu while setting their subtype ids in jQuery data |
159 | 164 | var subtype = $.wikiLove.types[$.wikiLove.currentTypeId].subtypes[subtypeId]; |
160 | 165 | $( '#wlSubtype' ).append( |
161 | | - $( '<option>' + subtype.option + '</option>' ).data( 'subtypeId', subtypeId ) |
| 166 | + $( '<option></option>' ).text( subtype.option ).data( 'subtypeId', subtypeId ) |
162 | 167 | ); |
163 | 168 | } |
164 | 169 | $( '#wlSubtype' ).show(); |
165 | 170 | |
166 | 171 | // change and show the subtype label depending on the type |
167 | | - $( '#wlSubtypeLabel' ).text( $.wikiLove.types[$.wikiLove.currentTypeId].select ); |
| 172 | + $( '#wlSubtypeLabel' ).text( $.wikiLove.types[$.wikiLove.currentTypeId].select || mw.msg( 'wikilove-select-type' ) ); |
168 | 173 | $( '#wlSubtypeLabel' ).show(); |
169 | 174 | $.wikiLove.changeSubtype(); // update controls depending on the currently selected (i.e. first) subtype |
170 | 175 | } |
— | — | @@ -200,33 +205,6 @@ |
201 | 206 | }, |
202 | 207 | |
203 | 208 | /* |
204 | | - * Find out whether we can e-mail this user. Probably needs to be moved to the API. |
205 | | - */ |
206 | | - getEmailable: function() { |
207 | | - // Test to see if the 'E-mail this user' link exists |
208 | | - $.wikiLove.emailable = $('#t-emailuser').length ? true : false; |
209 | | - }, |
210 | | - |
211 | | - /* |
212 | | - * Actually send the notification e-mail. Probably needs to be moved to the API. |
213 | | - */ |
214 | | - sendEmail: function( subject, text ) { |
215 | | - $.ajax({ |
216 | | - url: mw.util.wikiScript( 'api' ), |
217 | | - data: { |
218 | | - 'action': 'emailuser', |
219 | | - 'target': wgTitle, |
220 | | - 'subject': subject, |
221 | | - 'text': text, |
222 | | - 'format': 'json', |
223 | | - 'token': mw.user.tokens.get( 'editToken' ) |
224 | | - }, |
225 | | - dataType: 'json', |
226 | | - type: 'POST' |
227 | | - }); |
228 | | - }, |
229 | | - |
230 | | - /* |
231 | 209 | * Called when type or subtype changes, updates controls. |
232 | 210 | */ |
233 | 211 | updateAllDetails: function() { |
— | — | @@ -240,40 +218,34 @@ |
241 | 219 | } |
242 | 220 | |
243 | 221 | // show or hide header label and textbox depending on whether a predefined header exists |
244 | | - var needsHeader = $.inArray( 'header', $.wikiLove.types[$.wikiLove.currentTypeId].fields ); |
245 | | - if( typeof $.wikiLove.currentTypeOrSubtype.header == 'string' || needsHeader == -1 ) { |
246 | | - $( '#wlHeaderLabel').hide(); |
247 | | - $( '#wlHeader' ).hide(); |
248 | | - $( '#wlHeader' ).val( $.wikiLove.currentTypeOrSubtype.header ); |
249 | | - } else if ( needsHeader != -1 ) { |
| 222 | + if( $.inArray( 'header', $.wikiLove.currentTypeOrSubtype.fields ) >= 0 ) { |
250 | 223 | $( '#wlHeaderLabel').show(); |
251 | 224 | $( '#wlHeader' ).show(); |
252 | | - $( '#wlHeader' ).val( '' ); |
| 225 | + } else { |
| 226 | + $( '#wlHeaderLabel').hide(); |
| 227 | + $( '#wlHeader' ).hide(); |
253 | 228 | } |
| 229 | + $( '#wlHeader' ).val( $.wikiLove.currentTypeOrSubtype.header || '' ); |
254 | 230 | |
255 | 231 | // show or hide title label and textbox depending on whether a predefined title exists |
256 | | - var needsTitle = $.inArray( 'title', $.wikiLove.types[$.wikiLove.currentTypeId].fields ); |
257 | | - if( typeof $.wikiLove.currentTypeOrSubtype.title == 'string' || needsTitle == -1 ) { |
258 | | - $( '#wlTitleLabel').hide(); |
259 | | - $( '#wlTitle' ).hide(); |
260 | | - $( '#wlTitle' ).val( $.wikiLove.currentTypeOrSubtype.title ); |
261 | | - } else if ( needsTitle != -1 ) { |
| 232 | + if( $.inArray( 'title', $.wikiLove.currentTypeOrSubtype.fields ) >= 0 ) { |
262 | 233 | $( '#wlTitleLabel').show(); |
263 | 234 | $( '#wlTitle' ).show(); |
264 | | - $( '#wlTitle' ).val( '' ); |
| 235 | + } else { |
| 236 | + $( '#wlTitleLabel').hide(); |
| 237 | + $( '#wlTitle' ).hide(); |
265 | 238 | } |
| 239 | + $( '#wlTitle' ).val( $.wikiLove.currentTypeOrSubtype.title || '' ); |
266 | 240 | |
267 | 241 | // show or hide image label and textbox depending on whether a predefined image exists |
268 | | - var needsTitle = $.inArray( 'image', $.wikiLove.types[$.wikiLove.currentTypeId].fields ); |
269 | | - if( typeof $.wikiLove.currentTypeOrSubtype.image == 'string' || needsTitle == -1 ) { |
270 | | - $( '#wlImageLabel').hide(); |
271 | | - $( '#wlImage' ).hide(); |
272 | | - $( '#wlImage' ).val( $.wikiLove.currentTypeOrSubtype.image ); |
273 | | - } else if ( needsTitle != -1 ) { |
| 242 | + if( $.inArray( 'image', $.wikiLove.currentTypeOrSubtype.fields ) >= 0 ) { |
274 | 243 | $( '#wlImageLabel').show(); |
275 | 244 | $( '#wlImage' ).show(); |
276 | | - $( '#wlImage' ).val( '' ); |
| 245 | + } else { |
| 246 | + $( '#wlImageLabel').hide(); |
| 247 | + $( '#wlImage' ).hide(); |
277 | 248 | } |
| 249 | + $( '#wlImage' ).val( $.wikiLove.currentTypeOrSubtype.image || '' ); |
278 | 250 | |
279 | 251 | if( typeof $.wikiLove.currentTypeOrSubtype.gallery == 'object' ) { |
280 | 252 | $( '#wlGalleryLabel' ).show(); |
— | — | @@ -287,7 +259,7 @@ |
288 | 260 | $( '#wlGallerySpinner' ).hide(); |
289 | 261 | } |
290 | 262 | |
291 | | - if( $.wikiLove.types[$.wikiLove.currentTypeId].showNotify ) { |
| 263 | + if( $.inArray( 'notify', $.wikiLove.currentTypeOrSubtype.fields ) >= 0 && $.wikiLove.emailable ) { |
292 | 264 | $( '#wlNotify' ).show(); |
293 | 265 | } else { |
294 | 266 | $( '#wlNotify' ).hide(); |
— | — | @@ -320,13 +292,8 @@ |
321 | 293 | $.wikiLove.showError( 'wikilove-err-sig' ); return false; |
322 | 294 | } |
323 | 295 | |
324 | | - if ( $.wikiLove.currentTypeOrSubtype.text ) { |
325 | | - var text = $.wikiLove.currentTypeOrSubtype.text; |
326 | | - } else { |
327 | | - var text = $.wikiLove.defaultText; |
328 | | - } |
329 | 296 | var msg = $.wikiLove.prepareMsg( |
330 | | - text, |
| 297 | + $.wikiLove.currentTypeOrSubtype.text || $.wikiLove.defaultText, |
331 | 298 | $.wikiLove.currentTypeOrSubtype.imageSize, |
332 | 299 | $.wikiLove.currentTypeOrSubtype.backgroundColor, |
333 | 300 | $.wikiLove.currentTypeOrSubtype.borderColor |
— | — | @@ -337,14 +304,17 @@ |
338 | 305 | 'header': $( '#wlHeader' ).val(), |
339 | 306 | 'msg': msg, |
340 | 307 | 'type': $.wikiLove.currentTypeId |
341 | | - + ($.wikiLove.currentSubtypeId != null ? '-' + $.wikiLove.currentSubtypeId : ''), |
342 | | - 'notify': $( '#wlNotifyCheckbox:checked' ).val() |
| 308 | + + ($.wikiLove.currentSubtypeId !== null ? '-' + $.wikiLove.currentSubtypeId : ''), |
343 | 309 | }; |
| 310 | + |
| 311 | + if ( $( '#wlNotifyCheckbox:checked' ).val() && $.wikiLove.emailable ) { |
| 312 | + $.wikiLove.previewData.mail = $.wikiLove.prepareMsg( $.wikiLove.currentTypeOrSubtype.mail ); |
| 313 | + } |
344 | 314 | return false; |
345 | 315 | }, |
346 | 316 | |
347 | 317 | showError: function( errmsg ) { |
348 | | - $( '#wlAddDetails' ).append( $( '<div class="wlError"></div>' ).html( mw.msg( errmsg ) ) ); |
| 318 | + $( '#wlAddDetails' ).append( $( '<div class="wlError"></div>' ).text( mw.msg( errmsg ) ) ); |
349 | 319 | }, |
350 | 320 | |
351 | 321 | /* |
— | — | @@ -363,21 +333,10 @@ |
364 | 334 | msg = msg.replace( '$2', $( '#wlTitle' ).val() ); // replace the title |
365 | 335 | msg = msg.replace( '$3', $( '#wlImage' ).val() ); // replace the image |
366 | 336 | |
367 | | - if ( imageSize ) { |
368 | | - var myImageSize = imageSize; |
369 | | - } else { |
370 | | - var myImageSize = $.wikiLove.defaultImageSize; |
371 | | - } |
372 | | - if ( backgroundColor ) { |
373 | | - var myBackgroundColor = backgroundColor; |
374 | | - } else { |
375 | | - var myBackgroundColor = $.wikiLove.defaultBackgroundColor; |
376 | | - } |
377 | | - if ( borderColor ) { |
378 | | - var myBorderColor = borderColor; |
379 | | - } else { |
380 | | - var myBorderColor = $.wikiLove.defaultBorderColor; |
381 | | - } |
| 337 | + var myImageSize = imageSize || $.wikiLove.defaultImageSize; |
| 338 | + var myBackgroundColor = backgroundColor || $.wikiLove.defaultBackgroundColor; |
| 339 | + var myBorderColor = borderColor || $.wikiLove.defaultBorderColor; |
| 340 | + |
382 | 341 | msg = msg.replace( '$4', myImageSize ); // replace the image size |
383 | 342 | msg = msg.replace( '$5', myBackgroundColor ); // replace the background color |
384 | 343 | msg = msg.replace( '$6', myBorderColor ); // replace the border color |
— | — | @@ -433,33 +392,33 @@ |
434 | 393 | /* |
435 | 394 | * Fires the final AJAX request and then redirects to the talk page where the content is added. |
436 | 395 | */ |
437 | | - doSend: function( subject, wikitext, type, notify ) { |
| 396 | + doSend: function( subject, wikitext, type, mail ) { |
438 | 397 | $( '#wlPreview .wlSpinner' ).fadeIn( 200 ); |
| 398 | + |
| 399 | + var sendData = { |
| 400 | + 'action': 'wikilove', |
| 401 | + 'format': 'json', |
| 402 | + 'title': mw.config.get( 'wgPageName' ), |
| 403 | + 'type': type, |
| 404 | + 'text': wikitext, |
| 405 | + 'subject': subject, |
| 406 | + 'token': mw.user.tokens.get( 'editToken' ) |
| 407 | + }; |
| 408 | + |
| 409 | + if ( mail ) { |
| 410 | + sendData.email = mail; |
| 411 | + } |
| 412 | + |
439 | 413 | $.ajax({ |
440 | 414 | url: mw.config.get( 'wgServer' ) + mw.config.get( 'wgScriptPath' ) + '/api.php?', |
441 | | - data: { |
442 | | - 'action': 'wikiLove', |
443 | | - 'format': 'json', |
444 | | - 'title': mw.config.get( 'wgPageName' ), |
445 | | - 'type': type, |
446 | | - 'text': wikitext, |
447 | | - 'subject': subject, |
448 | | - 'token': mw.user.tokens.get( 'editToken' ) |
449 | | - }, |
| 415 | + data: sendData, |
450 | 416 | dataType: 'json', |
451 | 417 | type: 'POST', |
452 | 418 | success: function( data ) { |
453 | | - if ( notify && $.wikiLove.emailable && typeof $.wikiLove.currentTypeOrSubtype.mail != 'undefined' ) { |
454 | | - $.wikiLove.sendEmail( |
455 | | - $.wikiLove.currentTypeOrSubtype.title, |
456 | | - $.wikiLove.prepareMsg( $.wikiLove.currentTypeOrSubtype.mail ) |
457 | | - ); |
458 | | - } |
459 | | - |
460 | 419 | $( '#wlPreview .wlSpinner' ).fadeOut( 200 ); |
461 | 420 | |
462 | 421 | if ( typeof data.error !== 'undefined' ) { |
463 | | - $( '#wlPreview' ).append( '<div class="wlError">' + data.error.info + '<div>' ); |
| 422 | + $( '#wlPreview' ).append( '<div class="wlError">' + mw.html.escape( data.error.info ) + '<div>' ); |
464 | 423 | return; |
465 | 424 | } |
466 | 425 | |
— | — | @@ -471,8 +430,8 @@ |
472 | 431 | window.location.reload(); |
473 | 432 | } |
474 | 433 | else { |
475 | | - window.location = mw.config.get( 'wgArticlePath' ).replace('$1', data.redirect.pageName) |
476 | | - + data.redirect.fragment; |
| 434 | + window.location = mw.config.get( 'wgArticlePath' ).replace( '$1', data.redirect.pageName ) |
| 435 | + + '#' + data.redirect.fragment; |
477 | 436 | } |
478 | 437 | } |
479 | 438 | }); |
— | — | @@ -530,7 +489,7 @@ |
531 | 490 | // only add the image if it's actually an image |
532 | 491 | if( page.imageinfo[0].mime.substr(0,5) == 'image' ) { |
533 | 492 | // build an image tag with the correct url and width |
534 | | - $img = $( '<img/>' ) |
| 493 | + var $img = $( '<img/>' ) |
535 | 494 | .attr( 'src', page.imageinfo[0].url ) |
536 | 495 | .attr( 'width', $.wikiLove.currentTypeOrSubtype.gallery.width ) |
537 | 496 | .hide() |
— | — | @@ -578,5 +537,6 @@ |
579 | 538 | }); |
580 | 539 | } |
581 | 540 | }; |
582 | | -$.wikiLove.init(); |
| 541 | + |
| 542 | +$( document ).ready( $.wikiLove.init ); |
583 | 543 | } ) ( jQuery ); |
Index: trunk/extensions/WikiLove/WikiLove.api.php |
— | — | @@ -7,16 +7,16 @@ |
8 | 8 | |
9 | 9 | $title = Title::newFromText( $params['title'] ); |
10 | 10 | if ( is_null( $title ) ) { |
11 | | - $this->dieUsageMsg( array( 'invalidtitle', $params['title'] ) ); |
| 11 | + $this->dieUsageMsg( array( 'invaliduser', $params['title'] ) ); |
12 | 12 | } |
13 | 13 | |
14 | 14 | $talk = WikiLoveHooks::getUserTalkPage( $title ); |
15 | 15 | if ( is_null( $talk ) ) { |
16 | | - $this->dieUsageMsg( array( 'invalidtitle', $params['title'] ) ); |
| 16 | + $this->dieUsageMsg( array( 'invaliduser', $params['title'] ) ); |
17 | 17 | } |
18 | 18 | |
19 | 19 | if ( $wgWikiLoveLogging ) { |
20 | | - $this->saveInDb( $talk, $params['subject'], $params['text'], $params['type'], $params['template'] ); |
| 20 | + $this->saveInDb( $talk, $params['subject'], $params['text'], $params['type'], isset( $params['email'] ) ? 1 : 0 ); |
21 | 21 | } |
22 | 22 | |
23 | 23 | $api = new ApiMain( new FauxRequest( array( |
— | — | @@ -28,15 +28,19 @@ |
29 | 29 | 'summary' => $params['subject'], |
30 | 30 | 'notminor' => true, |
31 | 31 | ), false, array( 'wsEditToken' => $wgRequest->getSessionData( 'wsEditToken' ) ) ), true ); |
| 32 | + |
| 33 | + if ( isset( $params['email'] ) ) { |
| 34 | + $this->emailUser( $talk, $params['subject'], $params['email'] ); |
| 35 | + } |
32 | 36 | |
33 | 37 | $api->execute(); |
34 | 38 | |
35 | 39 | $result = $api->getResult(); |
36 | 40 | $data = $result->getData(); |
37 | 41 | |
38 | | - $talk->setFragment( '#' . $params['subject'] ); |
39 | 42 | $this->getResult()->addValue( 'redirect', 'pageName', $talk->getPrefixedDBkey() ); |
40 | | - $this->getResult()->addValue( 'redirect', 'fragment', $talk->getFragmentForURL() ); |
| 43 | + $this->getResult()->addValue( 'redirect', 'fragment', Title::escapeFragmentForURL( $params['subject'] ) ); |
| 44 | + // note that we cannot use Title::makeTitle here as it doesn't sanitize the fragment |
41 | 45 | } |
42 | 46 | |
43 | 47 | /** |
— | — | @@ -46,25 +50,38 @@ |
47 | 51 | * @param $type |
48 | 52 | * @return void |
49 | 53 | */ |
50 | | - private function saveInDb( $talk, $subject, $text, $type, $template ) { |
| 54 | + private function saveInDb( $talk, $subject, $text, $type, $email ) { |
51 | 55 | global $wgUser; |
52 | 56 | $dbw = wfGetDB( DB_MASTER ); |
53 | 57 | $values = array( |
54 | | - 'wl_timestamp' => $dbw->timestamp(), |
55 | | - 'wl_sender_id' => $wgUser->getId(), |
56 | | - 'wl_receiver_id' => User::newFromName( $talk->getSubjectPage()->getBaseText() )->getId(), |
57 | | - 'wl_type' => $type, |
58 | | - 'wl_subject' => $subject, |
59 | | - 'wl_message' => $text, |
60 | | - 'wl_email' => 0, |
| 58 | + 'wll_timestamp' => $dbw->timestamp(), |
| 59 | + 'wll_sender' => $wgUser->getId(), |
| 60 | + 'wll_receiver' => User::newFromName( $talk->getSubjectPage()->getBaseText() )->getId(), |
| 61 | + 'wll_type' => $type, |
| 62 | + 'wll_subject' => $subject, |
| 63 | + 'wll_message' => $text, |
| 64 | + 'wll_email' => $email, |
61 | 65 | ); |
62 | 66 | try{ |
63 | 67 | $dbw->insert( 'wikilove_log', $values, __METHOD__ ); |
64 | 68 | } catch( DBQueryError $dbqe ) { |
65 | | - $this->dieUsage( 'Warning: action was not logged!', 'nologging' ); |
66 | | - return false; |
| 69 | + $this->setWarning( 'Action was not logged' ); |
67 | 70 | } |
68 | 71 | } |
| 72 | + |
| 73 | + private function emailUser( $talk, $subject, $text ) { |
| 74 | + $api = new ApiMain( new FauxRequest( array( |
| 75 | + 'action' => 'emailuser', |
| 76 | + 'target' => User::newFromName( $talk->getSubjectPage()->getBaseText() )->getName(), |
| 77 | + 'subject' => $subject, |
| 78 | + 'text' => $text, |
| 79 | + ), false, array( 'wsEditToken' => $wgRequest->getSessionData( 'wsEditToken' ) ) ), true ); |
| 80 | + try{ |
| 81 | + $api->execute(); |
| 82 | + } catch( DBQueryError $dbqe ) { |
| 83 | + $this->setWarning( 'E-mail was not sent' ); |
| 84 | + } |
| 85 | + } |
69 | 86 | |
70 | 87 | public function getAllowedParams() { |
71 | 88 | return array( |
— | — | @@ -87,6 +104,9 @@ |
88 | 105 | 'type' => array( |
89 | 106 | ApiBase::PARAM_TYPE => 'string', |
90 | 107 | ), |
| 108 | + 'email' => array( |
| 109 | + ApiBase::PARAM_TYPE => 'string', |
| 110 | + ), |
91 | 111 | ); |
92 | 112 | } |
93 | 113 | |
— | — | @@ -125,7 +145,7 @@ |
126 | 146 | |
127 | 147 | public function getExamples() { |
128 | 148 | return array( |
129 | | - 'api.php?action=wikiLove&title=User:Dummy&text=Love&subject=Hi&token=%2B\\', |
| 149 | + 'api.php?action=wikilove&title=User:Dummy&text=Love&subject=Hi&token=%2B\\', |
130 | 150 | ); |
131 | 151 | } |
132 | 152 | |
Index: trunk/extensions/WikiLove/patches/WikiLoveLog.sql |
— | — | @@ -1,15 +1,24 @@ |
2 | 2 | -- |
3 | 3 | -- WikiLove logging schema |
| 4 | +-- Logs all actions of giving WikiLove. |
4 | 5 | -- Not final, please apply this patch manually for now! |
5 | 6 | -- |
6 | 7 | |
7 | 8 | CREATE TABLE IF NOT EXISTS /*_*/wikilove_log ( |
8 | | - `wl_id` int NOT NULL PRIMARY KEY auto_increment, |
9 | | - `wl_timestamp` binary(14) NOT NULL, |
10 | | - `wl_sender_id` int(11) NOT NULL, |
11 | | - `wl_receiver_id` int(11) NOT NULL, |
12 | | - `wl_type` varchar(64) NOT NULL, |
13 | | - `wl_subject` varchar(255) NOT NULL, |
14 | | - `wl_message` blob NOT NULL, |
15 | | - `wl_email` bool NOT NULL default '0' |
| 9 | + wll_id int NOT NULL PRIMARY KEY auto_increment, -- unique id |
| 10 | + wll_timestamp binary(14) NOT NULL, -- timestamp |
| 11 | + wll_sender int(11) NOT NULL, -- user id of the sender |
| 12 | + wll_receiver int(11) NOT NULL, -- user id of the receiver |
| 13 | + wll_type varchar(64) NOT NULL, -- type (and subtype) of message |
| 14 | + wll_subject varchar(255) NOT NULL, -- subject line |
| 15 | + wll_message blob NOT NULL, -- actual message |
| 16 | + wll_email bool NOT NULL default '0' -- whether or not a notification mail has been sent |
16 | 17 | ) /*$wgDBTableOptions*/; |
| 18 | + |
| 19 | +CREATE INDEX /*i*/wll_timestamp ON /*_*/wikilove_log (wll_timestamp); |
| 20 | +CREATE INDEX /*i*/wll_type_time ON /*_*/wikilove_log (wll_type, wll_timestamp); |
| 21 | +CREATE INDEX /*i*/wll_sender_time ON /*_*/wikilove_log (wll_sender, wll_timestamp); |
| 22 | +CREATE INDEX /*i*/wll_receiver_time ON /*_*/wikilove_log (wll_receiver, wll_timestamp); |
| 23 | +-- ASSUMPTION: once narrowed down to a single user (sender/receiver), we can afford a filesort |
| 24 | +-- as a single users will have only limited WikiLove messages from or to him/her. It's not worth |
| 25 | +-- the memory of extra indexes to cover all the combinations (sender/receiver/type => 8 indexes) |
Index: trunk/extensions/WikiLove/WikiLove.i18n.php |
— | — | @@ -31,6 +31,7 @@ |
32 | 32 | 'wikilove-omit-sig' => '(without a signature)', |
33 | 33 | 'wikilove-button-preview' => 'Preview', |
34 | 34 | 'wikilove-preview' => 'Preview', |
| 35 | + 'wikilove-notify' => 'Notify the user by e-mail', |
35 | 36 | 'wikilove-button-send' => 'Send WikiLove', |
36 | 37 | 'wikilove-type-makeyourown' => 'Make your own', |
37 | 38 | 'wikilove-err-header' => 'Please enter a header.', |
— | — | @@ -38,9 +39,6 @@ |
39 | 40 | 'wikilove-err-msg' => 'Please enter a message.', |
40 | 41 | 'wikilove-err-image' => 'Please select an image.', |
41 | 42 | 'wikilove-err-sig' => 'Please do not include a signature in the message.', |
42 | | - |
43 | | - // messages for default types |
44 | | - 'wikilove-barnstar-header' => 'A barnstar for you!', |
45 | 43 | ); |
46 | 44 | |
47 | 45 | /** Message documentation (Message documentation) |