[260493] Provide a CSV export and import script
diff --git a/classes/export/generate_csv.php b/classes/export/generate_csv.php
new file mode 100644
index 0000000..8435970
--- /dev/null
+++ b/classes/export/generate_csv.php
@@ -0,0 +1,55 @@
+<?php
+/*******************************************************************************
+ * Copyright (c) 2009 Intalio, Inc.
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Eclipse Public License v1.0
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/epl-v10.html
+ *
+ * Contributors:
+ *    Antoine Toulme, Intalio Inc. bug 260493: Provide a CSV export and import script
+*******************************************************************************/
+
+error_reporting(E_ALL);
+ini_set('display_errors', '1');
+// This script exports all the translations for each language as a CSV file.
+
+ob_start();
+ini_set("memory_limit", "256M");
+define("BABEL_BASE_DIR", "../../");
+require(BABEL_BASE_DIR . "html/common_functions.php");
+require(BABEL_BASE_DIR . "classes/system/dbconnection.class.php");
+require(BABEL_BASE_DIR . "classes/system/feature.class.php");
+$dbc = new DBConnection();
+$dbh = $dbc->connect();
+
+$work_dir = "/tmp/babel-working/";
+
+$work_context_dir = $work_dir . $context . "_csv/";
+$tmp_dir = $work_context_dir . "tmp/";
+$output_dir = $work_context_dir . "output/";
+
+exec("rm -rf $tmp_dir");
+exec("mkdir -p $tmp_dir");
+exec("mkdir -p $output_dir");
+
+//iterate over all the release trains
+foreach(ReleaseTrain::all() as $train) {
+	// create a dedicated folder for each of them
+	exec("mkdir -p $work_context_dir/$train->id");
+	// create the output folder for temporary artifacts
+	$output_dir_for_train = "$output_dir/$train->id/";
+	exec("mkdir -p $output_dir_for_train");
+	// iterate over each language
+	foreach(Language::all() as $lang) {
+		// create a new feature object
+		$feature = new Feature($lang, $train, $tmp_dir, $output_dir_for_train);
+		// make it generate itself
+		$feature->generateAsCSV();
+		// now zip it directly
+		$featureZip = $feature->zipAsCSV("$work_context_dir/$train->id");
+		// output the creation of the feature notification
+		echo "Feature created here: $featureZip\n";
+	}
+	break;
+}
\ No newline at end of file
diff --git a/classes/export/import_from_csv.php b/classes/export/import_from_csv.php
new file mode 100644
index 0000000..032bbd8
--- /dev/null
+++ b/classes/export/import_from_csv.php
@@ -0,0 +1,109 @@
+<?php
+/*******************************************************************************
+ * Copyright (c) 2009 Intalio, Inc.
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Eclipse Public License v1.0
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/epl-v10.html
+ *
+ * Contributors:
+ *    Antoine Toulme, Intalio Inc. bug 260493: Provide a CSV export and import script
+*******************************************************************************/
+
+if ($argc != 4) {
+	$help = <<<HELP
+Copyright (c) 2009 Intalio, Inc.
+Usage: import_from_csv.php language release_train csv_file
+
+  language: the code of the language to use. See the languages supported by Babel.
+
+  release_train: a release train name.
+
+  csv_file: the path to the csv_file. The path should either be relative to the php file or absolute.
+            The CSV file should be comma separated. It should have this structure: "translation_key", "translation_english_value", "translation_value"
+
+  Example:
+    import_from_csv.php fr_CA europa some_translations_fr.csv
+
+  Authors:
+    This script was written by the Babel project. Please see http://www.eclipse.org/babel for more information.
+
+
+HELP;
+    echo $help;
+	exit;
+}
+
+error_reporting(E_ALL); ini_set("display_errors", true);
+
+ob_start();
+ini_set("memory_limit", "256M");
+define("BABEL_BASE_DIR", "../../");
+require_once(BABEL_BASE_DIR . 'html/eclipse.org-common/system/app.class.php');
+require_once(BABEL_BASE_DIR . "html/common_functions.php");
+require_once(BABEL_BASE_DIR . "classes/system/dbconnection.class.php");
+require_once(BABEL_BASE_DIR . "classes/system/feature.class.php");
+require_once(BABEL_BASE_DIR . "classes/system/user.class.php");
+$App 	= new App();
+$dbc = new DBConnection();
+$dbh = $dbc->connect();
+
+//translations coming from a CSV file are considered to come from professional translators that tested their work in context, and/or in relation with the developers
+// change the variable below if you have doubts on the translation quality.
+$fuzzy = 0;
+
+//user that will be running the translations.
+$USER = getGenieUser()->userid;
+
+$language = $argv[1];
+$release_train_id = $argv[2];
+$csv_file = $argv[3];
+
+$sql = "select language_id from languages where iso_code = '" . addslashes($language) ."'";
+$lrow = mysql_fetch_assoc(mysql_query($sql));
+if (!$lrow) {
+	echo "This language code is not supported by Babel. Please see the Babel documentation for more information";
+	exit;
+}
+$language_id = $lrow['language_id'];
+
+
+$handle = fopen($csv_file, "r");
+while (($data = fgetcsv($handle)) !== FALSE) {
+	$sql = <<<SQL
+SELECT s.string_id FROM files AS f INNER JOIN strings AS s ON f.file_id = s.file_id INNER JOIN release_train_projects as v ON (f.project_id = v.project_id AND f.version = v.version) WHERE f.is_active AND s.non_translatable <> 1 AND s.name = '$data[0]' AND BINARY s.value = '$data[1]' AND v.train_id = '$release_train_id'
+
+SQL;
+    $values = mysql_query($sql);
+    $value_row = mysql_fetch_assoc($values);
+    if (!$value_row) {
+	    echo "Could not find the matching record for $data[0] with a value of $data[1]";
+	    continue;
+    }
+    $string_id = $value_row['string_id'];
+    
+    $sql = "select possibly_incorrect from translations where string_id = $string_id and language_id = $language_id";
+    $tr_row = mysql_fetch_assoc(mysql_query($sql));
+    if ($tr_row) {
+	    if ($fuzzy == 1) {
+		    if ($tr_row['possibly_incorrect'] == 1) {
+			    // replacing a fuzzy translation by a new fuzzy translation. Well.
+		    } else {
+			    //replacing a non-fuzzy translation by a fuzzy translation: no, thank you
+			    echo "The entry " . $data[0] . " is already translated in a non-fuzzy way. Aborting";
+			    continue;
+		    }
+	    } else {
+		    // we are not fuzzy, for now let's assume it's ok to override non-fuzzy translations when yours aren't either.
+	    }
+	    $query = "UPDATE translations set is_active = 0 where string_id = " . $string_id . " and language_id = '" . $language_id . "'";
+	    mysql_query($query);
+    }
+    $query = "INSERT INTO translations(string_id, language_id, value, userid, created_on, possibly_incorrect) values('". addslashes($string_id) ."','".  addslashes($language_id) ."','" . addslashes($data[2]) . "', '". addslashes($USER) ."', NOW(), $fuzzy)";
+    mysql_query($query);
+    echo "Added translation \"$data[2]\" for entry '$data[0]'\n";
+}
+fclose($handle);
+echo "\n\nDone.\n";
+
+?>
\ No newline at end of file
diff --git a/classes/system/feature.class.php b/classes/system/feature.class.php
index c415680..7970a7e 100644
--- a/classes/system/feature.class.php
+++ b/classes/system/feature.class.php
@@ -10,7 +10,7 @@
  *    Antoine Toulme, Intalio Inc. bug 248845: Refactoring generate1.php into different files with a functional approach
 *******************************************************************************/
 
