PlFlagset and PlDBTableEntry are exportable.
[platal.git] / classes / csvimporter.php
index 5f1b4af..7d56bc8 100644 (file)
@@ -1,6 +1,6 @@
 <?php
 /***************************************************************************
- *  Copyright (C) 2003-2007 Polytechnique.org                              *
+ *  Copyright (C) 2003-2010 Polytechnique.org                              *
  *  http://opensource.polytechnique.org/                                   *
  *                                                                         *
  *  This program is free software; you can redistribute it and/or modify   *
  *  59 Temple Place, Suite 330, Boston, MA  02111-1307  USA                *
  ***************************************************************************/
 
-define('CSV_INSERT',  'insert'); // INSERT IGNORE
-define('CSV_REPLACE', 'replace'); // REPLACE
-define('CSV_UPDATE',  'update'); // INSERT and UPDATE on error
+define('CSV_INSERT',     'insert'); // INSERT IGNORE
+define('CSV_REPLACE',    'replace'); // REPLACE
+define('CSV_UPDATE',     'update'); // INSERT and UPDATE on error
+define('CSV_UPDATEONLY', 'updateonly'); // UPDATE
 
 class CSVImporter
 {
@@ -30,7 +31,6 @@ class CSVImporter
     private $do_sql;
 
     private $index;
-    private $separator;
     private $data = array();
 
     private $user_functions = array();
@@ -40,13 +40,12 @@ class CSVImporter
     public function __construct($table, $key = 'id', $do_sql = true)
     {
         $this->table     = $table;
-        $this->key       = $key;
+        $this->key       = explode(',', $key);
         $this->do_sql    = $do_sql;
     }
 
-    private function processLine($line)
+    private function processLine(array $array)
     {
-        $array = explode($this->separator, $line);
         if (is_null($this->index)) {
             $this->index = array_map('strtolower', $array);
             return true;
@@ -65,12 +64,12 @@ class CSVImporter
         return true;
     }
 
-    private function getValue($line, $key, $action)
+    static public function getValue($line, $key, $action, $relation = null)
     {
         if (@array_key_exists($action, $line)) {
             $value = $line[$action];
         } elseif (is_callable($action, false)) {
-            $value = call_user_func($action, $line, $key);
+            $value = call_user_func($action, $line, $key, $relation);
         } else {
             $value = $action;
         }
@@ -84,7 +83,7 @@ class CSVImporter
     {
         $ops = array();
         foreach ($relation as $key=>$ref) {
-            $ops[$key] = $this->getValue($line, $key, $ref);
+            $ops[$key] = $this->getValue($line, $key, $ref, $relation);
         }
         return $ops;
     }
@@ -93,7 +92,7 @@ class CSVImporter
     {
         $ops = array();
         foreach ($relation as $key=>$ref) {
-            $value = $this->getValue($line, $key, $ref);
+            $value = $this->getValue($line, $key, $ref, $relation);
             if (!is_null($value) && $value != 'NULL') {
                 $value = "'" . addslashes($value) . "'";
             }
@@ -131,12 +130,16 @@ class CSVImporter
 
     public function setCSV($csv, $index = null, $separator = ';')
     {
+        require_once dirname(__FILE__) . '/varstream.php';
+        VarStream::init();
+        global $csv_source;
         $this->index     = null;
-        $this->separator = $separator;
-        $csv   = preg_split("/(\r\n|\r|\n)/", $csv);
 
-        foreach ($csv as $line) {
-            $this->processLine($line);
+        $csv_source = $csv;
+        $res        = fopen('var://csv_source', 'r');
+
+        while (!feof($res)) {
+            $this->processLine(fgetcsv($res, 0, $separator));
         }
     }
 
@@ -157,11 +160,16 @@ class CSVImporter
               case CSV_REPLACE:
                 $this->execute("REPLACE INTO {$this->table} SET $set");
                 break;
-              case CSV_UPDATE:
-                if (!$this->execute("INSERT INTO {$this->table} SET $set")) {
+              case CSV_UPDATE: case CSV_UPDATEONLY:
+                if ($action == CSV_UPDATEONLY || !$this->execute("INSERT INTO {$this->table} SET $set")) {
                     $ops = $this->makeRequestArgs($line, $update_relation);
                     $set = join(', ', $ops);
-                    $this->execute("UPDATE {$this->table} SET $set WHERE {$ops[$this->key]}");
+                    $where = array();
+                    foreach ($this->key as $key) {
+                        $where[] = $ops[$key];
+                    }
+                    $where = join(' AND ', $where);
+                    $this->execute("UPDATE {$this->table} SET $set WHERE $where");
                 }
                 break;
             }
@@ -173,11 +181,11 @@ class CSVImporter
         static $fields, $conds, $values, $thens, $elses;
 
         if (!isset($fields)) {
-            $fields = Env::v('csv_cond_field');
-            $conds  = Env::v('csv_cond');
-            $values = Env::v('csv_cond_value');
-            $thens  = Env::v('csv_cond_then');
-            $elses  = Env::v('csv_cond_else');
+            $fields = $_SESSION['csv_cond_field'];
+            $conds  = $_SESSION['csv_cond'];
+            $values = $_SESSION['csv_cond_value'];
+            $thens  = $_SESSION['csv_cond_then'];
+            $elses  = $_SESSION['csv_cond_else'];
         }
         $field = $line[$fields[$key]];
         $cond  = $conds[$key];
@@ -223,13 +231,29 @@ class CSVImporter
         $this->field_value[$name] = $value;
     }
 
+    private function cleanSession($fields)
+    {
+        foreach ($fields as $field) {
+            unset($_SESSION[$field]);
+        }
+    }
+
     /** Handle insertion form
-     * @param $page  PlatalPage to process
+     * @param $page  PlPage to process
      * @param $url   URI of the page
      * @param $field Editable fields
      */
     public function apply(&$page, $url, $fields = null)
     {
+        $sesfields = array('csv_value', 'csv_user_value', 'csv_cond_field',
+                           'csv_update', 'csv_action', 'csv_cond_field',
+                           'csv_cond', 'csv_cond_value', 'csv_cond_then',
+                           'csv_cond_else', 'csv', 'csv_separator', 'csv_url');
+        if ($url != @$_SESSION['csv_url']) {
+            $this->cleanSession($sesfields);
+            $_SESSION['csv_url'] = $url;
+        }
+
         if (is_null($fields) || empty($fields)) {
             $fields = $this->getFieldList();
         }
@@ -237,7 +261,8 @@ class CSVImporter
             return false;
         }
         foreach ($this->field_value as $key=>$value) {
-            unset($fields[$key]);
+            $search = array_search($key, $fields);
+            unset($fields[$search]);
         }
 
         $current = Env::v('csv_page');
@@ -248,29 +273,44 @@ class CSVImporter
         if (empty($next)) {
             $next = $current;
         }
-        $csv  = Env::v('csv');
+        $csv  = @$_SESSION['csv'];
         if ($current == 'source' && Env::has('csv_valid')) {
             $csv = Env::v('csv_source');
+            $_SESSION['csv'] = $csv;
             $next = 'values';
         }
         if ($csv) {
-            $sep = Env::v('csv_separator');
-            if (empty($sep)) {
-                $sep = ';';
+            if (Env::has('csv_separator')) {
+                $sep = Env::v('csv_separator');
+                if (empty($sep)) {
+                    $sep = ';';
+                }
+                $_SESSION['csv_separator'] = $sep;
             }
-            echo $sep;
-            $this->setCSV($csv, null, $sep);
+            $this->setCSV($csv, null, $_SESSION['csv_separator']);
         }
         if ($current == 'values' && Env::has('csv_valid')) {
             $next = 'valid';
-        }    
+        }
         if (empty($csv)) {
             $next = 'source';
         }
+        if (Env::has('csv_action')) {
+            $_SESSION['csv_action'] = Env::v('csv_action');
+        }
         if ($next == 'valid') {
-            $insert   = Env::v('csv_value');
-            $values   = Env::v('csv_user_value');
-            $update   = Env::v('csv_update');
+            if ($current != 'valid') {
+                $cpyfields = array('csv_value', 'csv_user_value', 'csv_cond_field',
+                                   'csv_update', 'csv_action', 'csv_cond_field',
+                                   'csv_cond', 'csv_cond_value', 'csv_cond_then',
+                                   'csv_cond_else');
+                foreach ($cpyfields as $field) {
+                    $_SESSION[$field] = Env::v($field);
+                }
+            }
+            $insert   = $_SESSION['csv_value'];
+            $values   = $_SESSION['csv_user_value'];
+            $update   = $_SESSION['csv_update'];
             foreach ($insert as $key=>$value) {
                 if (empty($value)) {
                     $insert[$key] = null;
@@ -287,10 +327,13 @@ class CSVImporter
             }
             foreach ($this->field_value as $key=>$value) {
                 $insert[$key] = $value;
+                $fields[]     = $key;
             }
             if ($current == 'valid' && Env::has('csv_valid')) {
-                $this->run(Env::v('csv_action'), $insert, $update);
+                S::assert_xsrf_token();
+                $this->run($_SESSION['csv_action'], $insert, $update);
                 $page->assign('csv_done', true);
+                $this->cleanSession($sesfields);
             } else {
                 $preview = array();
                 foreach ($this->data as $line) {
@@ -304,9 +347,9 @@ class CSVImporter
         $page->assign('csv_field_desc', $this->field_desc);
         $page->assign('csv_page', $next);
         $page->assign('csv_path', $url);
-        $page->assign('csv_fields', $fields);  
-        $page->assign('csv', $csv);
+        $page->assign('csv_fields', $fields);
     }
 }
 
+// vim:set et sw=4 sts=4 sws=4 foldmethod=marker enc=utf-8:
 ?>