/extensions/Translate/ffs/Simple.php

https://github.com/ChuguluGames/mediawiki-svn · PHP · 284 lines · 199 code · 60 blank · 25 comment · 23 complexity · 031e000361588b0871f8aea37b594f6f MD5 · raw file

  1. <?php
  2. /**
  3. * Simple file format handler for testing import and export.
  4. *
  5. * @author Niklas Laxström
  6. * @copyright Copyright © 2008-2010, Niklas Laxström
  7. * @license http://www.gnu.org/copyleft/gpl.html GNU General Public License 2.0 or later
  8. * @file
  9. */
  10. /**
  11. * Example implementation of old-style file format reader.
  12. * @see FFS
  13. */
  14. class SimpleFormatReader {
  15. const SEPARATOR = '----';
  16. const AUTHORPREFIX = 'Author: ';
  17. // One reader per file
  18. protected $filename = false;
  19. public function __construct( $filename ) {
  20. if ( is_readable( $filename ) ) {
  21. $this->filename = $filename;
  22. }
  23. }
  24. protected $authors = null;
  25. protected $staticHeader = '';
  26. public function parseAuthors() {
  27. if ( $this->authors === null ) {
  28. $this->parseHeader();
  29. }
  30. return $this->authors;
  31. }
  32. public function parseStaticHeader() {
  33. if ( $this->staticHeader === '' ) {
  34. $this->parseHeader();
  35. }
  36. return $this->staticHeader;
  37. }
  38. protected function parseHeader() {
  39. $authors = array();
  40. $staticHeader = '';
  41. if ( $this->filename !== false ) {
  42. $handle = fopen( $this->filename, "rt" );
  43. $state = 0;
  44. while ( !feof( $handle ) ) {
  45. $line = fgets( $handle );
  46. if ( $state === 0 ) {
  47. if ( $line === "\n" ) {
  48. $state = 1;
  49. continue;
  50. }
  51. $prefixLength = strlen( self::AUTHORPREFIX );
  52. $prefix = substr( $line, 0, $prefixLength );
  53. if ( strcasecmp( $prefix, self::AUTHORPREFIX ) === 0 ) {
  54. $authors[] = substr( $line, $prefixLength );
  55. }
  56. } elseif ( $state === 1 ) {
  57. if ( $line === self::SEPARATOR ) {
  58. break; // End of static header, if any
  59. }
  60. $staticHeader .= $line;
  61. }
  62. }
  63. fclose( $handle );
  64. }
  65. $this->authors = $authors;
  66. $this->staticHeader = $staticHeader;
  67. }
  68. protected $messagePattern = '/([^\0]+)\0([^\0]+)\0\n/U';
  69. public function parseMessages( StringMangler $mangler ) {
  70. $data = file_get_contents( $this->filename );
  71. $messages = array();
  72. $matches = array();
  73. preg_match_all( $this->messagePattern, $data, $matches, PREG_SET_ORDER );
  74. foreach ( $matches as $match ) {
  75. list( , $key, $value ) = $match;
  76. $messages[$key] = $value;
  77. }
  78. return $messages;
  79. }
  80. }
  81. /**
  82. * Example implementation of old-style file format writer.
  83. * @see FFS
  84. */
  85. class SimpleFormatWriter {
  86. const SEPARATOR = '----';
  87. const AUTHORPREFIX = 'Author: ';
  88. // Stored objects
  89. protected $group;
  90. // Stored data
  91. protected $authors, $staticHeader;
  92. public function __construct( MessageGroup $group ) {
  93. $this->group = $group;
  94. }
  95. public function addAuthors( array $authors, $code ) {
  96. if ( $this->authors === null ) {
  97. $this->authors = array();
  98. }
  99. if ( !isset( $this->authors[$code] ) ) {
  100. $this->authors[$code] = array();
  101. }
  102. /* Assuming there is only numerical keys, array_merge does the right thing
  103. * here, and wfMergeArray() not, because it overwrites instead of appends */
  104. $this->authors[$code] = array_merge( $this->authors[$code], $authors );
  105. $this->authors[$code] = array_unique( $this->authors[$code] );
  106. }
  107. public function load( $code ) {
  108. $reader = $this->group->getReader( $code );
  109. if ( $reader ) {
  110. $this->addAuthors( $reader->parseAuthors(), $code );
  111. $this->staticHeader = $reader->parseStaticHeader();
  112. }
  113. }
  114. public function fileExport( array $languages, $targetDirectory ) {
  115. foreach ( $languages as $code ) {
  116. $messages = $this->getMessagesForExport( $this->group, $code );
  117. if ( !count( $messages ) ) {
  118. continue;
  119. }
  120. $filename = $this->group->getMessageFile( $code );
  121. if ( !$filename ) {
  122. continue;
  123. }
  124. $target = $targetDirectory . '/' . $filename;
  125. wfMkdirParents( dirname( $target ), null, __METHOD__ );
  126. $handle = fopen( $target, 'wt' );
  127. if ( $handle === false ) {
  128. throw new MWException( "Unable to open target for writing" );
  129. }
  130. $this->exportLanguage( $handle, $messages );
  131. fclose( $handle );
  132. }
  133. }
  134. public function webExport( MessageCollection $collection ) {
  135. $code = $collection->code; // shorthand
  136. // Open temporary stream
  137. $handle = fopen( 'php://temp', 'wt' );
  138. $this->addAuthors( $collection->getAuthors(), $code );
  139. $this->exportLanguage( $handle, $collection );
  140. // Fetch data
  141. rewind( $handle );
  142. $data = stream_get_contents( $handle );
  143. fclose( $handle );
  144. return $data;
  145. }
  146. protected function getMessagesForExport( MessageGroup $group, $code ) {
  147. $collection = $this->group->initCollection( $code );
  148. $collection->setInfile( $this->group->load( $code ) );
  149. $collection->filter( 'ignored' );
  150. $collection->filter( 'hastranslation', false );
  151. $collection->loadTranslations();
  152. $this->addAuthors( $collection->getAuthors(), $code );
  153. return $collection;
  154. }
  155. protected function exportLanguage( $target, MessageCollection $collection ) {
  156. $this->load( $collection->code );
  157. $this->makeHeader( $target, $collection->code );
  158. $this->exportStaticHeader( $target );
  159. $this->exportMessages( $target, $collection );
  160. }
  161. // Writing three
  162. protected function makeHeader( $handle, $code ) {
  163. fwrite( $handle, $this->formatAuthors( self::AUTHORPREFIX, $code ) );
  164. fwrite( $handle, self::SEPARATOR . "\n" );
  165. }
  166. public function filterAuthors( array $authors, $code, $groupId ) {
  167. global $wgTranslateAuthorBlacklist;
  168. foreach ( $authors as $i => $v ) {
  169. $hash = "$groupId;$code;$v";
  170. $blacklisted = false;
  171. foreach ( $wgTranslateAuthorBlacklist as $rule ) {
  172. list( $type, $regex ) = $rule;
  173. if ( preg_match( $regex, $hash ) ) {
  174. if ( $type === 'white' ) {
  175. $blacklisted = false;
  176. break;
  177. } else {
  178. $blacklisted = true;
  179. }
  180. }
  181. }
  182. if ( $blacklisted ) {
  183. unset( $authors[$i] );
  184. }
  185. }
  186. return $authors;
  187. }
  188. protected function formatAuthors( $prefix, $code ) {
  189. // Check if there is any authors at all
  190. if ( empty( $this->authors[$code] ) ) {
  191. return '';
  192. }
  193. $groupId = $this->group->getId();
  194. $authors = $this->authors[$code];
  195. $authors = $this->filterAuthors( $authors, $code, $groupId );
  196. if ( empty( $authors ) ) {
  197. return '';
  198. }
  199. sort( $authors );
  200. $s = array();
  201. foreach ( $authors as $a ) {
  202. $s[] = $prefix . $a;
  203. }
  204. return implode( "\n", $s ) . "\n";
  205. }
  206. protected function exportStaticHeader( $target ) {
  207. if ( $this->staticHeader ) {
  208. fwrite( $target, $this->staticHeader . "\n" );
  209. }
  210. }
  211. protected function exportMessages( $handle, MessageCollection $collection ) {
  212. $mangler = $this->group->getMangler();
  213. foreach ( $collection as $item ) {
  214. $key = $mangler->unMangle( $item->key() );
  215. $value = str_replace( TRANSLATE_FUZZY, '', $item->translation() );
  216. fwrite( $handle, "$key\000$value\000\n" );
  217. }
  218. }
  219. protected function getLanguageNames( $code ) {
  220. $name = TranslateUtils::getLanguageName( $code );
  221. $native = TranslateUtils::getLanguageName( $code, true );
  222. return array( $name, $native );
  223. }
  224. }