Core  3.2
PHP API documentation
 All Data Structures Namespaces Files Functions Variables Pages
fam2po.php
Go to the documentation of this file.
1 <?php
2 /*
3  * @author Anakeen
4  * @license http://creativecommons.org/licenses/by-nc-sa/2.0/fr/ Anakeen - licence CC
5  * @package FDL
6 */
7 
8 define("SEPCHAR", ';');
9 define("ALTSEPCHAR", ' --- ');
10 
11 $inrow = false;
12 $incell = false;
13 $nrow = 0;
14 $ncol = 0;
15 $rows = array();
17 $celldata = '';
18 $cellattrs = array();
19 $dbg = false;
20 $podir = $argv[1];
21 
22 for ($i = 2; $i < count($argv); $i++) {
23  $err = "";
24  $familyFile = $argv[$i];
25  debugMessage("Processing file " . $familyFile);
26  try {
27  $familyFilePathInfo = pathinfo($familyFile);
28  if (file_exists($familyFile)) {
29  if (isset($familyFilePathInfo['extension'])) {
30  switch ($familyFilePathInfo['extension']) {
31  case 'ods':
32  debugMessage(" --- csv extraction");
33  $csvfile = $familyFile . ".csv";
34  ods2csv($familyFile, $csvfile);
35  if (file_exists($csvfile)) {
37  } else {
38  throw new Exception("Unable to generate CSV from " . $familyFile);
39  }
40  unlink($csvfile);
41  break;
42 
43  case 'csv':
44  extractPOFromCSV($familyFile, $podir);
45  break;
46 
47  default:
48  debugMessage($familyFile . " has an unknown extension, skipping it.");
49  }
50  } else {
51  debugMessage($familyFile . " has no extension, skipping it.");
52  }
53  } else {
54  throw new Exception("Can't access file " . $familyFile);
55  }
56  }
57  catch(Exception $e) {
58  $err.= $e->getMessage() . " " . $e->getFile() . " line (" . $e->getLine() . ")\n";
59  }
60  if ($err) {
61  throw new Exception($e);
62  }
63 }
64 
65 function debugMessage($msg)
66 {
67  global $dbg;
68  if ($dbg) {
69  error_log("fam2po: " . $msg);
70  }
71 }
72 /**
73  * extractPOFromCSV from a CSV file and print it on standard output
74  *
75  * @param string $fi file input path
76  * @param string $podir Po directory
77  * @return void
78  */
79 function extractPOFromCSV($fi, $podir)
80 {
81  $fdoc = fopen($fi, "r");
82  if (!$fdoc) {
83  new Exception("fam2po: Can't access file [$fi]");
84  } else {
85  $podoc = null;
86  $contentToWrite = "";
87  $nline = - 1;
88  $famname = "*******";
89  $cv_idview_index = 0;
90  $cv_lview_index = 0;
91  $cv_menu_index = 0;
92  $date = date("c");
93  while (!feof($fdoc)) {
94 
95  $nline++;
96 
97  $buffer = rtrim(fgets($fdoc, 16384));
98  $data = explode(";", $buffer);
99 
100  $num = count($data);
101  if ($num < 1) {
102  continue;
103  }
104 
105  $data[0] = trim(getArrayIndexValue($data, 0));
106  switch ($data[0]) {
107  case "BEGIN":
108  $famname = getArrayIndexValue($data, 5);
110  if ($famname) $podoc = fopen($podir . "/" . $famname . ".pot", "w+");
111  $contentToWrite = "msgid \"\"\n";
112  $contentToWrite.= "msgstr \"\"\n";
113  $contentToWrite.= "\"Project-Id-Version: $famname \\n\"\n";
114  $contentToWrite.= "\"Report-Msgid-Bugs-To: \\n\"\n";
115  $contentToWrite.= "\"PO-Revision-Date: $date\\n\"\n";
116  $contentToWrite.= "\"Last-Translator: Automatically generated\\n\"\n";
117  $contentToWrite.= "\"Language-Team: none\\n\"\n";
118  $contentToWrite.= "\"MIME-Version: 1.0\\n\"\n";
119  $contentToWrite.= "\"Content-Type: text/plain; charset=UTF-8\\n\"\n";
120  $contentToWrite.= "\"Content-Transfer-Encoding: 8bit\\n\"\n";
121  $contentToWrite.= "\"Language: \\n\"\n\n";
122  $contentToWrite.= "#, fuzzy, ($fi)\n";
123  $contentToWrite.= "msgid \"" . $famname . "#title\"\n";
124  $contentToWrite.= "msgstr \"" . $famtitle . "\"\n\n";
125  break;
126 
127  case "END":
128  if (!$podoc) {
129  new Exception("fam2po: Can't create tempory family po file [$podir/$famname.pot]");
130  } else {
131  fwrite($podoc, $contentToWrite);
132  fclose($podoc);
133  }
134  $famname = "*******";
135  break;
136 
137  case "ORDER":
139  $cv_idview_index = 0;
140  $cv_lview_index = 0;
141  $cv_menu_index = 0;
142  if ($type === "CVDOC") {
143  foreach ($data as $index => $value) {
144  if ($value === "cv_idview") $cv_idview_index = $index;
145  else if ($value === "cv_lview") $cv_lview_index = $index;
146  else if ($value === "cv_menu") $cv_menu_index = $index;
147  if ($cv_idview_index && $cv_lview_index && $cv_menu_index) break;
148  }
149  }
150  break;
151 
152  case "DOC":
154  if ($type === "CVDOC") {
155  $cvName = getArrayIndexValue($data, 2);
156  if ($cvName && !is_numeric($cvName) && $cv_idview_index) {
157  $cvdoc = fopen($podir . "/" . $cvName . ".pot", "w+");
158  if (!$cvdoc) {
159  new Exception("fam2po: Can't create tempory CV po file [$podir/$cvName.pot]");
160  }
161  $cvContentToWrite = "msgid \"\"\n";
162  $cvContentToWrite.= "msgstr \"\"\n";
163  $cvContentToWrite.= "\"Project-Id-Version: $cvName \\n\"\n";
164  $cvContentToWrite.= "\"Report-Msgid-Bugs-To: \\n\"\n";
165  $cvContentToWrite.= "\"PO-Revision-Date: $date\\n\"\n";
166  $cvContentToWrite.= "\"Last-Translator: Automatically generated\\n\"\n";
167  $cvContentToWrite.= "\"Language-Team: none\\n\"\n";
168  $cvContentToWrite.= "\"MIME-Version: 1.0\\n\"\n";
169  $cvContentToWrite.= "\"Content-Type: text/plain; charset=UTF-8\\n\"\n";
170  $cvContentToWrite.= "\"Content-Transfer-Encoding: 8bit\\n\"\n";
171  $cvContentToWrite.= "\"Language: \\n\"\n\n";
172  $tcv_idview = explode('\n', getArrayIndexValue($data, $cv_idview_index));
173  $tcv_lview = explode('\n', getArrayIndexValue($data, $cv_lview_index));
174  $tcv_menu = explode('\n', getArrayIndexValue($data, $cv_menu_index));
175  foreach ($tcv_idview as $i => $id) {
176  if ($cv_lview_index && $tcv_lview[$i]) {
177  $cvContentToWrite.= "#: $fi\n";
178  $cvContentToWrite.= "#, fuzzy\n";
179  $cvContentToWrite.= "msgid \"" . $cvName . "#label#" . $id . "\"\n";
180  $cvContentToWrite.= "msgstr \"" . $tcv_lview[$i] . "\"\n\n";
181  }
182  if ($cv_menu_index && $tcv_menu[$i]) {
183  $cvContentToWrite.= "#: $fi\n";
184  $cvContentToWrite.= "#, fuzzy\n";
185  $cvContentToWrite.= "msgid \"" . $cvName . "#menu#" . $id . "\"\n";
186  $cvContentToWrite.= "msgstr \"" . $tcv_menu[$i] . "\"\n\n";
187  }
188  }
189  fwrite($cvdoc, $cvContentToWrite);
190  fclose($cvdoc);
191  }
192  }
193  break;
194 
195  case "ATTR":
196  case "MODATTR":
197  case "PARAM":
198  case "OPTION":
199  $contentToWrite.= "#: $fi\n";
200  $contentToWrite.= "#, fuzzy, ($fi)\n";
201  $contentToWrite.= "msgid \"" . $famname . "#" . strtolower(getArrayIndexValue($data, 1)) . "\"\n";
202  $contentToWrite.= "msgstr \"" . getArrayIndexValue($data, 3) . "\"\n\n";
203  // Enum ----------------------------------------------
205  if ($type == "enum" || $type == "enumlist") {
206  $d = str_replace('\,', '\#', getArrayIndexValue($data, 12));
207  $tenum = explode(",", $d);
208  foreach ($tenum as $ve) {
209  $d = str_replace('\#', ',', $ve);
210  $enumValues = explode("|", $d);
211  $contentToWrite.= "#, fuzzy, ($fi)\n";
212  $contentToWrite.= "msgid \"" . $famname . "#" . strtolower(getArrayIndexValue($data, 1)) . "#" . (str_replace('\\', '', getArrayIndexValue($enumValues, 0))) . "\"\n";
213  $contentToWrite.= "msgstr \"" . (str_replace('\\', '', getArrayIndexValue($enumValues, 1))) . "\"\n\n";
214  }
215  }
216  // Options ----------------------------------------------
217  $options = getArrayIndexValue($data, 15);
218  $options = explode("|", $options);
219  foreach ($options as $currentOption) {
220  $currentOption = explode("=", $currentOption);
221  $currentOptionKey = getArrayIndexValue($currentOption, 0);
222  $currentOptionValue = getArrayIndexValue($currentOption, 1);
223  switch (strtolower($currentOptionKey)) {
224  case "elabel":
225  case "ititle":
226  case "submenu":
227  case "ltitle":
228  case "eltitle":
229  case "elsymbol":
230  case "lsymbol":
231  case "showempty":
232  $contentToWrite.= "#, fuzzy, ($fi)\n";
233  $contentToWrite.= "msgid \"" . $famname . "#" . strtolower(getArrayIndexValue($data, 1)) . "#" . strtolower($currentOptionKey) . "\"\n";
234  $contentToWrite.= "msgstr \"" . $currentOptionValue . "\"\n\n";
235  }
236  }
237  }
238  } }
239  }
240 
241  function getArrayIndexValue(&$array, $index)
242  {
243  return isset($array[$index]) ? $array[$index] : "";
244  }
245  /** Utilities function to produce a CSV from an ODS**/
246  /**
247  * Take an ODS file and produce one CSV
248  *
249  * @param string $odsfile path to ODS file
250  * @param string $csvfile path to CSV output file
251  * @throws Exception
252  * @return void
253  */
255  {
256  if ($odsfile === "" or !file_exists($odsfile) or $csvfile === "") {
257  throw new Exception("ODS convert needs an ODS path and a CSV path");
258  }
259 
260  $content = ods2content($odsfile);
261  $csv = xmlcontent2csv($content);
262  $isWrited = file_put_contents($csvfile, $csv);
263  if ($isWrited === false) {
264  throw new Exception(sprintf("Unable to convert ODS to CSV fo %s", $odsfile));
265  }
266  }
267  /**
268  * Extract content from an ods file
269  *
270  * @param string $odsfile file path
271  * @throws Exception
272  * @return string
273  */
275  {
276  if (!file_exists($odsfile)) {
277  throw new Exception("file $odsfile not found");
278  }
279  $cibledir = uniqid("/var/tmp/ods");
280 
281  $cmd = sprintf("unzip -j %s content.xml -d %s >/dev/null", $odsfile, $cibledir);
282  system($cmd);
283 
284  $contentxml = $cibledir . "/content.xml";
285  if (file_exists($contentxml)) {
286  $content = file_get_contents($contentxml);
287  unlink($contentxml);
288  } else {
289  throw new Exception("unable to extract $odsfile");
290  }
291 
292  rmdir($cibledir);
293  return $content;
294  }
295  /**
296  * @param $xmlcontent
297  *
298  * @throws Exception
299  * @return string
300  */
301  function xmlcontent2csv($xmlcontent)
302  {
303  global $rows;
304  $xml_parser = xml_parser_create();
305  // Use case handling $map_array
306  xml_parser_set_option($xml_parser, XML_OPTION_CASE_FOLDING, true);
307  xml_parser_set_option($xml_parser, XML_OPTION_SKIP_WHITE, 0);
308  xml_set_element_handler($xml_parser, "startElement", "endElement");
309  xml_set_character_data_handler($xml_parser, "characterData");
310 
311  if (!xml_parse($xml_parser, $xmlcontent)) {
312  throw new Exception(sprintf("Unable to parse XML : %s line %d", xml_error_string(xml_get_error_code($xml_parser)) , xml_get_current_line_number($xml_parser)));
313  }
314  $fcsv = "";
315  xml_parser_free($xml_parser);
316  foreach ($rows as $row) {
317  $fcsv.= implode(SEPCHAR, $row) . "\n";
318  }
319  return $fcsv;
320  }
321  /* Handling method for XML parser*/
322  function startElement(
323  /** @noinspection PhpUnusedParameterInspection */
324  $parser, $name, $attrs)
325  {
327  if ($name == "TABLE:TABLE-ROW") {
328  $inrow = true;
329  if (isset($rows[$nrow])) {
330  // fill empty cells
331  $idx = 0;
332  foreach ($rows[$nrow] as $k => $v) {
333  if (!isset($rows[$nrow][$idx])) {
334  $rows[$nrow][$idx] = '';
335  }
336  $idx++;
337  }
338  ksort($rows[$nrow], SORT_NUMERIC);
339  }
340  $nrow++;
341  $ncol = 0;
342  $rows[$nrow] = array();
343  }
344 
345  if ($name == "TABLE:TABLE-CELL") {
346  $incell = true;
347  $celldata = "";
348  $cellattrs = $attrs;
349  if (!empty($attrs["TABLE:NUMBER-COLUMNS-REPEATED"])) {
350  $colrepeat = intval($attrs["TABLE:NUMBER-COLUMNS-REPEATED"]);
351  }
352  }
353  if ($name == "TEXT:P") {
354  if (isset($rows[$nrow][$ncol])) {
355  if (strlen($rows[$nrow][$ncol]) > 0) {
356  $rows[$nrow][$ncol].= '\n';
357  }
358  }
359  }
360  }
361 
362  function endElement(
363  /** @noinspection PhpUnusedParameterInspection */
364  $parser, $name)
365  {
367  if ($name == "TABLE:TABLE-ROW") {
368  // Remove trailing empty cells
369  $i = $ncol - 1;
370  while ($i >= 0) {
371  if (strlen($rows[$nrow][$i]) > 0) {
372  break;
373  }
374  $i--;
375  }
376  array_splice($rows[$nrow], $i + 1);
377  $inrow = false;
378  }
379 
380  if ($name == "TABLE:TABLE-CELL") {
381  $incell = false;
382 
383  if ($celldata === '') {
384  $celldata = getOfficeTypedValue($cellattrs);
385  }
386 
387  $rows[$nrow][$ncol] = $celldata;
388 
389  if ($colrepeat > 1) {
390  $rval = $rows[$nrow][$ncol];
391  for ($i = 1; $i < $colrepeat; $i++) {
392  $ncol++;
393  $rows[$nrow][$ncol] = $rval;
394  }
395  }
396  $ncol++;
397  $colrepeat = 0;
398  }
399  }
400 
401  function characterData(
402  /** @noinspection PhpUnusedParameterInspection */
403  $parser, $data)
404  {
405  global $inrow, $incell, $celldata;
406  if ($inrow && $incell) {
407  $celldata.= preg_replace('/^\s*[\r\n]\s*$/ms', '', str_replace(SEPCHAR, ALTSEPCHAR, $data));
408  }
409  }
410 
411  function getOfficeTypedValue($attrs)
412  {
413  $value = '';
414  /* Get value from property OFFICE:<type>-VALUE */
415  if (isset($attrs['OFFICE:VALUE-TYPE'])) {
416  $type = strtoupper($attrs['OFFICE:VALUE-TYPE']);
417  $propName = 'OFFICE:' . $type . '-VALUE';
418  if (isset($attrs[$propName])) {
419  $value = (string)$attrs[$propName];
420  }
421  }
422  /* Get value from property OFFICE:VALUE */
423  if ($value == '' && isset($attrs['OFFICE:VALUE'])) {
424  $value = (string)$attrs['OFFICE:VALUE'];
425  }
426  return $value;
427  }
$csv
Definition: checkVault.php:41
getArrayIndexValue(&$array, $index)
Definition: fam2po.php:241
if($dbaccess=="") if($statusFile=== '') $famtitle
startElement($parser, $name, $attrs)
Definition: fam2po.php:322
const ALTSEPCHAR
Definition: fam2po.php:9
getOfficeTypedValue($attrs)
Definition: fam2po.php:411
$cellattrs
Definition: fam2po.php:18
$ncol
Definition: fam2po.php:14
$d
Definition: dav.php:77
$csvfile
foreach($argv as $arg) $cmd
$incell
Definition: fam2po.php:12
ods2content($odsfile)
Definition: fam2po.php:274
$celldata
Definition: fam2po.php:17
$podir
Definition: fam2po.php:20
$nrow
Definition: fam2po.php:13
$inrow
Definition: fam2po.php:11
$rows
Definition: fam2po.php:15
$odsfile
characterData($parser, $data)
Definition: fam2po.php:401
const SEPCHAR
Definition: fam2po.php:8
xmlcontent2csv($xmlcontent)
Definition: fam2po.php:301
extractPOFromCSV($fi, $podir)
Definition: fam2po.php:79
ods2csv($odsfile, $csvfile)
Definition: fam2po.php:254
if($file) if($subject==""&&$file) if($subject=="") $err
endElement($parser, $name)
Definition: fam2po.php:362
for($i=2;$i< count($argv);$i++) debugMessage($msg)
Definition: fam2po.php:65
$value
$dbg
Definition: fam2po.php:19
$data
$colrepeat
Definition: fam2po.php:16
← centre documentaire © anakeen