1<?php 2 3/* 4 * This file is part of the Symfony package. 5 * 6 * (c) Fabien Potencier <fabien@symfony.com> 7 * 8 * For the full copyright and license information, please view the LICENSE 9 * file that was distributed with this source code. 10 */ 11 12namespace Symfony\Component\Intl\Data\Bundle\Writer; 13 14use Symfony\Component\Intl\Exception\UnexpectedTypeException; 15 16/** 17 * Writes .txt resource bundles. 18 * 19 * The resulting files can be converted to binary .res files using a 20 * {@link \Symfony\Component\Intl\ResourceBundle\Compiler\BundleCompilerInterface} 21 * implementation. 22 * 23 * @author Bernhard Schussek <bschussek@gmail.com> 24 * 25 * @see http://source.icu-project.org/repos/icu/icuhtml/trunk/design/bnf_rb.txt 26 * 27 * @internal 28 */ 29class TextBundleWriter implements BundleWriterInterface 30{ 31 /** 32 * {@inheritdoc} 33 */ 34 public function write($path, $locale, $data, $fallback = true) 35 { 36 $file = fopen($path.'/'.$locale.'.txt', 'w'); 37 38 $this->writeResourceBundle($file, $locale, $data, $fallback); 39 40 fclose($file); 41 } 42 43 /** 44 * Writes a "resourceBundle" node. 45 * 46 * @param resource $file The file handle to write to 47 * @param string $bundleName The name of the bundle 48 * @param mixed $value The value of the node 49 * @param bool $fallback Whether the resource bundle should be merged 50 * with the fallback locale 51 * 52 * @see http://source.icu-project.org/repos/icu/icuhtml/trunk/design/bnf_rb.txt 53 */ 54 private function writeResourceBundle($file, $bundleName, $value, $fallback) 55 { 56 fwrite($file, $bundleName); 57 58 $this->writeTable($file, $value, 0, $fallback); 59 60 fwrite($file, "\n"); 61 } 62 63 /** 64 * Writes a "resource" node. 65 * 66 * @param resource $file The file handle to write to 67 * @param mixed $value The value of the node 68 * @param int $indentation The number of levels to indent 69 * @param bool $requireBraces Whether to require braces to be printedaround the value 70 * 71 * @see http://source.icu-project.org/repos/icu/icuhtml/trunk/design/bnf_rb.txt 72 */ 73 private function writeResource($file, $value, $indentation, $requireBraces = true) 74 { 75 if (\is_int($value)) { 76 $this->writeInteger($file, $value); 77 78 return; 79 } 80 81 if ($value instanceof \Traversable) { 82 $value = iterator_to_array($value); 83 } 84 85 if (\is_array($value)) { 86 $intValues = \count($value) === \count(array_filter($value, 'is_int')); 87 88 $keys = array_keys($value); 89 90 // check that the keys are 0-indexed and ascending 91 $intKeys = $keys === range(0, \count($keys) - 1); 92 93 if ($intValues && $intKeys) { 94 $this->writeIntVector($file, $value, $indentation); 95 96 return; 97 } 98 99 if ($intKeys) { 100 $this->writeArray($file, $value, $indentation); 101 102 return; 103 } 104 105 $this->writeTable($file, $value, $indentation); 106 107 return; 108 } 109 110 if (\is_bool($value)) { 111 $value = $value ? 'true' : 'false'; 112 } 113 114 $this->writeString($file, (string) $value, $requireBraces); 115 } 116 117 /** 118 * Writes an "integer" node. 119 * 120 * @param resource $file The file handle to write to 121 * @param int $value The value of the node 122 * 123 * @see http://source.icu-project.org/repos/icu/icuhtml/trunk/design/bnf_rb.txt 124 */ 125 private function writeInteger($file, $value) 126 { 127 fprintf($file, ':int{%d}', $value); 128 } 129 130 /** 131 * Writes an "intvector" node. 132 * 133 * @param resource $file The file handle to write to 134 * @param array $value The value of the node 135 * @param int $indentation The number of levels to indent 136 * 137 * @see http://source.icu-project.org/repos/icu/icuhtml/trunk/design/bnf_rb.txt 138 */ 139 private function writeIntVector($file, array $value, $indentation) 140 { 141 fwrite($file, ":intvector{\n"); 142 143 foreach ($value as $int) { 144 fprintf($file, "%s%d,\n", str_repeat(' ', $indentation + 1), $int); 145 } 146 147 fprintf($file, '%s}', str_repeat(' ', $indentation)); 148 } 149 150 /** 151 * Writes a "string" node. 152 * 153 * @param resource $file The file handle to write to 154 * @param string $value The value of the node 155 * @param bool $requireBraces Whether to require braces to be printed 156 * around the value 157 * 158 * @see http://source.icu-project.org/repos/icu/icuhtml/trunk/design/bnf_rb.txt 159 */ 160 private function writeString($file, $value, $requireBraces = true) 161 { 162 if ($requireBraces) { 163 fprintf($file, '{"%s"}', $value); 164 165 return; 166 } 167 168 fprintf($file, '"%s"', $value); 169 } 170 171 /** 172 * Writes an "array" node. 173 * 174 * @param resource $file The file handle to write to 175 * @param array $value The value of the node 176 * @param int $indentation The number of levels to indent 177 * 178 * @see http://source.icu-project.org/repos/icu/icuhtml/trunk/design/bnf_rb.txt 179 */ 180 private function writeArray($file, array $value, $indentation) 181 { 182 fwrite($file, "{\n"); 183 184 foreach ($value as $entry) { 185 fwrite($file, str_repeat(' ', $indentation + 1)); 186 187 $this->writeResource($file, $entry, $indentation + 1, false); 188 189 fwrite($file, ",\n"); 190 } 191 192 fprintf($file, '%s}', str_repeat(' ', $indentation)); 193 } 194 195 /** 196 * Writes a "table" node. 197 * 198 * @param resource $file The file handle to write to 199 * @param iterable $value The value of the node 200 * @param int $indentation The number of levels to indent 201 * @param bool $fallback Whether the table should be merged 202 * with the fallback locale 203 * 204 * @throws UnexpectedTypeException when $value is not an array and not a 205 * \Traversable instance 206 */ 207 private function writeTable($file, $value, $indentation, $fallback = true) 208 { 209 if (!\is_array($value) && !$value instanceof \Traversable) { 210 throw new UnexpectedTypeException($value, 'array or \Traversable'); 211 } 212 213 if (!$fallback) { 214 fwrite($file, ':table(nofallback)'); 215 } 216 217 fwrite($file, "{\n"); 218 219 foreach ($value as $key => $entry) { 220 fwrite($file, str_repeat(' ', $indentation + 1)); 221 222 // escape colons, otherwise they are interpreted as resource types 223 if (false !== strpos($key, ':') || false !== strpos($key, ' ')) { 224 $key = '"'.$key.'"'; 225 } 226 227 fwrite($file, $key); 228 229 $this->writeResource($file, $entry, $indentation + 1); 230 231 fwrite($file, "\n"); 232 } 233 234 fprintf($file, '%s}', str_repeat(' ', $indentation)); 235 } 236} 237