Translate extension for MediaWiki
 
Loading...
Searching...
No Matches
TranslateYaml.php
Go to the documentation of this file.
1<?php
12use MediaWiki\Shell\Shell;
13
24 public static function loadString( $text ) {
25 global $wgTranslateYamlLibrary;
26
27 switch ( $wgTranslateYamlLibrary ) {
28 case 'phpyaml':
29 // Harden: do not support unserializing objects.
30 $previousValue = ini_set( 'yaml.decode_php', false );
31 $ret = yaml_parse( $text );
32 ini_set( 'yaml.decode_php', $previousValue );
33 if ( $ret === false ) {
34 // Convert failures to exceptions
35 throw new InvalidArgumentException( 'Invalid Yaml string' );
36 }
37
38 return $ret;
39 case 'spyc':
40 $yaml = spyc_load( $text );
41
42 return self::fixSpycSpaces( $yaml );
43 case 'syck':
44 $yaml = self::syckLoad( $text );
45
46 return self::fixSyckBooleans( $yaml );
47 default:
48 throw new MWException( 'Unknown Yaml library' );
49 }
50 }
51
56 public static function fixSyckBooleans( &$yaml ) {
57 foreach ( $yaml as &$value ) {
58 if ( is_array( $value ) ) {
59 self::fixSyckBooleans( $value );
60 } elseif ( $value === 'yes' ) {
61 $value = true;
62 }
63 }
64
65 return $yaml;
66 }
67
72 public static function fixSpycSpaces( &$yaml ) {
73 foreach ( $yaml as $key => &$value ) {
74 if ( is_array( $value ) ) {
75 self::fixSpycSpaces( $value );
76 } elseif ( is_string( $value ) && $key === 'header' ) {
77 $value = preg_replace( '~^\*~m', ' *', $value ) . "\n";
78 }
79 }
80
81 return $yaml;
82 }
83
84 public static function load( $file ) {
85 $text = file_get_contents( $file );
86
87 return self::loadString( $text );
88 }
89
90 public static function dump( $text ) {
91 global $wgTranslateYamlLibrary;
92
93 switch ( $wgTranslateYamlLibrary ) {
94 case 'phpyaml':
95 return self::phpyamlDump( $text );
96 case 'spyc':
97 return Spyc::YAMLDump( $text );
98 case 'syck':
99 return self::syckDump( $text );
100 default:
101 throw new MWException( 'Unknown Yaml library' );
102 }
103 }
104
105 protected static function phpyamlDump( $data ) {
106 return yaml_emit( $data, YAML_UTF8_ENCODING );
107 }
108
109 protected static function syckLoad( $data ) {
110 # Make temporary file
111 $td = wfTempDir();
112 $tf = tempnam( $td, 'yaml-load-' );
113
114 # Write to file
115 file_put_contents( $tf, $data );
116
117 $cmd = "perl -MYAML::Syck=LoadFile -MPHP::Serialization=serialize -wle '" .
118 'my $tf = q[' . $tf . '];' .
119 'my $yaml = LoadFile($tf);' .
120 'open my $fh, ">", "$tf.serialized" or die qq[Can not open "$tf.serialized"];' .
121 'print $fh serialize($yaml);' .
122 'close($fh);' .
123 "'";
124
125 self::runCommand( $cmd );
126
127 $serialized = file_get_contents( "$tf.serialized" );
128 $php_data = unserialize( $serialized );
129
130 unlink( $tf );
131 unlink( "$tf.serialized" );
132
133 return $php_data;
134 }
135
136 protected static function syckDump( $data ) {
137 # Make temporary file
138 $td = wfTempDir();
139 $tf = tempnam( $td, 'yaml-load-' );
140
141 # Write to file
142 $sdata = serialize( $data );
143 file_put_contents( $tf, $sdata );
144
145 $cmd = "perl -MYAML::Syck=DumpFile -MPHP::Serialization=unserialize -MFile::Slurp=slurp -we '" .
146 '$YAML::Syck::Headless = 1;' .
147 '$YAML::Syck::SortKeys = 1;' .
148 'my $tf = q[' . $tf . '];' .
149 'my $serialized = slurp($tf);' .
150 'my $unserialized = unserialize($serialized);' .
151 'my $unserialized_utf8 = deutf8($unserialized);' .
152 'DumpFile(qq[$tf.yaml], $unserialized_utf8);' .
153 'sub deutf8 {' .
154 'if(ref($_[0]) eq "HASH") {' .
155 'return { map { deutf8($_) } %{$_[0]} };' .
156 '} elsif(ref($_[0]) eq "ARRAY") {' .
157 'return [ map { deutf8($_) } @{$_[0]} ];' .
158 '} else {' .
159 'my $s = $_[0];' .
160 'utf8::decode($s);' .
161 'return $s;' .
162 '}' .
163 '}' .
164 "'";
165
166 self::runCommand( $cmd );
167 $yaml = file_get_contents( "$tf.yaml" );
168
169 unlink( $tf );
170 unlink( "$tf.yaml" );
171
172 return $yaml;
173 }
174
175 private static function runCommand( string $cmd ): void {
176 $result = Shell::command( $cmd )->execute();
177 $exitCode = $result->getExitCode();
178 $stdOutput = $result->getStdout();
179 $stdError = $result->getStderr();
180 if ( $exitCode !== 0 ) {
181 throw new MWException(
182 "The command '$cmd' died in execution with exit code '$exitCode': Output: $stdOutput \nError: $stdError"
183 );
184 }
185 }
186}
This class is a wrapper class to provide interface to parse and generate YAML files with syck or spyc...
static fixSyckBooleans(&$yaml)
static fixSpycSpaces(&$yaml)
static loadString( $text)