Index: trunk/extensions/Push/Push.i18n.php |
— | — | @@ -17,6 +17,10 @@ |
18 | 18 | $messages['en'] = array( |
19 | 19 | 'push-desc' => 'Lightweight extension to push content to other wikis', |
20 | 20 | |
| 21 | + 'right-push' => 'Authorization to use push functionality.', |
| 22 | + 'right-bulkpush' => 'Authorization to use bulk push functionality (ie Special:Push).', |
| 23 | + 'right-pushadmin' => 'Authorization to modify push targets and push settings.', |
| 24 | + |
21 | 25 | // Tab |
22 | 26 | 'push-tab-text' => 'Push', |
23 | 27 | 'push-button-text' => 'Push', |
— | — | @@ -46,13 +50,13 @@ |
47 | 51 | 'push-special-button-text' => 'Push pages', |
48 | 52 | 'push-special-target-is' => 'Target wiki: $1', |
49 | 53 | 'push-special-select-targets' => 'Target wikis:', |
50 | | - 'push-special-item-getting' => '$1: Getting page', |
51 | | - 'push-special-item-pushing-to' => '$1: Pushing to $2', |
| 54 | + 'push-special-item-pushing' => '$1: Pushing', |
52 | 55 | 'push-special-item-completed' => '$1: Push completed', |
53 | 56 | 'push-special-item-failed' => '$1: Push failed: $2', |
54 | | - 'push-special-push-done' => 'Push completed' |
55 | | - # 'right-push' => '', // Please add a description of this userright which is shown at [[Special:ListGroupRights]] |
56 | | - # 'right-pushadmin' => '', // Please add a description of this userright which is shown at [[Special:ListGroupRights]] |
| 57 | + 'push-special-push-done' => 'Push completed', |
| 58 | + 'push-special-err-token-failed' => 'Could not obtain an edit token on the target wiki.', |
| 59 | + 'push-special-err-pageget-failed' => 'Could not obtain local page content.', |
| 60 | + 'push-special-err-push-failed' => 'Target wiki refused the pushed page.' |
57 | 61 | ); |
58 | 62 | |
59 | 63 | /** Message documentation (Message documentation) */ |
Index: trunk/extensions/Push/specials/Push_Body.php |
— | — | @@ -119,7 +119,7 @@ |
120 | 120 | * @param string $pages |
121 | 121 | */ |
122 | 122 | protected function doPush( $pages ) { |
123 | | - global $wgOut, $wgLang, $wgRequest, $wgSitename, $egPushTargets, $egPushBulkWorkers; |
| 123 | + global $wgOut, $wgLang, $wgRequest, $wgSitename, $egPushTargets, $egPushBulkWorkers, $egPushBatchSize; |
124 | 124 | |
125 | 125 | $pageSet = array(); // Inverted index of all pages to look up |
126 | 126 | |
— | — | @@ -142,18 +142,18 @@ |
143 | 143 | |
144 | 144 | $targets = array(); |
145 | 145 | $links = array(); |
146 | | - $revisions = array(); |
147 | 146 | |
148 | | - foreach ( $pages as $page ) { |
149 | | - $revisions[$page] = PushFunctions::getRevisionToPush( Title::newFromText( $page ) ); |
150 | | - } |
151 | | - |
152 | | - foreach ( $egPushTargets as $targetName => $targetUrl ) { |
153 | | - if ( $wgRequest->getCheck( str_replace( ' ', '_', $targetName ) ) ) { |
154 | | - $targets[$targetName] = $targetUrl; |
155 | | - $links[] = "[$targetUrl $targetName]"; |
| 147 | + if ( count( $egPushTargets ) > 1 ) { |
| 148 | + foreach ( $egPushTargets as $targetName => $targetUrl ) { |
| 149 | + if ( $wgRequest->getCheck( str_replace( ' ', '_', $targetName ) ) ) { |
| 150 | + $targets[$targetName] = $targetUrl; |
| 151 | + $links[] = "[$targetUrl $targetName]"; |
| 152 | + } |
156 | 153 | } |
157 | 154 | } |
| 155 | + else { |
| 156 | + $targets = $egPushTargets; |
| 157 | + } |
158 | 158 | |
159 | 159 | $wgOut->addWikiMsg( 'push-special-pushing-desc', $wgLang->listToText( $links ), $wgLang->formatNum( count( $pages ) ) ); |
160 | 160 | |
— | — | @@ -175,9 +175,9 @@ |
176 | 176 | |
177 | 177 | $wgOut->addInlineScript( |
178 | 178 | 'var wgPushPages = ' . json_encode( $pages ) . ';' . |
179 | | - 'var wgPushRevs = ' . json_encode( $revisions ) . ';' . |
180 | 179 | 'var wgPushTargets = ' . json_encode( $targets ) . ';' . |
181 | | - 'var wgPushWorkerCount = ' . $egPushBulkWorkers . ';' |
| 180 | + 'var wgPushWorkerCount = ' . $egPushBulkWorkers . ';' . |
| 181 | + 'var wgPushBatchSize = ' . $egPushBatchSize . ';' |
182 | 182 | ); |
183 | 183 | |
184 | 184 | $this->loadJs(); |
Index: trunk/extensions/Push/specials/ext.push.special.js |
— | — | @@ -12,20 +12,27 @@ |
13 | 13 | if ( typeof mediaWiki === 'undefined' ) { |
14 | 14 | mediaWiki = new Object(); |
15 | 15 | |
16 | | - mediaWiki.msg = function( message ) { |
17 | | - return window.wgPushMessages[message]; |
| 16 | + mediaWiki.msg = function() { |
| 17 | + message = window.wgPushMessages[arguments[0]]; |
| 18 | + |
| 19 | + for ( var i = arguments.length - 1; i > 0; i-- ) { |
| 20 | + message = message.replace( '$' + i, arguments[i] ); |
| 21 | + } |
| 22 | + |
| 23 | + return message; |
18 | 24 | } |
19 | 25 | } |
20 | 26 | |
21 | 27 | var resultList = $('#pushResultList'); |
22 | 28 | |
23 | | - var targets = window.wgPushTargets; |
| 29 | + var targets = []; |
| 30 | + for (targetName in window.wgPushTargets) targets.push( window.wgPushTargets[targetName] ); |
| 31 | + |
24 | 32 | var pages = window.wgPushPages; |
25 | | - var revs = window.wgPushRevs; |
| 33 | + |
26 | 34 | var requestAmount = Math.min( pages.length, window.wgPushWorkerCount ); |
| 35 | + var batchSize = Math.min( targets.length, window.wgPushBatchSize ); |
27 | 36 | |
28 | | - var pageTargets = []; |
29 | | - |
30 | 37 | for ( i = requestAmount; i > 0; i-- ) { |
31 | 38 | initiateNextPush(); |
32 | 39 | } |
— | — | @@ -34,139 +41,70 @@ |
35 | 42 | var page = pages.pop(); |
36 | 43 | |
37 | 44 | if ( page ) { |
38 | | - startPush( page ); |
| 45 | + startPush( page, 0, null ); |
39 | 46 | } |
40 | 47 | else if ( !--requestAmount ) { |
41 | 48 | showCompletion(); |
42 | 49 | } |
43 | 50 | } |
44 | 51 | |
45 | | - function startPush( pageName ) { |
46 | | - var listItem = $( '<li />' ); |
47 | | - listItem.text( pageName ); |
48 | | - |
49 | | - var box = $('#pushResultDiv'); |
50 | | - var innerBox = $('#pushResultDiv > .innerResultBox'); |
51 | | - var atBottom = Math.abs(innerBox.offset().top) + box.height() + box.offset().top >= innerBox.outerHeight(); |
52 | | - |
53 | | - resultList.append( listItem ); |
54 | | - |
55 | | - if ( atBottom ) { |
56 | | - box.attr( {'scrollTop': box.attr( 'scrollHeight' )} ); |
| 52 | + function startPush( pageName, targetOffset, listItem ) { |
| 53 | + if ( targetOffset == 0 ) { |
| 54 | + var listItem = $( '<li />' ); |
| 55 | + listItem.text( mediaWiki.msg( 'push-special-item-pushing', pageName ) ); |
| 56 | + |
| 57 | + var box = $('#pushResultDiv'); |
| 58 | + var innerBox = $('#pushResultDiv > .innerResultBox'); |
| 59 | + var atBottom = Math.abs(innerBox.offset().top) + box.height() + box.offset().top >= innerBox.outerHeight(); |
| 60 | + |
| 61 | + resultList.append( listItem ); |
| 62 | + |
| 63 | + if ( atBottom ) { |
| 64 | + box.attr( {'scrollTop': box.attr( 'scrollHeight' )} ); |
| 65 | + } |
57 | 66 | } |
58 | 67 | |
59 | | - getLocalArtcileAndContinue( listItem, pageName ); |
60 | | - } |
61 | | - |
62 | | - function showCompletion() { |
63 | | - resultList.append( $( '<li />' ).append( $( '<b />' ).text( mediaWiki.msg( 'push-special-push-done' ) ) ) ); |
64 | | - } |
65 | | - |
66 | | - function getLocalArtcileAndContinue( listItem, pageName ) { |
67 | | - listItem.text( msgReplace( 'push-special-item-getting', pageName ) ); |
| 68 | + var currentBatchLimit = Math.min( targetOffset + batchSize, targets.length ); |
| 69 | + var currentBatchStart = targetOffset; |
68 | 70 | |
69 | | - $.getJSON( |
70 | | - wgScriptPath + '/api.php', |
71 | | - { |
72 | | - 'action': 'query', |
73 | | - 'format': 'json', |
74 | | - 'prop': 'revisions', |
75 | | - 'rvprop': 'timestamp|user|comment|content', |
76 | | - 'titles': pageName, |
77 | | - 'rvstartid': revs[pageName], |
78 | | - 'rvendid': revs[pageName], |
79 | | - }, |
80 | | - function( data ) { |
81 | | - if ( data.error ) { |
82 | | - handleError( listItem, pageName, data.error ); |
| 71 | + if ( targetOffset < targets.length ) { |
| 72 | + listItem.text( listItem.text() + '...' ); |
| 73 | + |
| 74 | + targetOffset = currentBatchLimit; |
| 75 | + |
| 76 | + $.getJSON( |
| 77 | + wgScriptPath + '/api.php', |
| 78 | + { |
| 79 | + 'action': 'push', |
| 80 | + 'format': 'json', |
| 81 | + 'page': pageName, |
| 82 | + 'targets': targets.slice( currentBatchStart, currentBatchLimit ).join( '|' ) |
| 83 | + }, |
| 84 | + function( data ) { |
| 85 | + if ( data.error ) { |
| 86 | + handleError( listItem, pageName, data.error ); |
| 87 | + } |
| 88 | + else { |
| 89 | + startPush( pageName, targetOffset, listItem ); |
| 90 | + } |
83 | 91 | } |
84 | | - else { |
85 | | - for (first in data.query.pages) break; |
86 | | - var remainingTargets = []; |
87 | | - for (targetName in targets) remainingTargets.push( targetName ); |
88 | | - initiateEdit( listItem, pageName, data.query.pages[first], remainingTargets ); |
89 | | - } |
90 | | - } |
91 | | - ); |
92 | | - } |
93 | | - |
94 | | - function initiateEdit( listItem, pageName, page, remainingTargets ) { |
95 | | - targetName = remainingTargets.pop(); |
96 | | - |
97 | | - if ( targetName ) { |
98 | | - getEditTokenAndContinue( listItem, pageName, targets[targetName], targetName, page, remainingTargets ); |
| 92 | + ); |
99 | 93 | } |
100 | 94 | else { |
101 | | - listItem.text( msgReplace( 'push-special-item-completed', pageName ) ); |
| 95 | + listItem.text( mediaWiki.msg( 'push-special-item-completed', pageName ) ); |
102 | 96 | listItem.css( 'color', 'darkgray' ); |
103 | | - initiateNextPush(); |
| 97 | + initiateNextPush(); |
104 | 98 | } |
105 | 99 | } |
106 | 100 | |
107 | | - function getEditTokenAndContinue( listItem, pageName, targetUrl, targetName, page, remainingTargets ) { |
108 | | - listItem.text( msgReplace( 'push-special-item-pushing-to', pageName, targetName ) ); |
109 | | - |
110 | | - $.getJSON( |
111 | | - targetUrl + '/api.php', |
112 | | - { |
113 | | - 'action': 'query', |
114 | | - 'format': 'json', |
115 | | - 'intoken': 'edit', |
116 | | - 'prop': 'info', |
117 | | - 'titles': page.title, |
118 | | - }, |
119 | | - function( data ) { |
120 | | - if ( data.error ) { |
121 | | - handleError( listItem, pageName, data.error ); |
122 | | - } |
123 | | - else { |
124 | | - for (first in data.query.pages) break; |
125 | | - doPush( listItem, pageName, targetUrl, page, data.query.pages[first].edittoken, remainingTargets ); |
126 | | - } |
127 | | - } |
128 | | - ); |
129 | | - } |
130 | | - |
131 | | - function doPush( listItem, pageName, targetUrl, page, token, remainingTargets ) { |
132 | | - var summary = msgReplace( |
133 | | - 'push-import-revision-message', |
134 | | - $('#siteName').attr('value'), |
135 | | - page.revisions[0].user, |
136 | | - page.revisions[0].comment ? msgReplace( 'push-import-revision-comment', page.revisions[0].comment ) : '' |
137 | | - ); |
138 | | - |
139 | | - $.post( |
140 | | - targetUrl + '/api.php', |
141 | | - { |
142 | | - 'action': 'edit', |
143 | | - 'format': 'json', |
144 | | - 'token': token, |
145 | | - 'title': page.title, |
146 | | - 'summary': summary, |
147 | | - 'text': page.revisions[0].* |
148 | | - }, |
149 | | - function( data ) { |
150 | | - if ( data.error ) { |
151 | | - handleError( listItem, pageName, data.error ); |
152 | | - } |
153 | | - else { |
154 | | - initiateEdit( listItem, pageName, page, remainingTargets ); |
155 | | - } |
156 | | - } |
157 | | - ); |
| 101 | + function showCompletion() { |
| 102 | + resultList.append( $( '<li />' ).append( $( '<b />' ).text( mediaWiki.msg( 'push-special-push-done' ) ) ) ); |
158 | 103 | } |
159 | 104 | |
160 | 105 | function handleError( listItem, pageName, error ) { |
161 | | - listItem.text( msgReplace( 'push-special-item-failed', pageName, error.info ) ); |
| 106 | + listItem.text( mediaWiki.msg( 'push-special-item-failed', pageName, error.info ) ); |
| 107 | + listItem.css( 'color', 'darkred' ); |
162 | 108 | initiateNextPush(); |
163 | 109 | } |
164 | 110 | |
165 | | - function msgReplace() { |
166 | | - message = mediaWiki.msg( arguments[0] ); |
167 | | - for ( var i = arguments.length - 1; i > 0; i-- ) { |
168 | | - message = message.replace( '$' + i, arguments[i] ); |
169 | | - } |
170 | | - return message; |
171 | | - } |
172 | | - |
173 | 111 | } ); })(jQuery); |
\ No newline at end of file |
Index: trunk/extensions/Push/Push.php |
— | — | @@ -71,8 +71,7 @@ |
72 | 72 | 'push-import-revision-comment', |
73 | 73 | 'push-button-text', |
74 | 74 | 'push-button-all', |
75 | | - 'push-special-item-getting', |
76 | | - 'push-special-item-pushing-to', |
| 75 | + 'push-special-item-pushing', |
77 | 76 | 'push-special-item-completed', |
78 | 77 | 'push-special-item-failed', |
79 | 78 | 'push-special-push-done', |
Index: trunk/extensions/Push/Push_Settings.php |
— | — | @@ -28,3 +28,4 @@ |
29 | 29 | $egPushShowTab = false; |
30 | 30 | |
31 | 31 | $egPushBulkWorkers = 3; |
| 32 | +$egPushBatchSize = 3; |
Index: trunk/extensions/Push/api/ApiPush.php |
— | — | @@ -64,7 +64,8 @@ |
65 | 65 | |
66 | 66 | $revision = false; |
67 | 67 | |
68 | | - if ( array_key_exists( 'query', $response ) |
| 68 | + if ( $response !== false |
| 69 | + && array_key_exists( 'query', $response ) |
69 | 70 | && array_key_exists( 'pages', $response['query'] ) |
70 | 71 | && count( $response['query']['pages'] ) > 0 ) { |
71 | 72 | |
— | — | @@ -78,11 +79,11 @@ |
79 | 80 | $revision = $response['query']['pages'][$first]['revisions'][0]; |
80 | 81 | } |
81 | 82 | else { |
82 | | - // TODO |
| 83 | + $this->dieUsage( wfMsg( 'push-special-err-pageget-failed' ), 'page-get-failed' ); |
83 | 84 | } |
84 | 85 | } |
85 | 86 | else { |
86 | | - // TODO |
| 87 | + $this->dieUsage( wfMsg( 'push-special-err-pageget-failed' ), 'page-get-failed' ); |
87 | 88 | } |
88 | 89 | |
89 | 90 | return $revision; |
— | — | @@ -138,11 +139,12 @@ |
139 | 140 | foreach ( $requestData as $key => $value ) { |
140 | 141 | $parts[] = $key . '=' . urlencode( $value ); |
141 | 142 | } |
142 | | - |
| 143 | + |
143 | 144 | $response = FormatJson::decode( Http::get( $target . '?' . implode( '&', $parts ) ) ); |
144 | 145 | $token = false; |
145 | 146 | |
146 | | - if ( property_exists( $response, 'query' ) |
| 147 | + if ( !is_null( $response ) |
| 148 | + && property_exists( $response, 'query' ) |
147 | 149 | && property_exists( $response->query, 'pages' ) |
148 | 150 | && count( $response->query->pages ) > 0 ) { |
149 | 151 | |
— | — | @@ -154,12 +156,15 @@ |
155 | 157 | if ( property_exists( $response->query->pages->$first, 'edittoken' ) ) { |
156 | 158 | $token = $response->query->pages->$first->edittoken; |
157 | 159 | } |
| 160 | + elseif ( !is_null( $response ) && property_exists( $response, 'query' ) && property_exists( $response->query, 'error' ) ) { |
| 161 | + $this->dieUsage( $response->query->error->message, 'token-request-failed' ); |
| 162 | + } |
158 | 163 | else { |
159 | | - // TODO |
160 | | - } |
| 164 | + $this->dieUsage( wfMsg( 'push-special-err-token-failed' ), 'token-request-failed' ); |
| 165 | + } |
161 | 166 | } |
162 | 167 | else { |
163 | | - // TODO |
| 168 | + $this->dieUsage( wfMsg( 'push-special-err-token-failed' ), 'token-request-failed' ); |
164 | 169 | } |
165 | 170 | |
166 | 171 | return $token; |
— | — | @@ -196,20 +201,25 @@ |
197 | 202 | ); |
198 | 203 | |
199 | 204 | $response = Http::post( $target, array( 'postData' => $requestData ) ); |
200 | | -//var_dump($response);exit; |
201 | | - // TODO |
| 205 | + |
| 206 | + if ( $response !== false ) { |
| 207 | + die( $response ); |
| 208 | + } |
| 209 | + else { |
| 210 | + $this->dieUsage( wfMsg( 'push-special-err-push-failed' ), 'page-push-failed' ); |
| 211 | + } |
202 | 212 | } |
203 | 213 | |
204 | 214 | public function getAllowedParams() { |
205 | 215 | return array( |
206 | 216 | 'page' => array( |
207 | 217 | ApiBase::PARAM_TYPE => 'string', |
208 | | - ApiBase::PARAM_REQUIRED => true, |
| 218 | + //ApiBase::PARAM_REQUIRED => true, |
209 | 219 | ), |
210 | 220 | 'targets' => array( |
211 | 221 | ApiBase::PARAM_TYPE => 'string', |
212 | 222 | ApiBase::PARAM_ISMULTI => true, |
213 | | - ApiBase::PARAM_REQUIRED => true, |
| 223 | + //ApiBase::PARAM_REQUIRED => true, |
214 | 224 | ), |
215 | 225 | ); |
216 | 226 | } |