]> scripts.mit.edu Git - autoinstalls/mediawiki.git/blob - includes/specials/SpecialExport.php
MediaWiki 1.14.0
[autoinstalls/mediawiki.git] / includes / specials / SpecialExport.php
1 <?php
2 # Copyright (C) 2003-2008 Brion Vibber <brion@pobox.com>
3 # http://www.mediawiki.org/
4 #
5 # This program is free software; you can redistribute it and/or modify
6 # it under the terms of the GNU General Public License as published by
7 # the Free Software Foundation; either version 2 of the License, or
8 # (at your option) any later version.
9 #
10 # This program is distributed in the hope that it will be useful,
11 # but WITHOUT ANY WARRANTY; without even the implied warranty of
12 # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13 # GNU General Public License for more details.
14 #
15 # You should have received a copy of the GNU General Public License along
16 # with this program; if not, write to the Free Software Foundation, Inc.,
17 # 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
18 # http://www.gnu.org/copyleft/gpl.html
19 /**
20  * @file
21  * @ingroup SpecialPage
22  */
23
24 function wfExportGetPagesFromCategory( $title ) {
25         global $wgContLang;
26
27         $name = $title->getDBkey();
28
29         $dbr = wfGetDB( DB_SLAVE );
30
31         list( $page, $categorylinks ) = $dbr->tableNamesN( 'page', 'categorylinks' );
32         $sql = "SELECT page_namespace, page_title FROM $page " .
33                 "JOIN $categorylinks ON cl_from = page_id " .
34                 "WHERE cl_to = " . $dbr->addQuotes( $name );
35
36         $pages = array();
37         $res = $dbr->query( $sql, 'wfExportGetPagesFromCategory' );
38         while ( $row = $dbr->fetchObject( $res ) ) {
39                 $n = $row->page_title;
40                 if ($row->page_namespace) {
41                         $ns = $wgContLang->getNsText( $row->page_namespace );
42                         $n = $ns . ':' . $n;
43                 }
44
45                 $pages[] = $n;
46         }
47         $dbr->freeResult($res);
48
49         return $pages;
50 }
51
52 /**
53  * Expand a list of pages to include templates used in those pages.
54  * @param $inputPages array, list of titles to look up
55  * @param $pageSet array, associative array indexed by titles for output
56  * @return array associative array index by titles
57  */
58 function wfExportGetTemplates( $inputPages, $pageSet ) {
59         return wfExportGetLinks( $inputPages, $pageSet,
60                 'templatelinks',
61                 array( 'tl_namespace AS namespace', 'tl_title AS title' ),
62                 array( 'page_id=tl_from' ) );
63 }
64
65 /**
66  * Expand a list of pages to include images used in those pages.
67  * @param $inputPages array, list of titles to look up
68  * @param $pageSet array, associative array indexed by titles for output
69  * @return array associative array index by titles
70  */
71 function wfExportGetImages( $inputPages, $pageSet ) {
72         return wfExportGetLinks( $inputPages, $pageSet,
73                 'imagelinks',
74                 array( NS_FILE . ' AS namespace', 'il_to AS title' ),
75                 array( 'page_id=il_from' ) );
76 }
77
78 /**
79  * Expand a list of pages to include items used in those pages.
80  * @private
81  */
82 function wfExportGetLinks( $inputPages, $pageSet, $table, $fields, $join ) {
83         $dbr = wfGetDB( DB_SLAVE );
84         foreach( $inputPages as $page ) {
85                 $title = Title::newFromText( $page );
86                 if( $title ) {
87                         $pageSet[$title->getPrefixedText()] = true;
88                         /// @fixme May or may not be more efficient to batch these
89                         ///        by namespace when given multiple input pages.
90                         $result = $dbr->select(
91                                 array( 'page', $table ),
92                                 $fields,
93                                 array_merge( $join,
94                                         array(
95                                                 'page_namespace' => $title->getNamespace(),
96                                                 'page_title' => $title->getDBKey() ) ),
97                                 __METHOD__ );
98                         foreach( $result as $row ) {
99                                 $template = Title::makeTitle( $row->namespace, $row->title );
100                                 $pageSet[$template->getPrefixedText()] = true;
101                         }
102                 }
103         }
104         return $pageSet;
105 }
106
107 /**
108  * Callback function to remove empty strings from the pages array.
109  */
110 function wfFilterPage( $page ) {
111         return $page !== '' && $page !== null;
112 }
113
114 /**
115  *
116  */
117 function wfSpecialExport( $page = '' ) {
118         global $wgOut, $wgRequest, $wgSitename, $wgExportAllowListContributors;
119         global $wgExportAllowHistory, $wgExportMaxHistory;
120
121         $curonly = true;
122         $doexport = false;
123
124         if ( $wgRequest->getCheck( 'addcat' ) ) {
125                 $page = $wgRequest->getText( 'pages' );
126                 $catname = $wgRequest->getText( 'catname' );
127
128                 if ( $catname !== '' && $catname !== NULL && $catname !== false ) {
129                         $t = Title::makeTitleSafe( NS_MAIN, $catname );
130                         if ( $t ) {
131                                 /**
132                                  * @fixme This can lead to hitting memory limit for very large
133                                  * categories. Ideally we would do the lookup synchronously
134                                  * during the export in a single query.
135                                  */
136                                 $catpages = wfExportGetPagesFromCategory( $t );
137                                 if ( $catpages ) $page .= "\n" . implode( "\n", $catpages );
138                         }
139                 }
140         }
141         else if( $wgRequest->wasPosted() && $page == '' ) {
142                 $page = $wgRequest->getText( 'pages' );
143                 $curonly = $wgRequest->getCheck( 'curonly' );
144                 $rawOffset = $wgRequest->getVal( 'offset' );
145                 if( $rawOffset ) {
146                         $offset = wfTimestamp( TS_MW, $rawOffset );
147                 } else {
148                         $offset = null;
149                 }
150                 $limit = $wgRequest->getInt( 'limit' );
151                 $dir = $wgRequest->getVal( 'dir' );
152                 $history = array(
153                         'dir' => 'asc',
154                         'offset' => false,
155                         'limit' => $wgExportMaxHistory,
156                 );
157                 $historyCheck = $wgRequest->getCheck( 'history' );
158                 if ( $curonly ) {
159                         $history = WikiExporter::CURRENT;
160                 } elseif ( !$historyCheck ) {
161                         if ( $limit > 0 && $limit < $wgExportMaxHistory ) {
162                                 $history['limit'] = $limit;
163                         }
164                         if ( !is_null( $offset ) ) {
165                                 $history['offset'] = $offset;
166                         }
167                         if ( strtolower( $dir ) == 'desc' ) {
168                                 $history['dir'] = 'desc';
169                         }
170                 }
171
172                 if( $page != '' ) $doexport = true;
173         } else {
174                 // Default to current-only for GET requests
175                 $page = $wgRequest->getText( 'pages', $page );
176                 $historyCheck = $wgRequest->getCheck( 'history' );
177                 if( $historyCheck ) {
178                         $history = WikiExporter::FULL;
179                 } else {
180                         $history = WikiExporter::CURRENT;
181                 }
182
183                 if( $page != '' ) $doexport = true;
184         }
185
186         if( !$wgExportAllowHistory ) {
187                 // Override
188                 $history = WikiExporter::CURRENT;
189         }
190
191         $list_authors = $wgRequest->getCheck( 'listauthors' );
192         if ( !$curonly || !$wgExportAllowListContributors ) $list_authors = false ;
193
194         if ( $doexport ) {
195                 $wgOut->disable();
196
197                 // Cancel output buffering and gzipping if set
198                 // This should provide safer streaming for pages with history
199                 wfResetOutputBuffers();
200                 header( "Content-type: application/xml; charset=utf-8" );
201                 if( $wgRequest->getCheck( 'wpDownload' ) ) {
202                         // Provide a sane filename suggestion
203                         $filename = urlencode( $wgSitename . '-' . wfTimestampNow() . '.xml' );
204                         $wgRequest->response()->header( "Content-disposition: attachment;filename={$filename}" );
205                 }
206
207                 /* Split up the input and look up linked pages */
208                 $inputPages = array_filter( explode( "\n", $page ), 'wfFilterPage' );
209                 $pageSet = array_flip( $inputPages );
210
211                 if( $wgRequest->getCheck( 'templates' ) ) {
212                         $pageSet = wfExportGetTemplates( $inputPages, $pageSet );
213                 }
214
215                 /*
216                 // Enable this when we can do something useful exporting/importing image information. :)
217                 if( $wgRequest->getCheck( 'images' ) ) {
218                         $pageSet = wfExportGetImages( $inputPages, $pageSet );
219                 }
220                 */
221
222                 $pages = array_keys( $pageSet );
223
224                 /* Ok, let's get to it... */
225
226                 if( $history == WikiExporter::CURRENT ) {
227                         $lb = false;
228                         $db = wfGetDB( DB_SLAVE );
229                         $buffer = WikiExporter::BUFFER;
230                 } else {
231                         // Use an unbuffered query; histories may be very long!
232                         $lb = wfGetLBFactory()->newMainLB();
233                         $db = $lb->getConnection( DB_SLAVE );
234                         $buffer = WikiExporter::STREAM;
235                         
236                         // This might take a while... :D
237                         wfSuppressWarnings();
238                         set_time_limit(0);
239                         wfRestoreWarnings();
240                 }
241
242                 $exporter = new WikiExporter( $db, $history, $buffer );
243                 $exporter->list_authors = $list_authors ;
244                 $exporter->openStream();
245
246                 foreach( $pages as $page ) {
247                         /*
248                         if( $wgExportMaxHistory && !$curonly ) {
249                                 $title = Title::newFromText( $page );
250                                 if( $title ) {
251                                         $count = Revision::countByTitle( $db, $title );
252                                         if( $count > $wgExportMaxHistory ) {
253                                                 wfDebug( __FUNCTION__ .
254                                                         ": Skipped $page, $count revisions too big\n" );
255                                                 continue;
256                                         }
257                                 }
258                         }*/
259
260                         #Bug 8824: Only export pages the user can read
261                         $title = Title::newFromText( $page );
262                         if( is_null( $title ) ) continue; #TODO: perhaps output an <error> tag or something.
263                         if( !$title->userCanRead() ) continue; #TODO: perhaps output an <error> tag or something.
264
265                         $exporter->pageByTitle( $title );
266                 }
267
268                 $exporter->closeStream();
269                 if( $lb ) {
270                         $lb->closeAll();
271                 }
272                 return;
273         }
274
275         $self = SpecialPage::getTitleFor( 'Export' );
276         $wgOut->addHTML( wfMsgExt( 'exporttext', 'parse' ) );
277
278         $form = Xml::openElement( 'form', array( 'method' => 'post',
279                 'action' => $self->getLocalUrl( 'action=submit' ) ) );
280
281         $form .= Xml::inputLabel( wfMsg( 'export-addcattext' )  , 'catname', 'catname', 40 ) . '&nbsp;';
282         $form .= Xml::submitButton( wfMsg( 'export-addcat' ), array( 'name' => 'addcat' ) ) . '<br />';
283
284         $form .= Xml::openElement( 'textarea', array( 'name' => 'pages', 'cols' => 40, 'rows' => 10 ) );
285         $form .= htmlspecialchars( $page );
286         $form .= Xml::closeElement( 'textarea' );
287         $form .= '<br />';
288
289         if( $wgExportAllowHistory ) {
290                 $form .= Xml::checkLabel( wfMsg( 'exportcuronly' ), 'curonly', 'curonly', true ) . '<br />';
291         } else {
292                 $wgOut->addHTML( wfMsgExt( 'exportnohistory', 'parse' ) );
293         }
294         $form .= Xml::checkLabel( wfMsg( 'export-templates' ), 'templates', 'wpExportTemplates', false ) . '<br />';
295         // Enable this when we can do something useful exporting/importing image information. :)
296         //$form .= Xml::checkLabel( wfMsg( 'export-images' ), 'images', 'wpExportImages', false ) . '<br />';
297         $form .= Xml::checkLabel( wfMsg( 'export-download' ), 'wpDownload', 'wpDownload', true ) . '<br />';
298
299         $form .= Xml::submitButton( wfMsg( 'export-submit' ), array( 'accesskey' => 's' ) );
300         $form .= Xml::closeElement( 'form' );
301         $wgOut->addHTML( $form );
302 }