Index: branches/wmf/1.18wmf1/includes/Export.php |
— | — | @@ -41,6 +41,7 @@ |
42 | 42 | const CURRENT = 2; |
43 | 43 | const STABLE = 4; // extension defined |
44 | 44 | const LOGS = 8; |
| 45 | + const RANGE = 16; |
45 | 46 | |
46 | 47 | const BUFFER = 0; |
47 | 48 | const STREAM = 1; |
— | — | @@ -56,7 +57,8 @@ |
57 | 58 | * main query is still running. |
58 | 59 | * |
59 | 60 | * @param $db Database |
60 | | - * @param $history Mixed: one of WikiExporter::FULL or WikiExporter::CURRENT, |
| 61 | + * @param $history Mixed: one of WikiExporter::FULL, WikiExporter::CURRENT, |
| 62 | + * WikiExporter::RANGE or WikiExporter::STABLE, |
61 | 63 | * or an associative array: |
62 | 64 | * offset: non-inclusive offset at which to start the query |
63 | 65 | * limit: maximum number of rows to return |
— | — | @@ -120,6 +122,21 @@ |
121 | 123 | } |
122 | 124 | |
123 | 125 | /** |
| 126 | + * Dumps a series of page and revision records for those pages |
| 127 | + * in the database with revisions falling within the rev_id range given. |
| 128 | + * @param $start Int: inclusive lower limit (this id is included) |
| 129 | + * @param $end Int: Exclusive upper limit (this id is not included) |
| 130 | + * If 0, no upper limit. |
| 131 | + */ |
| 132 | + public function revsByRange( $start, $end ) { |
| 133 | + $condition = 'rev_id >= ' . intval( $start ); |
| 134 | + if ( $end ) { |
| 135 | + $condition .= ' AND rev_id < ' . intval( $end ); |
| 136 | + } |
| 137 | + return $this->dumpFrom( $condition ); |
| 138 | + } |
| 139 | + |
| 140 | + /** |
124 | 141 | * @param $title Title |
125 | 142 | */ |
126 | 143 | public function pageByTitle( $title ) { |
— | — | @@ -259,6 +276,10 @@ |
260 | 277 | wfProfileOut( __METHOD__ ); |
261 | 278 | throw new MWException( __METHOD__ . " given invalid history dump type." ); |
262 | 279 | } |
| 280 | + } elseif ( $this->history & WikiExporter::RANGE ) { |
| 281 | + # Dump of revisions within a specified range |
| 282 | + $join['revision'] = array( 'INNER JOIN', 'page_id=rev_page' ); |
| 283 | + $opts['ORDER BY'] = 'rev_page ASC, rev_id ASC'; |
263 | 284 | } else { |
264 | 285 | # Uknown history specification parameter? |
265 | 286 | wfProfileOut( __METHOD__ ); |
— | — | @@ -354,10 +375,6 @@ |
355 | 376 | * @ingroup Dump |
356 | 377 | */ |
357 | 378 | class XmlDumpWriter { |
358 | | - var $firstPageWritten = 0; |
359 | | - var $lastPageWritten = 0; |
360 | | - var $pageInProgress = 0; |
361 | | - |
362 | 379 | /** |
363 | 380 | * Returns the export schema version. |
364 | 381 | * @return string |
— | — | @@ -461,7 +478,6 @@ |
462 | 479 | $title = Title::makeTitle( $row->page_namespace, $row->page_title ); |
463 | 480 | $out .= ' ' . Xml::elementClean( 'title', array(), $title->getPrefixedText() ) . "\n"; |
464 | 481 | $out .= ' ' . Xml::element( 'id', array(), strval( $row->page_id ) ) . "\n"; |
465 | | - $this->pageInProgress = $row->page_id; |
466 | 482 | if ( $row->page_is_redirect ) { |
467 | 483 | $out .= ' ' . Xml::element( 'redirect', array() ) . "\n"; |
468 | 484 | } |
— | — | @@ -482,10 +498,6 @@ |
483 | 499 | */ |
484 | 500 | function closePage() { |
485 | 501 | return " </page>\n"; |
486 | | - if (! $this->firstPageWritten) { |
487 | | - $this->firstPageWritten = $this->pageInProgress; |
488 | | - } |
489 | | - $this->lastPageWritten = $this->pageInProgress; |
490 | 502 | } |
491 | 503 | |
492 | 504 | /** |
— | — | @@ -632,7 +644,7 @@ |
633 | 645 | */ |
634 | 646 | function writeUpload( $file, $dumpContents = false ) { |
635 | 647 | if ( $file->isOld() ) { |
636 | | - $archiveName = " " . |
| 648 | + $archiveName = " " . |
637 | 649 | Xml::element( 'archivename', null, $file->getArchiveName() ) . "\n"; |
638 | 650 | } else { |
639 | 651 | $archiveName = ''; |
— | — | @@ -640,7 +652,7 @@ |
641 | 653 | if ( $dumpContents ) { |
642 | 654 | # Dump file as base64 |
643 | 655 | # Uses only XML-safe characters, so does not need escaping |
644 | | - $contents = ' <contents encoding="base64">' . |
| 656 | + $contents = ' <contents encoding="base64">' . |
645 | 657 | chunk_split( base64_encode( file_get_contents( $file->getPath() ) ) ) . |
646 | 658 | " </contents>\n"; |
647 | 659 | } else { |
— | — | @@ -651,7 +663,7 @@ |
652 | 664 | $this->writeContributor( $file->getUser( 'id' ), $file->getUser( 'text' ) ) . |
653 | 665 | " " . Xml::elementClean( 'comment', null, $file->getDescription() ) . "\n" . |
654 | 666 | " " . Xml::element( 'filename', null, $file->getName() ) . "\n" . |
655 | | - $archiveName . |
| 667 | + $archiveName . |
656 | 668 | " " . Xml::element( 'src', null, $file->getCanonicalUrl() ) . "\n" . |
657 | 669 | " " . Xml::element( 'size', null, $file->getSize() ) . "\n" . |
658 | 670 | " " . Xml::element( 'sha1base36', null, $file->getSha1() ) . "\n" . |
— | — | @@ -700,19 +712,33 @@ |
701 | 713 | print $string; |
702 | 714 | } |
703 | 715 | |
| 716 | + /** |
| 717 | + * Close the old file, move it to a specified name, |
| 718 | + * and reopen new file with the old name. Use this |
| 719 | + * for writing out a file in multiple pieces |
| 720 | + * at specified checkpoints (e.g. every n hours). |
| 721 | + * @param $newname mixed File name. May be a string or an array with one element |
| 722 | + */ |
704 | 723 | function closeRenameAndReopen( $newname ) { |
705 | 724 | return; |
706 | 725 | } |
707 | 726 | |
708 | | - function closeAndRename( $newname ) { |
| 727 | + /** |
| 728 | + * Close the old file, and move it to a specified name. |
| 729 | + * Use this for the last piece of a file written out |
| 730 | + * at specified checkpoints (e.g. every n hours). |
| 731 | + * @param $newname mixed File name. May be a string or an array with one element |
| 732 | + * @param $open bool If true, a new file with the old filename will be opened again for writing (default: false) |
| 733 | + */ |
| 734 | + function closeAndRename( $newname, $open = false ) { |
709 | 735 | return; |
710 | 736 | } |
711 | 737 | |
712 | | - function rename( $newname ) { |
713 | | - return; |
714 | | - } |
715 | | - |
716 | | - function getFilename() { |
| 738 | + /** |
| 739 | + * Returns the name of the file or files which are |
| 740 | + * being written to, if there are any. |
| 741 | + */ |
| 742 | + function getFilenames() { |
717 | 743 | return NULL; |
718 | 744 | } |
719 | 745 | } |
— | — | @@ -722,8 +748,7 @@ |
723 | 749 | * @ingroup Dump |
724 | 750 | */ |
725 | 751 | class DumpFileOutput extends DumpOutput { |
726 | | - var $handle; |
727 | | - var $filename; |
| 752 | + protected $handle, $filename; |
728 | 753 | |
729 | 754 | function __construct( $file ) { |
730 | 755 | $this->handle = fopen( $file, "wt" ); |
— | — | @@ -734,58 +759,39 @@ |
735 | 760 | fputs( $this->handle, $string ); |
736 | 761 | } |
737 | 762 | |
738 | | - /** |
739 | | - * Close the old file, move it to a specified name, |
740 | | - * and reopen new file with the old name. Use this |
741 | | - * for writing out a file in multiple pieces |
742 | | - * at specified checkpoints (e.g. every n hours). |
743 | | - */ |
744 | 763 | function closeRenameAndReopen( $newname ) { |
745 | | - if ( is_array($newname) ) { |
746 | | - if (count($newname) > 1) { |
747 | | - WfDie("Export closeRenameAndReopen: passed multiple argumnts for rename of single file\n"); |
748 | | - } |
749 | | - else { |
750 | | - $newname = $newname[0]; |
751 | | - } |
752 | | - } |
753 | | - if ( $newname ) { |
754 | | - fclose( $this->handle ); |
755 | | - rename( $this->filename, $newname ); |
756 | | - $this->handle = fopen( $this->filename, "wt" ); |
757 | | - } |
| 764 | + $this->closeAndRename( $newname, true ); |
758 | 765 | } |
759 | 766 | |
760 | | - function closeAndRename( $newname ) { |
761 | | - if ( is_array($newname) ) { |
762 | | - if (count($newname) > 1) { |
763 | | - throw new MWException("Export closeRenameAndReopen: passed multiple argumnts for rename of single file\n"); |
| 767 | + function renameOrException( $newname ) { |
| 768 | + if (! rename( $this->filename, $newname ) ) { |
| 769 | + throw new MWException( __METHOD__ . ": rename of file {$this->filename} to $newname failed\n" ); |
764 | 770 | } |
765 | | - else { |
| 771 | + } |
| 772 | + |
| 773 | + function checkRenameArgCount( $newname ) { |
| 774 | + if ( is_array( $newname ) ) { |
| 775 | + if ( count( $newname ) > 1 ) { |
| 776 | + throw new MWException( __METHOD__ . ": passed multiple arguments for rename of single file\n" ); |
| 777 | + } else { |
766 | 778 | $newname = $newname[0]; |
767 | 779 | } |
768 | 780 | } |
769 | | - if ( $newname ) { |
770 | | - fclose( $this->handle ); |
771 | | - rename( $this->filename, $newname ); |
772 | | - } |
| 781 | + return $newname; |
773 | 782 | } |
774 | 783 | |
775 | | - function rename( $newname ) { |
776 | | - if ( is_array($newname) ) { |
777 | | - if (count($newname) > 1) { |
778 | | - WfDie("Export closeRenameAndReopen: passed multiple argumnts for rename of single file\n"); |
| 784 | + function closeAndRename( $newname, $open = false ) { |
| 785 | + $newname = $this->checkRenameArgCount( $newname ); |
| 786 | + if ( $newname ) { |
| 787 | + fclose( $this->handle ); |
| 788 | + $this->renameOrException( $newname ); |
| 789 | + if ( $open ) { |
| 790 | + $this->handle = fopen( $this->filename, "wt" ); |
779 | 791 | } |
780 | | - else { |
781 | | - $newname = $newname[0]; |
782 | | - } |
783 | 792 | } |
784 | | - if ( $newname ) { |
785 | | - rename( $this->filename, $newname ); |
786 | | - } |
787 | 793 | } |
788 | 794 | |
789 | | - function getFilename() { |
| 795 | + function getFilenames() { |
790 | 796 | return $this->filename; |
791 | 797 | } |
792 | 798 | } |
— | — | @@ -797,19 +803,19 @@ |
798 | 804 | * @ingroup Dump |
799 | 805 | */ |
800 | 806 | class DumpPipeOutput extends DumpFileOutput { |
801 | | - var $command; |
| 807 | + protected $command, $filename; |
802 | 808 | |
803 | 809 | function __construct( $command, $file = null ) { |
804 | 810 | if ( !is_null( $file ) ) { |
805 | 811 | $command .= " > " . wfEscapeShellArg( $file ); |
806 | 812 | } |
807 | | - |
808 | | - $this->startCommand($command); |
| 813 | + |
| 814 | + $this->startCommand( $command ); |
809 | 815 | $this->command = $command; |
810 | 816 | $this->filename = $file; |
811 | 817 | } |
812 | 818 | |
813 | | - function startCommand($command) { |
| 819 | + function startCommand( $command ) { |
814 | 820 | $spec = array( |
815 | 821 | 0 => array( "pipe", "r" ), |
816 | 822 | ); |
— | — | @@ -818,59 +824,24 @@ |
819 | 825 | $this->handle = $pipes[0]; |
820 | 826 | } |
821 | 827 | |
822 | | - /** |
823 | | - * Close the old file, move it to a specified name, |
824 | | - * and reopen new file with the old name. |
825 | | - */ |
826 | 828 | function closeRenameAndReopen( $newname ) { |
827 | | - if ( is_array($newname) ) { |
828 | | - if (count($newname) > 1) { |
829 | | - WfDie("Export closeRenameAndReopen: passed multiple argumnts for rename of single file\n"); |
830 | | - } |
831 | | - else { |
832 | | - $newname = $newname[0]; |
833 | | - } |
834 | | - } |
835 | | - if ( $newname ) { |
836 | | - fclose( $this->handle ); |
837 | | - proc_close($this->procOpenResource); |
838 | | - rename( $this->filename, $newname ); |
839 | | - $command = $this->command; |
840 | | - $command .= " > " . wfEscapeShellArg( $this->filename ); |
841 | | - $this->startCommand($command); |
842 | | - } |
| 829 | + $this->closeAndRename( $newname, true ); |
843 | 830 | } |
844 | 831 | |
845 | | - function closeAndRename( $newname ) { |
846 | | - if ( is_array($newname) ) { |
847 | | - if (count($newname) > 1) { |
848 | | - throw new MWException("Export closeRenameAndReopen: passed multiple argumnts for rename of single file\n"); |
849 | | - } |
850 | | - else { |
851 | | - $newname = $newname[0]; |
852 | | - } |
853 | | - } |
| 832 | + function closeAndRename( $newname, $open = false ) { |
| 833 | + $newname = $this->checkRenameArgCount( $newname ); |
854 | 834 | if ( $newname ) { |
855 | | -# pclose( $this->handle ); |
856 | 835 | fclose( $this->handle ); |
857 | | - proc_close($this->procOpenResource); |
858 | | - rename( $this->filename, $newname ); |
859 | | - } |
860 | | - } |
861 | | - |
862 | | - function rename( $newname ) { |
863 | | - if ( is_array($newname) ) { |
864 | | - if (count($newname) > 1) { |
865 | | - WfDie("Export closeRenameAndReopen: passed multiple argumnts for rename of single file\n"); |
| 836 | + proc_close( $this->procOpenResource ); |
| 837 | + $this->renameOrException( $newname ); |
| 838 | + if ( $open ) { |
| 839 | + $command = $this->command; |
| 840 | + $command .= " > " . wfEscapeShellArg( $this->filename ); |
| 841 | + $this->startCommand( $command ); |
866 | 842 | } |
867 | | - else { |
868 | | - $newname = $newname[0]; |
869 | | - } |
870 | 843 | } |
871 | | - if ( $newname ) { |
872 | | - rename( $this->filename, $newname ); |
873 | | - } |
874 | 844 | } |
| 845 | + |
875 | 846 | } |
876 | 847 | |
877 | 848 | /** |
— | — | @@ -898,64 +869,37 @@ |
899 | 870 | * @ingroup Dump |
900 | 871 | */ |
901 | 872 | class Dump7ZipOutput extends DumpPipeOutput { |
902 | | - var $filename; |
| 873 | + protected $filename; |
903 | 874 | |
904 | 875 | function __construct( $file ) { |
| 876 | + $command = $this->setup7zCommand( $file ); |
| 877 | + parent::__construct( $command ); |
| 878 | + $this->filename = $file; |
| 879 | + } |
| 880 | + |
| 881 | + function setup7zCommand( $file ) { |
905 | 882 | $command = "7za a -bd -si " . wfEscapeShellArg( $file ); |
906 | 883 | // Suppress annoying useless crap from p7zip |
907 | 884 | // Unfortunately this could suppress real error messages too |
908 | 885 | $command .= ' >' . wfGetNull() . ' 2>&1'; |
909 | | - parent::__construct( $command ); |
910 | | - $this->filename = $file; |
| 886 | + return( $command ); |
911 | 887 | } |
912 | 888 | |
913 | 889 | function closeRenameAndReopen( $newname ) { |
914 | | - if ( is_array($newname) ) { |
915 | | - if (count($newname) > 1) { |
916 | | - WfDie("Export closeRenameAndReopen: passed multiple argumnts for rename of single file\n"); |
917 | | - } |
918 | | - else { |
919 | | - $newname = $newname[0]; |
920 | | - } |
921 | | - } |
922 | | - if ( $newname ) { |
923 | | - fclose( $this->handle ); |
924 | | - proc_close($this->procOpenResource); |
925 | | - rename( $this->filename, $newname ); |
926 | | - $command = "7za a -bd -si " . wfEscapeShellArg( $file ); |
927 | | - $command .= ' >' . wfGetNull() . ' 2>&1'; |
928 | | - $this->startCommand($command); |
929 | | - } |
| 890 | + $this->closeAndRename( $newname, true ); |
930 | 891 | } |
931 | 892 | |
932 | | - function closeAndRename( $newname ) { |
933 | | - if ( is_array($newname) ) { |
934 | | - if (count($newname) > 1) { |
935 | | - throw new MWException("Export closeRenameAndReopen: passed multiple argumnts for rename of single file\n"); |
936 | | - } |
937 | | - else { |
938 | | - $newname = $newname[0]; |
939 | | - } |
940 | | - } |
| 893 | + function closeAndRename( $newname, $open = false ) { |
| 894 | + $newname = $this->checkRenameArgCount( $newname ); |
941 | 895 | if ( $newname ) { |
942 | 896 | fclose( $this->handle ); |
943 | | - proc_close($this->procOpenResource); |
944 | | - rename( $this->filename, $newname ); |
945 | | - } |
946 | | - } |
947 | | - |
948 | | - function rename( $newname ) { |
949 | | - if ( is_array($newname) ) { |
950 | | - if (count($newname) > 1) { |
951 | | - WfDie("Export closeRenameAndReopen: passed multiple argumnts for rename of single file\n"); |
| 897 | + proc_close( $this->procOpenResource ); |
| 898 | + $this->renameOrException( $newname ); |
| 899 | + if ( $open ) { |
| 900 | + $command = $this->setup7zCommand( $file ); |
| 901 | + $this->startCommand( $command ); |
952 | 902 | } |
953 | | - else { |
954 | | - $newname = $newname[0]; |
955 | | - } |
956 | 903 | } |
957 | | - if ( $newname ) { |
958 | | - rename( $this->filename, $newname ); |
959 | | - } |
960 | 904 | } |
961 | 905 | } |
962 | 906 | |
— | — | @@ -1008,18 +952,14 @@ |
1009 | 953 | $this->sink->closeRenameAndReopen( $newname ); |
1010 | 954 | } |
1011 | 955 | |
1012 | | - function closeAndRename( $newname ) { |
1013 | | - $this->sink->closeAndRename( $newname ); |
| 956 | + function closeAndRename( $newname, $open = false ) { |
| 957 | + $this->sink->closeAndRename( $newname, $open ); |
1014 | 958 | } |
1015 | 959 | |
1016 | | - function rename( $newname ) { |
1017 | | - $this->sink->rename( $newname ); |
| 960 | + function getFilenames() { |
| 961 | + return $this->sink->getFilenames(); |
1018 | 962 | } |
1019 | 963 | |
1020 | | - function getFilename() { |
1021 | | - return $this->sink->getFilename(); |
1022 | | - } |
1023 | | - |
1024 | 964 | /** |
1025 | 965 | * Override for page-based filter types. |
1026 | 966 | * @return bool |
— | — | @@ -1169,26 +1109,19 @@ |
1170 | 1110 | } |
1171 | 1111 | |
1172 | 1112 | function closeRenameAndReopen( $newnames ) { |
1173 | | - for( $i = 0; $i < $this->count; $i++ ) { |
1174 | | - $this->sinks[$i]->closeRenameAndReopen( $newnames[$i] ); |
1175 | | - } |
| 1113 | + $this->closeAndRename( $newnames, true ); |
1176 | 1114 | } |
1177 | 1115 | |
1178 | | - function closeAndRename( $newname ) { |
1179 | | - for( $i = 0; $i < $this->count; $i++ ) { |
1180 | | - $this->sinks[$i]->closeAndRename( $newnames[$i] ); |
| 1116 | + function closeAndRename( $newnames, $open = false ) { |
| 1117 | + for ( $i = 0; $i < $this->count; $i++ ) { |
| 1118 | + $this->sinks[$i]->closeAndRename( $newnames[$i], $open ); |
1181 | 1119 | } |
1182 | 1120 | } |
1183 | | - function rename( $newnames ) { |
1184 | | - for( $i = 0; $i < $this->count; $i++ ) { |
1185 | | - $this->sinks[$i]->rename( $newnames[$i] ); |
1186 | | - } |
1187 | | - } |
1188 | 1121 | |
1189 | | - function getFilename() { |
| 1122 | + function getFilenames() { |
1190 | 1123 | $filenames = array(); |
1191 | | - for( $i = 0; $i < $this->count; $i++ ) { |
1192 | | - $filenames[] = $this->sinks[$i]->getFilename(); |
| 1124 | + for ( $i = 0; $i < $this->count; $i++ ) { |
| 1125 | + $filenames[] = $this->sinks[$i]->getFilenames(); |
1193 | 1126 | } |
1194 | 1127 | return $filenames; |
1195 | 1128 | } |
Property changes on: branches/wmf/1.18wmf1/includes |
___________________________________________________________________ |
Modified: svn:mergeinfo |
1196 | 1129 | Merged /branches/REL1_18/phase3/includes:r103054 |
Property changes on: branches/wmf/1.18wmf1 |
___________________________________________________________________ |
Modified: svn:mergeinfo |
1197 | 1130 | Merged /branches/REL1_18/phase3:r103054 |