PageRenderTime 22ms CodeModel.GetById 24ms RepoModel.GetById 1ms app.codeStats 0ms

/extensions/Translate/scripts/magic-export.php

https://github.com/ChuguluGames/mediawiki-svn
PHP | 306 lines | 216 code | 41 blank | 49 comment | 21 complexity | eefe94611ca0845edcb40b2a61b6f95b MD5 | raw file
  1. <?php
  2. /**
  3. * Script to export special page aliases and magic words of extensions.
  4. *
  5. * @author Robert Leverington <robert@rhl.me.uk>
  6. *
  7. * @copyright Copyright © 2010 Robert Leverington
  8. * @license http://www.gnu.org/copyleft/gpl.html GNU General Public License 2.0 or later
  9. * @file
  10. */
  11. require( dirname( dirname( dirname( dirname( __FILE__ ) ) ) ) . '/maintenance/Maintenance.php' );
  12. /**
  13. * Maintenance class for the fast export of special page aliases and magic words.
  14. */
  15. class MagicExport extends Maintenance {
  16. protected $type;
  17. protected $target;
  18. protected $handles = array();
  19. protected $messagesOld = array();
  20. public function __construct() {
  21. parent::__construct();
  22. $this->addOption( 'target', 'Target directory for exported files', true, true );
  23. $this->addOption( 'type', 'magic or special', true, true );
  24. }
  25. public function execute() {
  26. $this->target = $this->getOption( 'target' );
  27. $this->type = $this->getOption( 'type' );
  28. switch( $this->type ) {
  29. case 'special':
  30. case 'magic':
  31. break;
  32. default:
  33. die( 'Invalid type.' );
  34. }
  35. $this->openHandles();
  36. $this->writeHeaders();
  37. $this->writeFiles();
  38. $this->writeFooters();
  39. $this->closeHandles();
  40. }
  41. /**
  42. * Itterate through all groups, loading current data from the existing
  43. * extension and opening message files for message output.
  44. * - If the group does not define a special page alias file or magic
  45. * words file, or that file does not exist, it is ignored silently.
  46. * - If the file does contain a data array (e.g. $aliases) then the
  47. * program exits.
  48. */
  49. protected function openHandles() {
  50. $this->output( "Opening file handles and loading current data...\n" );
  51. $groups = MessageGroups::singleton()->getGroups();
  52. foreach ( $groups as $group ) {
  53. if ( !$group instanceof ExtensionMessageGroup ) {
  54. continue;
  55. }
  56. switch ( $this->type ) {
  57. case 'special':
  58. $filename = $group->getAliasFile();
  59. break;
  60. case 'magic':
  61. $filename = $group->getMagicFile();
  62. break;
  63. }
  64. if ( $filename === null ) {
  65. continue;
  66. }
  67. global $wgTranslateExtensionDirectory;
  68. $inFile = "$wgTranslateExtensionDirectory/$filename";
  69. if ( !file_exists( $inFile ) ) {
  70. continue;
  71. }
  72. include( $inFile );
  73. switch( $this->type ) {
  74. case 'special':
  75. if ( isset( $aliases ) ) {
  76. $this->messagesOld[$group->getId()] = $aliases;
  77. unset( $aliases );
  78. } elseif ( isset( $specialPageAliases ) ) {
  79. $this->messagesOld[$group->getId()] = $specialPageAliases;
  80. unset( $specialPageAliases );
  81. } else {
  82. die( "File '$inFile' does not contain an aliases array.\n" );
  83. }
  84. break;
  85. case 'magic':
  86. if ( !isset( $magicWords ) ) {
  87. die( "File '$inFile' does not contain a magic words array.\n" );
  88. }
  89. $this->messagesOld[$group->getId()] = $magicWords;
  90. unset( $magicWords );
  91. break;
  92. }
  93. $outFile = $this->target . '/' . $filename;
  94. wfMkdirParents( dirname( $outFile ), null, __METHOD__ );
  95. $this->handles[$group->getId()] = fopen( $outFile, 'w' );
  96. fwrite( $this->handles[$group->getId()], $this->readHeader( $inFile ) );
  97. $this->output( "\t{$group->getId()}\n" );
  98. }
  99. }
  100. protected function readHeader( $file ) {
  101. $data = file_get_contents( $file );
  102. // Seek first '*/'.
  103. $end = strpos( $data, '*/' ) + 2;
  104. if ( $end === false ) {
  105. return "<?php\n";
  106. }
  107. // Grab header.
  108. return substr( $data, 0, $end );
  109. }
  110. /**
  111. * Write the opening of the files for each output file handle.
  112. */
  113. protected function writeHeaders() {
  114. foreach ( $this->handles as $handle ) {
  115. switch( $this->type ) {
  116. case 'special':
  117. fwrite( $handle, <<<PHP
  118. \$specialPageAliases = array();
  119. PHP
  120. );
  121. break;
  122. case 'magic':
  123. fwrite( $handle, <<<PHP
  124. \$magicWords = array();
  125. PHP
  126. );
  127. break;
  128. }
  129. }
  130. }
  131. /**
  132. * Itterate through available languages, loading and parsing the data
  133. * message from the MediaWiki namespace and writing the data to its output
  134. * file handle.
  135. */
  136. protected function writeFiles() {
  137. $langs = self::parseLanguageCodes( '*' );
  138. unset( $langs[array_search( 'en', $langs )] );
  139. $langs = array_merge( array( 'en' ), $langs );
  140. foreach ( $langs as $l ) {
  141. // Load message page.
  142. switch ( $this->type ) {
  143. case 'special':
  144. $title = Title::makeTitleSafe( NS_MEDIAWIKI, 'Sp-translate-data-SpecialPageAliases/' . $l );
  145. break;
  146. case 'magic':
  147. $title = Title::makeTitleSafe( NS_MEDIAWIKI, 'Sp-translate-data-MagicWords/' . $l );
  148. break;
  149. default:
  150. exit( 1 );
  151. }
  152. // Parse message page.
  153. if ( !$title || !$title->exists() ) {
  154. $this->output( "Skiping $l...\n" );
  155. $messagesNew = array();
  156. } else {
  157. $this->output( "Processing $l...\n" );
  158. $article = new Article( $title );
  159. $data = $article->getContent();
  160. // Parse message file.
  161. $segments = explode( "\n", $data );
  162. array_shift( $segments );
  163. array_shift( $segments );
  164. unset( $segments[count( $segments ) -1] );
  165. unset( $segments[count( $segments ) -1] );
  166. $messagesNew = array();
  167. foreach ( $segments as $segment ) {
  168. $parts = explode( ' = ', $segment );
  169. $key = array_shift( $parts );
  170. $translations = explode( ', ', implode( $parts ) );
  171. $messagesNew[$key] = $translations;
  172. }
  173. }
  174. // Write data to handles.
  175. $namesEn = LanguageNames::getNames( 'en' );
  176. $namesNative = Language::getLanguageNames();
  177. foreach ( $this->handles as $group => $handle ) {
  178. // Find messages to write to this handle.
  179. $messagesOut = array();
  180. foreach ( $this->messagesOld[$group]['en'] as $key => $message ) {
  181. if ( array_key_exists( $key, $messagesNew ) ) {
  182. $messagesOut[$key] = $messagesNew[$key];
  183. } elseif ( isset( $this->messagesOld[$group][$l][$key] ) ) {
  184. $messagesOut[$key] = $this->messagesOld[$group][$l][$key];
  185. }
  186. }
  187. // If there are messages to write, write them.
  188. if ( count( $messagesOut ) > 0 ) {
  189. switch( $this->type ) {
  190. case 'special':
  191. $out = "\n\n/** {$namesEn[$l]} ({$namesNative[$l]}) */\n\$specialPageAliases['{$l}'] = array(\n";
  192. break;
  193. case 'magic':
  194. $out = "\n\n/** {$namesEn[$l]} ({$namesNative[$l]}) */\n\$magicWords['{$l}'] = array(\n";
  195. break;
  196. }
  197. foreach ( $messagesOut as $key => $translations ) {
  198. foreach ( $translations as $id => $translation ) {
  199. $translations[$id] = addslashes( $translation );
  200. if ( $this->type === 'magic' && $translation == '0' ) {
  201. unset( $translations[$id] );
  202. }
  203. }
  204. $translations = implode( "', '", $translations );
  205. switch( $this->type ) {
  206. case 'special':
  207. $out .= "\t'$key' => array( '$translations' ),\n";
  208. break;
  209. case 'magic':
  210. if ( $this->messagesOld[$group]['en'][$key][0] === 0 ) {
  211. $out .= "\t'$key' => array( 0, '$translations' ),\n";
  212. } else {
  213. $out .= "\t'$key' => array( '$translations' ),\n";
  214. }
  215. break;
  216. }
  217. }
  218. $out .= ");";
  219. fwrite( $handle, $out );
  220. }
  221. }
  222. }
  223. }
  224. /**
  225. * For special page aliases we set $aliases as a reference to
  226. * the more modern $specialPageAliases for backwards compatibility.
  227. */
  228. protected function writeFooters() {
  229. $this->output( "Writing file footers...\n" );
  230. if ( $this->type === 'special' ) {
  231. foreach ( $this->handles as $handle ) {
  232. fwrite( $handle, <<<PHP
  233. /**
  234. * For backwards compatibility with MediaWiki 1.15 and earlier.
  235. */
  236. \$aliases =& \$specialPageAliases;
  237. PHP
  238. );
  239. }
  240. }
  241. }
  242. /**
  243. * Close all output file handles.
  244. */
  245. protected function closeHandles() {
  246. $this->output( "Closing file handles...\n" );
  247. foreach ( $this->handles as $handle ) {
  248. fclose( $handle );
  249. }
  250. }
  251. /**
  252. * Copied from cli.inc.
  253. */
  254. private static function parseLanguageCodes( /* string */ $codes ) {
  255. $langs = array_map( 'trim', explode( ',', $codes ) );
  256. if ( $langs[0] === '*' ) {
  257. $languages = Language::getLanguageNames();
  258. ksort( $languages );
  259. $langs = array_keys( $languages );
  260. }
  261. return $langs;
  262. }
  263. }
  264. $maintClass = "MagicExport";
  265. require_once( DO_MAINTENANCE );