-require(BABEL_BASE_DIR . "classes/system/fragment.class.php"); 
+require_once(BABEL_BASE_DIR . "classes/system/fragment.class.php"); 
 
 class Feature {
 	public $language;
@@ -73,6 +73,10 @@
 				}
 			}
 		}
+		
+		if (!isSet($pct)) {
+			return 0;
+		}
 		return $pct;
 	}
 	
@@ -101,14 +105,18 @@
 	/*
 	 * Cleans the $output_dir/eclipse/features/ and $output_dir/eclipse/plugins folders.
 	 */
-	function cleanupOutput($output_dir = null) {
+	function cleanupOutput($output_dir = null, $create_eclipse_structure = true) {
 		if (!$output_dir) {
 			$output_dir = $this->output_dir;
 		}
-		$instructions = array("rm -Rf $output_dir/eclipse/features/", 
-				"rm -Rf $output_dir/eclipse/plugins/",
-				"mkdir -p $output_dir/eclipse/features/",
-				"mkdir -p $output_dir/eclipse/plugins/");
+		if ($create_eclipse_structure) {
+			$instructions = array("rm -Rf $output_dir/eclipse/features/", 
+					"rm -Rf $output_dir/eclipse/plugins/",
+					"mkdir -p $output_dir/eclipse/features/",
+					"mkdir -p $output_dir/eclipse/plugins/");
+		} else {
+			$instructions = array("rm -Rf $output_dir/*");
+		}
 		foreach ($instructions as $cmd) {
 			$retval = system($cmd, $return_code);
 			if ($return_code != 0) {
@@ -244,4 +252,56 @@
 		}
 		return "$destination/$filename";
 	}
+	
+	// Following functions help dealing with CSV files.
+	
+	/**
+	 * Zips the feature as a zip to a destination folder.
+	 */
+	function zipAsCSV($destination, $output_dir = null) {
+		if (!$output_dir) {
+			$output_dir = $this->output_dir;
+		}
+		$filename = $this->filename() . ".zip";
+		$instructions = array(
+						"zip -r -q $filename $output_dir/* -d $output_dir/$filename",
+						"mkdir -p $destination", 
+						"cd $output_dir ; mv $filename $destination");
+		
+		foreach ($instructions as $cmd) {
+			$retval = system($cmd, $return_code);
+			if ($return_code != 0) {
+				echo "### ERROR during the execution of: $cmd";
+				echo "\n$return_code $retval";
+			}
+		}
+		return "$destination/$filename";
+	}
+	
+	function generateAsCSV() {
+		$this->cleanupOutput(null, false);
+		$filename = $this->filename() . ".csv";
+		$language = $this->language->id;
+		$train = $this->train->id;
+		$sql = <<<SQL
+			SELECT s.name, s.value, s.string_id
+			FROM files AS f
+			INNER JOIN strings AS s ON f.file_id = s.file_id
+			INNER JOIN release_train_projects as v ON (f.project_id = v.project_id AND f.version = v.version)
+			WHERE f.is_active
+			AND s.non_translatable <> 1
+			AND v.train_id = '$train'
+SQL;
+		$result = mysql_query($sql);
+		$f = fopen("$this->output_dir/" . $this->filename() . ".csv", "w");
+		while (($row = mysql_fetch_assoc($result)) != null) {
+		    $value_row = mysql_fetch_assoc(mysql_query("SELECT value from translations where string_id = " . $row['string_id'] . " and language_id = " . $language));
+			$value = '';
+			if ($value_row != null) {
+				$value = $value_row['value'];
+            }
+            fputcsv($f, array($row['name'], $row['value'], $value));
+		}
+		fclose($f);
+	}
 }
\ No newline at end of file