Index: trunk/phase3/includes/specials/SpecialExport.php |
— | — | @@ -23,363 +23,377 @@ |
24 | 24 | |
25 | 25 | class SpecialExport extends SpecialPage { |
26 | 26 | |
27 | | - private $curonly, $doExport, $pageLinkDepth, $templates; |
28 | | - private $images; |
| 27 | + private $curonly, $doExport, $pageLinkDepth, $templates; |
| 28 | + private $images; |
29 | 29 | |
30 | | - public function __construct() { |
31 | | - parent::__construct( 'Export' ); |
32 | | - } |
33 | | - |
34 | | - public function execute( $par ) { |
35 | | - global $wgOut, $wgRequest, $wgSitename, $wgExportAllowListContributors; |
36 | | - global $wgExportAllowHistory, $wgExportMaxHistory, $wgExportMaxLinkDepth; |
| 30 | + public function __construct() { |
| 31 | + parent::__construct( 'Export' ); |
| 32 | + } |
| 33 | + |
| 34 | + public function execute( $par ) { |
| 35 | + global $wgOut, $wgRequest, $wgSitename, $wgExportAllowListContributors; |
| 36 | + global $wgExportAllowHistory, $wgExportMaxHistory, $wgExportMaxLinkDepth; |
37 | 37 | |
38 | | - $this->setHeaders(); |
39 | | - $this->outputHeader(); |
| 38 | + $this->setHeaders(); |
| 39 | + $this->outputHeader(); |
40 | 40 | |
41 | | - // Set some variables |
42 | | - $this->curonly = true; |
43 | | - $this->doExport = false; |
44 | | - $this->templates = $wgRequest->getCheck( 'templates' ); |
45 | | - $this->images = $wgRequest->getCheck( 'images' ); // Doesn't do anything yet |
46 | | - $this->pageLinkDepth = $this->validateLinkDepth( |
47 | | - $wgRequest->getIntOrNull( 'pagelink-depth' ) ); |
| 41 | + // Set some variables |
| 42 | + $this->curonly = true; |
| 43 | + $this->doExport = false; |
| 44 | + $this->templates = $wgRequest->getCheck( 'templates' ); |
| 45 | + $this->images = $wgRequest->getCheck( 'images' ); // Doesn't do anything yet |
| 46 | + $this->pageLinkDepth = $this->validateLinkDepth( |
| 47 | + $wgRequest->getIntOrNull( 'pagelink-depth' ) ); |
48 | 48 | |
49 | | - if ( $wgRequest->getCheck( 'addcat' ) ) { |
50 | | - $page = $wgRequest->getText( 'pages' ); |
51 | | - $catname = $wgRequest->getText( 'catname' ); |
| 49 | + if ( $wgRequest->getCheck( 'addcat' ) ) { |
| 50 | + $page = $wgRequest->getText( 'pages' ); |
| 51 | + $catname = $wgRequest->getText( 'catname' ); |
52 | 52 | |
53 | | - if ( $catname !== '' && $catname !== NULL && $catname !== false ) { |
54 | | - $t = Title::makeTitleSafe( NS_MAIN, $catname ); |
55 | | - if ( $t ) { |
56 | | - /** |
57 | | - * @fixme This can lead to hitting memory limit for very large |
58 | | - * categories. Ideally we would do the lookup synchronously |
59 | | - * during the export in a single query. |
60 | | - */ |
61 | | - $catpages = $this->getPagesFromCategory( $t ); |
62 | | - if ( $catpages ) $page .= "\n" . implode( "\n", $catpages ); |
63 | | - } |
64 | | - } |
65 | | - } |
66 | | - else if( $wgRequest->getCheck( 'addns' ) ) { |
67 | | - $page = $wgRequest->getText( 'pages' ); |
68 | | - $nsindex = $wgRequest->getText( 'nsindex' ); |
69 | | - |
70 | | - if ( $nsindex !== '' && $nsindex !== NULL && $nsindex !== false ) { |
71 | | - /** |
72 | | - * Same implementation as above, so same @fixme |
73 | | - */ |
74 | | - $nspages = $this->getPagesFromNamespace( $nsindex ); |
75 | | - if ( $nspages ) $page .= "\n" . implode( "\n", $nspages ); |
76 | | - } |
77 | | - } |
78 | | - else if( $wgRequest->wasPosted() && $par == '' ) { |
79 | | - $page = $wgRequest->getText( 'pages' ); |
80 | | - $this->curonly = $wgRequest->getCheck( 'curonly' ); |
81 | | - $rawOffset = $wgRequest->getVal( 'offset' ); |
82 | | - if( $rawOffset ) { |
83 | | - $offset = wfTimestamp( TS_MW, $rawOffset ); |
84 | | - } else { |
85 | | - $offset = null; |
86 | | - } |
87 | | - $limit = $wgRequest->getInt( 'limit' ); |
88 | | - $dir = $wgRequest->getVal( 'dir' ); |
89 | | - $history = array( |
90 | | - 'dir' => 'asc', |
91 | | - 'offset' => false, |
92 | | - 'limit' => $wgExportMaxHistory, |
93 | | - ); |
94 | | - $historyCheck = $wgRequest->getCheck( 'history' ); |
95 | | - if ( $this->curonly ) { |
96 | | - $history = WikiExporter::CURRENT; |
97 | | - } elseif ( !$historyCheck ) { |
98 | | - if ( $limit > 0 && $limit < $wgExportMaxHistory ) { |
99 | | - $history['limit'] = $limit; |
100 | | - } |
101 | | - if ( !is_null( $offset ) ) { |
102 | | - $history['offset'] = $offset; |
103 | | - } |
104 | | - if ( strtolower( $dir ) == 'desc' ) { |
105 | | - $history['dir'] = 'desc'; |
106 | | - } |
107 | | - } |
| 53 | + if ( $catname !== '' && $catname !== NULL && $catname !== false ) { |
| 54 | + $t = Title::makeTitleSafe( NS_MAIN, $catname ); |
| 55 | + if ( $t ) { |
| 56 | + /** |
| 57 | + * @fixme This can lead to hitting memory limit for very large |
| 58 | + * categories. Ideally we would do the lookup synchronously |
| 59 | + * during the export in a single query. |
| 60 | + */ |
| 61 | + $catpages = $this->getPagesFromCategory( $t ); |
| 62 | + if ( $catpages ) $page .= "\n" . implode( "\n", $catpages ); |
| 63 | + } |
| 64 | + } |
| 65 | + } |
| 66 | + else if( $wgRequest->getCheck( 'addns' ) ) { |
| 67 | + $page = $wgRequest->getText( 'pages' ); |
| 68 | + $nsindex = $wgRequest->getText( 'nsindex' ); |
| 69 | + |
| 70 | + if ( $nsindex !== '' && $nsindex !== NULL && $nsindex !== false ) { |
| 71 | + /** |
| 72 | + * Same implementation as above, so same @fixme |
| 73 | + */ |
| 74 | + $nspages = $this->getPagesFromNamespace( $nsindex ); |
| 75 | + if ( $nspages ) $page .= "\n" . implode( "\n", $nspages ); |
| 76 | + } |
| 77 | + } |
| 78 | + else if( $wgRequest->wasPosted() && $par == '' ) { |
| 79 | + $page = $wgRequest->getText( 'pages' ); |
| 80 | + $this->curonly = $wgRequest->getCheck( 'curonly' ); |
| 81 | + $rawOffset = $wgRequest->getVal( 'offset' ); |
| 82 | + if( $rawOffset ) { |
| 83 | + $offset = wfTimestamp( TS_MW, $rawOffset ); |
| 84 | + } else { |
| 85 | + $offset = null; |
| 86 | + } |
| 87 | + $limit = $wgRequest->getInt( 'limit' ); |
| 88 | + $dir = $wgRequest->getVal( 'dir' ); |
| 89 | + $history = array( |
| 90 | + 'dir' => 'asc', |
| 91 | + 'offset' => false, |
| 92 | + 'limit' => $wgExportMaxHistory, |
| 93 | + ); |
| 94 | + $historyCheck = $wgRequest->getCheck( 'history' ); |
| 95 | + if ( $this->curonly ) { |
| 96 | + $history = WikiExporter::CURRENT; |
| 97 | + } elseif ( !$historyCheck ) { |
| 98 | + if ( $limit > 0 && $limit < $wgExportMaxHistory ) { |
| 99 | + $history['limit'] = $limit; |
| 100 | + } |
| 101 | + if ( !is_null( $offset ) ) { |
| 102 | + $history['offset'] = $offset; |
| 103 | + } |
| 104 | + if ( strtolower( $dir ) == 'desc' ) { |
| 105 | + $history['dir'] = 'desc'; |
| 106 | + } |
| 107 | + } |
108 | 108 | |
109 | | - if( $page != '' ) $this->doExport = true; |
110 | | - } else { |
111 | | - // Default to current-only for GET requests |
112 | | - $page = $wgRequest->getText( 'pages', $par ); |
113 | | - $historyCheck = $wgRequest->getCheck( 'history' ); |
114 | | - if( $historyCheck ) { |
115 | | - $history = WikiExporter::FULL; |
116 | | - } else { |
117 | | - $history = WikiExporter::CURRENT; |
118 | | - } |
| 109 | + if( $page != '' ) $this->doExport = true; |
| 110 | + } else { |
| 111 | + // Default to current-only for GET requests |
| 112 | + $page = $wgRequest->getText( 'pages', $par ); |
| 113 | + $historyCheck = $wgRequest->getCheck( 'history' ); |
| 114 | + if( $historyCheck ) { |
| 115 | + $history = WikiExporter::FULL; |
| 116 | + } else { |
| 117 | + $history = WikiExporter::CURRENT; |
| 118 | + } |
119 | 119 | |
120 | | - if( $page != '' ) $this->doExport = true; |
121 | | - } |
| 120 | + if( $page != '' ) $this->doExport = true; |
| 121 | + } |
122 | 122 | |
123 | | - if( !$wgExportAllowHistory ) { |
124 | | - // Override |
125 | | - $history = WikiExporter::CURRENT; |
126 | | - } |
| 123 | + if( !$wgExportAllowHistory ) { |
| 124 | + // Override |
| 125 | + $history = WikiExporter::CURRENT; |
| 126 | + } |
127 | 127 | |
128 | | - $list_authors = $wgRequest->getCheck( 'listauthors' ); |
129 | | - if ( !$this->curonly || !$wgExportAllowListContributors ) $list_authors = false ; |
| 128 | + $list_authors = $wgRequest->getCheck( 'listauthors' ); |
| 129 | + if ( !$this->curonly || !$wgExportAllowListContributors ) $list_authors = false ; |
130 | 130 | |
131 | | - if ( $this->doExport ) { |
132 | | - $wgOut->disable(); |
133 | | - // Cancel output buffering and gzipping if set |
134 | | - // This should provide safer streaming for pages with history |
135 | | - wfResetOutputBuffers(); |
136 | | - header( "Content-type: application/xml; charset=utf-8" ); |
137 | | - if( $wgRequest->getCheck( 'wpDownload' ) ) { |
138 | | - // Provide a sane filename suggestion |
139 | | - $filename = urlencode( $wgSitename . '-' . wfTimestampNow() . '.xml' ); |
140 | | - $wgRequest->response()->header( "Content-disposition: attachment;filename={$filename}" ); |
141 | | - } |
142 | | - $this->doExport( $page, $history, $list_authors ); |
143 | | - return; |
144 | | - } |
| 131 | + if ( $this->doExport ) { |
| 132 | + $wgOut->disable(); |
| 133 | + // Cancel output buffering and gzipping if set |
| 134 | + // This should provide safer streaming for pages with history |
| 135 | + wfResetOutputBuffers(); |
| 136 | + header( "Content-type: application/xml; charset=utf-8" ); |
| 137 | + if( $wgRequest->getCheck( 'wpDownload' ) ) { |
| 138 | + // Provide a sane filename suggestion |
| 139 | + $filename = urlencode( $wgSitename . '-' . wfTimestampNow() . '.xml' ); |
| 140 | + $wgRequest->response()->header( "Content-disposition: attachment;filename={$filename}" ); |
| 141 | + } |
| 142 | + $this->doExport( $page, $history, $list_authors ); |
| 143 | + return; |
| 144 | + } |
145 | 145 | |
146 | | - $wgOut->addWikiMsg( 'exporttext' ); |
| 146 | + $wgOut->addWikiMsg( 'exporttext' ); |
147 | 147 | |
148 | | - $form = Xml::openElement( 'form', array( 'method' => 'post', |
149 | | - 'action' => $this->getTitle()->getLocalUrl( 'action=submit' ) ) ); |
150 | | - $form .= Xml::inputLabel( wfMsg( 'export-addcattext' ) , 'catname', 'catname', 40 ) . ' '; |
151 | | - $form .= Xml::submitButton( wfMsg( 'export-addcat' ), array( 'name' => 'addcat' ) ) . '<br />'; |
| 148 | + $form = Xml::openElement( 'form', array( 'method' => 'post', |
| 149 | + 'action' => $this->getTitle()->getLocalUrl( 'action=submit' ) ) ); |
| 150 | + $form .= Xml::inputLabel( wfMsg( 'export-addcattext' ) , 'catname', 'catname', 40 ) . ' '; |
| 151 | + $form .= Xml::submitButton( wfMsg( 'export-addcat' ), array( 'name' => 'addcat' ) ) . '<br />'; |
152 | 152 | |
153 | | - $form .= Xml::namespaceSelector( '', null, 'nsindex', wfMsg( 'export-addnstext' ) ) . ' '; |
154 | | - $form .= Xml::submitButton( wfMsg( 'export-addns' ), array( 'name' => 'addns' ) ) . '<br />'; |
| 153 | + $form .= Xml::namespaceSelector( '', null, 'nsindex', wfMsg( 'export-addnstext' ) ) . ' '; |
| 154 | + $form .= Xml::submitButton( wfMsg( 'export-addns' ), array( 'name' => 'addns' ) ) . '<br />'; |
155 | 155 | |
156 | | - $form .= Xml::element( 'textarea', array( 'name' => 'pages', 'cols' => 40, 'rows' => 10 ), $page, false ); |
157 | | - $form .= '<br />'; |
| 156 | + $form .= Xml::element( 'textarea', array( 'name' => 'pages', 'cols' => 40, 'rows' => 10 ), $page, false ); |
| 157 | + $form .= '<br />'; |
158 | 158 | |
159 | | - if( $wgExportAllowHistory ) { |
160 | | - $form .= Xml::checkLabel( wfMsg( 'exportcuronly' ), 'curonly', 'curonly', true ) . '<br />'; |
161 | | - } else { |
162 | | - $wgOut->addHTML( wfMsgExt( 'exportnohistory', 'parse' ) ); |
163 | | - } |
164 | | - $form .= Xml::checkLabel( wfMsg( 'export-templates' ), 'templates', 'wpExportTemplates', false ) . '<br />'; |
165 | | - if( $wgExportMaxLinkDepth ) { |
166 | | - $form .= Xml::inputLabel( wfMsg( 'export-pagelinks' ), 'pagelink-depth', 'pagelink-depth', 20, 0 ) . '<br />'; |
167 | | - } |
168 | | - // Enable this when we can do something useful exporting/importing image information. :) |
169 | | - //$form .= Xml::checkLabel( wfMsg( 'export-images' ), 'images', 'wpExportImages', false ) . '<br />'; |
170 | | - $form .= Xml::checkLabel( wfMsg( 'export-download' ), 'wpDownload', 'wpDownload', true ) . '<br />'; |
| 159 | + if( $wgExportAllowHistory ) { |
| 160 | + $form .= Xml::checkLabel( wfMsg( 'exportcuronly' ), 'curonly', 'curonly', true ) . '<br />'; |
| 161 | + } else { |
| 162 | + $wgOut->addHTML( wfMsgExt( 'exportnohistory', 'parse' ) ); |
| 163 | + } |
| 164 | + $form .= Xml::checkLabel( wfMsg( 'export-templates' ), 'templates', 'wpExportTemplates', false ) . '<br />'; |
| 165 | + if( $wgExportMaxLinkDepth || $this->userCanOverrideExportDepth() ) { |
| 166 | + $form .= Xml::inputLabel( wfMsg( 'export-pagelinks' ), 'pagelink-depth', 'pagelink-depth', 20, 0 ) . '<br />'; |
| 167 | + } |
| 168 | + // Enable this when we can do something useful exporting/importing image information. :) |
| 169 | + //$form .= Xml::checkLabel( wfMsg( 'export-images' ), 'images', 'wpExportImages', false ) . '<br />'; |
| 170 | + $form .= Xml::checkLabel( wfMsg( 'export-download' ), 'wpDownload', 'wpDownload', true ) . '<br />'; |
171 | 171 | |
172 | | - $form .= Xml::submitButton( wfMsg( 'export-submit' ), array( 'accesskey' => 's' ) ); |
173 | | - $form .= Xml::closeElement( 'form' ); |
174 | | - $wgOut->addHTML( $form ); |
175 | | - } |
| 172 | + $form .= Xml::submitButton( wfMsg( 'export-submit' ), array( 'accesskey' => 's' ) ); |
| 173 | + $form .= Xml::closeElement( 'form' ); |
| 174 | + $wgOut->addHTML( $form ); |
| 175 | + } |
176 | 176 | |
177 | | - /** |
178 | | - * Do the actual page exporting |
179 | | - * @param string $page User input on what page(s) to export |
180 | | - * @param mixed $history one of the WikiExporter history export constants |
181 | | - */ |
182 | | - private function doExport( $page, $history, $list_authors ) { |
183 | | - global $wgExportMaxHistory; |
| 177 | + private function userCanOverrideExportDepth() { |
| 178 | + global $wgUser; |
| 179 | + |
| 180 | + return in_array( 'override-export-depth', $wgUser->getRights()); |
| 181 | + } |
| 182 | + |
| 183 | + /** |
| 184 | + * Do the actual page exporting |
| 185 | + * @param string $page User input on what page(s) to export |
| 186 | + * @param mixed $history one of the WikiExporter history export constants |
| 187 | + */ |
| 188 | + private function doExport( $page, $history, $list_authors ) { |
| 189 | + global $wgExportMaxHistory; |
184 | 190 | |
185 | | - /* Split up the input and look up linked pages */ |
186 | | - $inputPages = array_filter( explode( "\n", $page ), array( $this, 'filterPage' ) ); |
187 | | - $pageSet = array_flip( $inputPages ); |
| 191 | + /* Split up the input and look up linked pages */ |
| 192 | + $inputPages = array_filter( explode( "\n", $page ), array( $this, 'filterPage' ) ); |
| 193 | + $pageSet = array_flip( $inputPages ); |
188 | 194 | |
189 | | - if( $this->templates ) { |
190 | | - $pageSet = $this->getTemplates( $inputPages, $pageSet ); |
191 | | - } |
| 195 | + if( $this->templates ) { |
| 196 | + $pageSet = $this->getTemplates( $inputPages, $pageSet ); |
| 197 | + } |
192 | 198 | |
193 | | - if( $linkDepth = $this->pageLinkDepth ) { |
194 | | - $pageSet = $this->getPageLinks( $inputPages, $pageSet, $linkDepth ); |
195 | | - } |
| 199 | + if( $linkDepth = $this->pageLinkDepth ) { |
| 200 | + $pageSet = $this->getPageLinks( $inputPages, $pageSet, $linkDepth ); |
| 201 | + } |
196 | 202 | |
197 | | - /* |
198 | | - // Enable this when we can do something useful exporting/importing image information. :) |
199 | | - if( $this->images ) ) { |
200 | | - $pageSet = $this->getImages( $inputPages, $pageSet ); |
201 | | - } |
202 | | - */ |
| 203 | + /* |
| 204 | + // Enable this when we can do something useful exporting/importing image information. :) |
| 205 | + if( $this->images ) ) { |
| 206 | + $pageSet = $this->getImages( $inputPages, $pageSet ); |
| 207 | + } |
| 208 | + */ |
203 | 209 | |
204 | | - $pages = array_keys( $pageSet ); |
| 210 | + $pages = array_keys( $pageSet ); |
205 | 211 | |
206 | | - /* Ok, let's get to it... */ |
207 | | - if( $history == WikiExporter::CURRENT ) { |
208 | | - $lb = false; |
209 | | - $db = wfGetDB( DB_SLAVE ); |
210 | | - $buffer = WikiExporter::BUFFER; |
211 | | - } else { |
212 | | - // Use an unbuffered query; histories may be very long! |
213 | | - $lb = wfGetLBFactory()->newMainLB(); |
214 | | - $db = $lb->getConnection( DB_SLAVE ); |
215 | | - $buffer = WikiExporter::STREAM; |
| 212 | + /* Ok, let's get to it... */ |
| 213 | + if( $history == WikiExporter::CURRENT ) { |
| 214 | + $lb = false; |
| 215 | + $db = wfGetDB( DB_SLAVE ); |
| 216 | + $buffer = WikiExporter::BUFFER; |
| 217 | + } else { |
| 218 | + // Use an unbuffered query; histories may be very long! |
| 219 | + $lb = wfGetLBFactory()->newMainLB(); |
| 220 | + $db = $lb->getConnection( DB_SLAVE ); |
| 221 | + $buffer = WikiExporter::STREAM; |
216 | 222 | |
217 | | - // This might take a while... :D |
218 | | - wfSuppressWarnings(); |
219 | | - set_time_limit(0); |
220 | | - wfRestoreWarnings(); |
221 | | - } |
222 | | - $exporter = new WikiExporter( $db, $history, $buffer ); |
223 | | - $exporter->list_authors = $list_authors; |
224 | | - $exporter->openStream(); |
225 | | - foreach( $pages as $page ) { |
226 | | - /* |
227 | | - if( $wgExportMaxHistory && !$this->curonly ) { |
228 | | - $title = Title::newFromText( $page ); |
229 | | - if( $title ) { |
230 | | - $count = Revision::countByTitle( $db, $title ); |
231 | | - if( $count > $wgExportMaxHistory ) { |
232 | | - wfDebug( __FUNCTION__ . |
233 | | - ": Skipped $page, $count revisions too big\n" ); |
234 | | - continue; |
235 | | - } |
236 | | - } |
237 | | - }*/ |
238 | | - #Bug 8824: Only export pages the user can read |
239 | | - $title = Title::newFromText( $page ); |
240 | | - if( is_null( $title ) ) continue; #TODO: perhaps output an <error> tag or something. |
241 | | - if( !$title->userCanRead() ) continue; #TODO: perhaps output an <error> tag or something. |
| 223 | + // This might take a while... :D |
| 224 | + wfSuppressWarnings(); |
| 225 | + set_time_limit(0); |
| 226 | + wfRestoreWarnings(); |
| 227 | + } |
| 228 | + $exporter = new WikiExporter( $db, $history, $buffer ); |
| 229 | + $exporter->list_authors = $list_authors; |
| 230 | + $exporter->openStream(); |
| 231 | + foreach( $pages as $page ) { |
| 232 | + /* |
| 233 | + if( $wgExportMaxHistory && !$this->curonly ) { |
| 234 | + $title = Title::newFromText( $page ); |
| 235 | + if( $title ) { |
| 236 | + $count = Revision::countByTitle( $db, $title ); |
| 237 | + if( $count > $wgExportMaxHistory ) { |
| 238 | + wfDebug( __FUNCTION__ . |
| 239 | + ": Skipped $page, $count revisions too big\n" ); |
| 240 | + continue; |
| 241 | + } |
| 242 | + } |
| 243 | + }*/ |
| 244 | + #Bug 8824: Only export pages the user can read |
| 245 | + $title = Title::newFromText( $page ); |
| 246 | + if( is_null( $title ) ) continue; #TODO: perhaps output an <error> tag or something. |
| 247 | + if( !$title->userCanRead() ) continue; #TODO: perhaps output an <error> tag or something. |
242 | 248 | |
243 | | - $exporter->pageByTitle( $title ); |
244 | | - } |
| 249 | + $exporter->pageByTitle( $title ); |
| 250 | + } |
245 | 251 | |
246 | | - $exporter->closeStream(); |
247 | | - if( $lb ) { |
248 | | - $lb->closeAll(); |
249 | | - } |
250 | | - } |
| 252 | + $exporter->closeStream(); |
| 253 | + if( $lb ) { |
| 254 | + $lb->closeAll(); |
| 255 | + } |
| 256 | + } |
251 | 257 | |
252 | 258 | |
253 | | - private function getPagesFromCategory( $title ) { |
254 | | - global $wgContLang; |
| 259 | + private function getPagesFromCategory( $title ) { |
| 260 | + global $wgContLang; |
255 | 261 | |
256 | | - $name = $title->getDBkey(); |
| 262 | + $name = $title->getDBkey(); |
257 | 263 | |
258 | | - $dbr = wfGetDB( DB_SLAVE ); |
259 | | - $res = $dbr->select( array('page', 'categorylinks' ), |
260 | | - array( 'page_namespace', 'page_title' ), |
261 | | - array('cl_from=page_id', 'cl_to' => $name ), |
262 | | - __METHOD__, array('LIMIT' => '5000')); |
| 264 | + $dbr = wfGetDB( DB_SLAVE ); |
| 265 | + $res = $dbr->select( array('page', 'categorylinks' ), |
| 266 | + array( 'page_namespace', 'page_title' ), |
| 267 | + array('cl_from=page_id', 'cl_to' => $name ), |
| 268 | + __METHOD__, array('LIMIT' => '5000')); |
263 | 269 | |
264 | | - $pages = array(); |
265 | | - while ( $row = $dbr->fetchObject( $res ) ) { |
266 | | - $n = $row->page_title; |
267 | | - if ($row->page_namespace) { |
268 | | - $ns = $wgContLang->getNsText( $row->page_namespace ); |
269 | | - $n = $ns . ':' . $n; |
270 | | - } |
| 270 | + $pages = array(); |
| 271 | + while ( $row = $dbr->fetchObject( $res ) ) { |
| 272 | + $n = $row->page_title; |
| 273 | + if ($row->page_namespace) { |
| 274 | + $ns = $wgContLang->getNsText( $row->page_namespace ); |
| 275 | + $n = $ns . ':' . $n; |
| 276 | + } |
271 | 277 | |
272 | | - $pages[] = $n; |
273 | | - } |
274 | | - $dbr->freeResult($res); |
| 278 | + $pages[] = $n; |
| 279 | + } |
| 280 | + $dbr->freeResult($res); |
275 | 281 | |
276 | | - return $pages; |
277 | | - } |
| 282 | + return $pages; |
| 283 | + } |
278 | 284 | |
279 | | - private function getPagesFromNamespace( $nsindex ) { |
280 | | - global $wgContLang; |
| 285 | + private function getPagesFromNamespace( $nsindex ) { |
| 286 | + global $wgContLang; |
281 | 287 | |
282 | | - $dbr = wfGetDB( DB_SLAVE ); |
283 | | - $res = $dbr->select( 'page', array('page_namespace', 'page_title'), |
284 | | - array('page_namespace' => $nsindex), |
285 | | - __METHOD__, array('LIMIT' => '5000') ); |
| 288 | + $dbr = wfGetDB( DB_SLAVE ); |
| 289 | + $res = $dbr->select( 'page', array('page_namespace', 'page_title'), |
| 290 | + array('page_namespace' => $nsindex), |
| 291 | + __METHOD__, array('LIMIT' => '5000') ); |
286 | 292 | |
287 | | - $pages = array(); |
288 | | - while ( $row = $dbr->fetchObject( $res ) ) { |
289 | | - $n = $row->page_title; |
290 | | - if ($row->page_namespace) { |
291 | | - $ns = $wgContLang->getNsText( $row->page_namespace ); |
292 | | - $n = $ns . ':' . $n; |
293 | | - } |
| 293 | + $pages = array(); |
| 294 | + while ( $row = $dbr->fetchObject( $res ) ) { |
| 295 | + $n = $row->page_title; |
| 296 | + if ($row->page_namespace) { |
| 297 | + $ns = $wgContLang->getNsText( $row->page_namespace ); |
| 298 | + $n = $ns . ':' . $n; |
| 299 | + } |
294 | 300 | |
295 | | - $pages[] = $n; |
296 | | - } |
297 | | - $dbr->freeResult($res); |
| 301 | + $pages[] = $n; |
| 302 | + } |
| 303 | + $dbr->freeResult($res); |
298 | 304 | |
299 | | - return $pages; |
300 | | - } |
301 | | - /** |
302 | | - * Expand a list of pages to include templates used in those pages. |
303 | | - * @param $inputPages array, list of titles to look up |
304 | | - * @param $pageSet array, associative array indexed by titles for output |
305 | | - * @return array associative array index by titles |
306 | | - */ |
307 | | - private function getTemplates( $inputPages, $pageSet ) { |
308 | | - return $this->getLinks( $inputPages, $pageSet, |
309 | | - 'templatelinks', |
310 | | - array( 'tl_namespace AS namespace', 'tl_title AS title' ), |
311 | | - array( 'page_id=tl_from' ) ); |
312 | | - } |
| 305 | + return $pages; |
| 306 | + } |
| 307 | + /** |
| 308 | + * Expand a list of pages to include templates used in those pages. |
| 309 | + * @param $inputPages array, list of titles to look up |
| 310 | + * @param $pageSet array, associative array indexed by titles for output |
| 311 | + * @return array associative array index by titles |
| 312 | + */ |
| 313 | + private function getTemplates( $inputPages, $pageSet ) { |
| 314 | + return $this->getLinks( $inputPages, $pageSet, |
| 315 | + 'templatelinks', |
| 316 | + array( 'tl_namespace AS namespace', 'tl_title AS title' ), |
| 317 | + array( 'page_id=tl_from' ) ); |
| 318 | + } |
313 | 319 | |
314 | | - /** |
315 | | - * Validate link depth setting, if available. |
316 | | - */ |
317 | | - private function validateLinkDepth( $depth ) { |
318 | | - global $wgExportMaxLinkDepth; |
319 | | - if( $depth < 0 ) { |
320 | | - return 0; |
| 320 | + /** |
| 321 | + * Validate link depth setting, if available. |
| 322 | + */ |
| 323 | + private function validateLinkDepth( $depth ) { |
| 324 | + global $wgExportMaxLinkDepth, $wgExportMaxLinkDepthLimit; |
| 325 | + if( $depth < 0 ) { |
| 326 | + return 0; |
| 327 | + } |
| 328 | + if ( !$this->userCanOverrideExportDepth() ) { |
| 329 | + if( $depth > $wgExportMaxLinkDepth ) { |
| 330 | + return $wgExportMaxLinkDepth; |
| 331 | + } |
321 | 332 | } |
322 | | - if( $depth > $wgExportMaxLinkDepth ) { |
323 | | - return $wgExportMaxLinkDepth; |
324 | | - } |
325 | | - return intval( $depth ); |
326 | | - } |
| 333 | + /* |
| 334 | + * There's a HARD CODED limit of 5 levels of recursion here to prevent a |
| 335 | + * crazy-big export from being done by someone setting the depth |
| 336 | + * number too high. In other words, last resort safety net. |
| 337 | + */ |
| 338 | + return intval( min( $depth, 5 ) ); |
| 339 | + } |
327 | 340 | |
328 | | - /** Expand a list of pages to include pages linked to from that page. */ |
329 | | - private function getPageLinks( $inputPages, $pageSet, $depth ) { |
330 | | - for( $depth=$depth; $depth>0; --$depth ) { |
331 | | - $pageSet = $this->getLinks( $inputPages, $pageSet, 'pagelinks', |
332 | | - array( 'pl_namespace AS namespace', 'pl_title AS title' ), |
333 | | - array( 'page_id=pl_from' ) ); |
334 | | - } |
335 | | - return $pageSet; |
336 | | - } |
| 341 | + /** Expand a list of pages to include pages linked to from that page. */ |
| 342 | + private function getPageLinks( $inputPages, $pageSet, $depth ) { |
| 343 | + for( $depth=$depth; $depth>0; --$depth ) { |
| 344 | + $pageSet = $this->getLinks( $inputPages, $pageSet, 'pagelinks', |
| 345 | + array( 'pl_namespace AS namespace', 'pl_title AS title' ), |
| 346 | + array( 'page_id=pl_from' ) ); |
| 347 | + } |
| 348 | + return $pageSet; |
| 349 | + } |
337 | 350 | |
338 | | - /** |
339 | | - * Expand a list of pages to include images used in those pages. |
340 | | - * @param $inputPages array, list of titles to look up |
341 | | - * @param $pageSet array, associative array indexed by titles for output |
342 | | - * @return array associative array index by titles |
343 | | - */ |
344 | | - private function getImages( $inputPages, $pageSet ) { |
345 | | - return $this->getLinks( $inputPages, $pageSet, |
346 | | - 'imagelinks', |
347 | | - array( NS_FILE . ' AS namespace', 'il_to AS title' ), |
348 | | - array( 'page_id=il_from' ) ); |
349 | | - } |
| 351 | + /** |
| 352 | + * Expand a list of pages to include images used in those pages. |
| 353 | + * @param $inputPages array, list of titles to look up |
| 354 | + * @param $pageSet array, associative array indexed by titles for output |
| 355 | + * @return array associative array index by titles |
| 356 | + */ |
| 357 | + private function getImages( $inputPages, $pageSet ) { |
| 358 | + return $this->getLinks( $inputPages, $pageSet, |
| 359 | + 'imagelinks', |
| 360 | + array( NS_FILE . ' AS namespace', 'il_to AS title' ), |
| 361 | + array( 'page_id=il_from' ) ); |
| 362 | + } |
350 | 363 | |
351 | | - /** |
352 | | - * Expand a list of pages to include items used in those pages. |
353 | | - * @private |
354 | | - */ |
355 | | - private function getLinks( $inputPages, $pageSet, $table, $fields, $join ) { |
356 | | - $dbr = wfGetDB( DB_SLAVE ); |
357 | | - foreach( $inputPages as $page ) { |
358 | | - $title = Title::newFromText( $page ); |
359 | | - if( $title ) { |
360 | | - $pageSet[$title->getPrefixedText()] = true; |
361 | | - /// @fixme May or may not be more efficient to batch these |
362 | | - /// by namespace when given multiple input pages. |
363 | | - $result = $dbr->select( |
364 | | - array( 'page', $table ), |
365 | | - $fields, |
366 | | - array_merge( $join, |
367 | | - array( |
368 | | - 'page_namespace' => $title->getNamespace(), |
369 | | - 'page_title' => $title->getDBKey() ) ), |
370 | | - __METHOD__ ); |
371 | | - foreach( $result as $row ) { |
372 | | - $template = Title::makeTitle( $row->namespace, $row->title ); |
373 | | - $pageSet[$template->getPrefixedText()] = true; |
374 | | - } |
375 | | - } |
376 | | - } |
377 | | - return $pageSet; |
378 | | - } |
| 364 | + /** |
| 365 | + * Expand a list of pages to include items used in those pages. |
| 366 | + * @private |
| 367 | + */ |
| 368 | + private function getLinks( $inputPages, $pageSet, $table, $fields, $join ) { |
| 369 | + $dbr = wfGetDB( DB_SLAVE ); |
| 370 | + foreach( $inputPages as $page ) { |
| 371 | + $title = Title::newFromText( $page ); |
| 372 | + if( $title ) { |
| 373 | + $pageSet[$title->getPrefixedText()] = true; |
| 374 | + /// @fixme May or may not be more efficient to batch these |
| 375 | + /// by namespace when given multiple input pages. |
| 376 | + $result = $dbr->select( |
| 377 | + array( 'page', $table ), |
| 378 | + $fields, |
| 379 | + array_merge( $join, |
| 380 | + array( |
| 381 | + 'page_namespace' => $title->getNamespace(), |
| 382 | + 'page_title' => $title->getDBKey() ) ), |
| 383 | + __METHOD__ ); |
| 384 | + foreach( $result as $row ) { |
| 385 | + $template = Title::makeTitle( $row->namespace, $row->title ); |
| 386 | + $pageSet[$template->getPrefixedText()] = true; |
| 387 | + } |
| 388 | + } |
| 389 | + } |
| 390 | + return $pageSet; |
| 391 | + } |
379 | 392 | |
380 | | - /** |
381 | | - * Callback function to remove empty strings from the pages array. |
382 | | - */ |
383 | | - private function filterPage( $page ) { |
384 | | - return $page !== '' && $page !== null; |
385 | | - } |
| 393 | + /** |
| 394 | + * Callback function to remove empty strings from the pages array. |
| 395 | + */ |
| 396 | + private function filterPage( $page ) { |
| 397 | + return $page !== '' && $page !== null; |
| 398 | + } |
386 | 399 | } |
| 400 | + |