2 /***************************************************************************
3 * Copyright (C) 2003-2007 Polytechnique.org *
4 * http://opensource.polytechnique.org/ *
6 * This program is free software; you can redistribute it and/or modify *
7 * it under the terms of the GNU General Public License as published by *
8 * the Free Software Foundation; either version 2 of the License, or *
9 * (at your option) any later version. *
11 * This program is distributed in the hope that it will be useful, *
12 * but WITHOUT ANY WARRANTY; without even the implied warranty of *
13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the *
14 * GNU General Public License for more details. *
16 * You should have received a copy of the GNU General Public License *
17 * along with this program; if not, write to the Free Software *
19 * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA *
20 ***************************************************************************/
22 define('CSV_INSERT', 'insert'); // INSERT IGNORE
23 define('CSV_REPLACE', 'replace'); // REPLACE
24 define('CSV_UPDATE', 'update'); // INSERT and UPDATE on error
25 define('CSV_UPDATEONLY', 'updateonly'); // UPDATE
34 private $data = array();
36 private $user_functions = array();
37 private $field_desc = array();
38 private $field_value = array();
40 public function __construct($table, $key = 'id', $do_sql = true
)
42 $this->table
= $table;
43 $this->key
= explode(',', $key);
44 $this->do_sql
= $do_sql;
47 private function processLine(array $array)
49 if (is_null($this->index
)) {
50 $this->index
= array_map('strtolower', $array);
54 if (count($array) != count($this->index
)) {
59 foreach ($this->index
as $key) {
60 $assoc[$key] = $array[$i];
63 $this->data
[] = $assoc;
67 private function getValue($line, $key, $action)
69 if (@array_key_exists
($action, $line)) {
70 $value = $line[$action];
71 } elseif (is_callable($action, false
)) {
72 $value = call_user_func($action, $line, $key);
76 if (is_null($value) ||
$value == 'NULL') {
82 private function makeAssoc($line, $relation)
85 foreach ($relation as $key=>$ref) {
86 $ops[$key] = $this->getValue($line, $key, $ref);
91 private function makeRequestArgs($line, $relation)
94 foreach ($relation as $key=>$ref) {
95 $value = $this->getValue($line, $key, $ref);
96 if (!is_null($value) && $value != 'NULL') {
97 $value = "'" . addslashes($value) . "'";
99 $ops[$key] = "$key = $value";
104 private function makeRelation()
107 foreach ($this->index
as $title) {
108 $relation[$title] = $title;
113 private function execute($query)
115 if (!$this->do_sql
) {
119 return XDB
::execute($query);
122 private function getFieldList()
124 $res = XDB
::query("SHOW COLUMNS FROM {$this->table}");
125 if ($res->numRows()) {
126 return $res->fetchColumn();
131 public function setCSV($csv, $index = null
, $separator = ';')
133 require_once dirname(__FILE__
) . '/varstream.php';
139 $res = fopen('var://csv_source', 'r');
141 while (!feof($res)) {
142 $this->processLine(fgetcsv($res, 0, $separator));
146 public function run($action = CSV_UPDATE
, $insert_relation = null
, $update_relation = null
)
148 if (is_null($insert_relation)) {
149 $insert_relation = $this->makeRelation();
151 if (is_null($update_relation)) {
152 $update_relation = $insert_relation;
154 foreach ($this->data
as $line) {
155 $set = join(', ', $this->makeRequestArgs($line, $insert_relation));
158 $this->execute("INSERT IGNORE INTO {$this->table} SET $set");
161 $this->execute("REPLACE INTO {$this->table} SET $set");
163 case CSV_UPDATE
: case CSV_UPDATEONLY
:
164 if ($action == CSV_UPDATEONLY ||
!$this->execute("INSERT INTO {$this->table} SET $set")) {
165 $ops = $this->makeRequestArgs($line, $update_relation);
166 $set = join(', ', $ops);
168 foreach ($this->key
as $key) {
169 $where[] = $ops[$key];
171 $where = join(' AND ', $where);
172 $this->execute("UPDATE {$this->table} SET $set WHERE $where");
179 static public function dynamicCond($line, $key)
181 static $fields, $conds, $values, $thens, $elses;
183 if (!isset($fields)) {
184 $fields = $_SESSION['csv_cond_field'];
185 $conds = $_SESSION['csv_cond'];
186 $values = $_SESSION['csv_cond_value'];
187 $thens = $_SESSION['csv_cond_then'];
188 $elses = $_SESSION['csv_cond_else'];
190 $field = $line[$fields[$key]];
191 $cond = $conds[$key];
192 $value = $values[$key];
193 if (is_numeric($field) && is_numeric($value)) {
194 $field = floatval($field);
195 $value = floatval($value);
198 case 'defined': $ok = (!empty($field)); break;
199 case 'equals': $ok = ($field == $value); break;
200 case 'contains': $ok = (strpos($field, $value) !== false
); break;
201 case 'contained': $ok = (strpos($value, $field) !== false
); break;
202 case 'greater': $ok = ($field > $value); break;
203 case 'greater_or_equal': $ok ($field >= $value); break;
204 case 'lower': $ok = ($field < $value); break;
205 case 'lower_or_equal': $ok = ($field <= $value); break;
206 default: $ok = false
;
215 public function registerFunction($name, $desc, $callback)
217 if (is_callable($callback, false
, $ref)) {
218 $this->user_functions
['func_' . $name] = array('desc' => $desc, 'callback' => $callback);
224 public function describe($name, $desc)
226 $this->field_desc
[$name] = $desc;
229 public function forceValue($name, $value)
231 $this->field_value
[$name] = $value;
234 private function cleanSession($fields)
236 foreach ($fields as $field) {
237 unset($_SESSION[$field]);
241 /** Handle insertion form
242 * @param $page PlatalPage to process
243 * @param $url URI of the page
244 * @param $field Editable fields
246 public function apply(&$page, $url, $fields = null
)
248 $sesfields = array('csv_value', 'csv_user_value', 'csv_cond_field',
249 'csv_update', 'csv_action', 'csv_cond_field',
250 'csv_cond', 'csv_cond_value', 'csv_cond_then',
251 'csv_cond_else', 'csv', 'csv_separator', 'csv_url');
252 if ($url != @$_SESSION['csv_url']) {
253 $this->cleanSession($sesfields);
254 $_SESSION['csv_url'] = $url;
257 if (is_null($fields) ||
empty($fields)) {
258 $fields = $this->getFieldList();
260 if (is_null($fields)) {
263 foreach ($this->field_value
as $key=>$value) {
264 $search = array_search($key, $fields);
265 unset($fields[$search]);
268 $current = Env
::v('csv_page');
269 if (empty($current)) {
272 $next = Env
::v('csv_next_page');
276 $csv = @$_SESSION['csv'];
277 if ($current == 'source' && Env
::has('csv_valid')) {
278 $csv = Env
::v('csv_source');
279 $_SESSION['csv'] = $csv;
283 if (Env
::has('csv_separator')) {
284 $sep = Env
::v('csv_separator');
288 $_SESSION['csv_separator'] = $sep;
290 $this->setCSV($csv, null
, $_SESSION['csv_separator']);
292 if ($current == 'values' && Env
::has('csv_valid')) {
298 if (Env
::has('csv_action')) {
299 $_SESSION['csv_action'] = Env
::v('csv_action');
301 if ($next == 'valid') {
302 if ($current != 'valid') {
303 $cpyfields = array('csv_value', 'csv_user_value', 'csv_cond_field',
304 'csv_update', 'csv_action', 'csv_cond_field',
305 'csv_cond', 'csv_cond_value', 'csv_cond_then',
307 foreach ($cpyfields as $field) {
308 $_SESSION[$field] = Env
::v($field);
311 $insert = $_SESSION['csv_value'];
312 $values = $_SESSION['csv_user_value'];
313 $update = $_SESSION['csv_update'];
314 foreach ($insert as $key=>$value) {
316 $insert[$key] = null
;
317 } elseif ($value == 'user_value') {
318 $insert[$key] = $values[$key];
319 } elseif ($value == 'cond_value') {
320 $insert[$key] = array($this, 'dynamicCond');
321 } elseif (array_key_exists($value, $this->user_functions
)) {
322 $insert[$key] = $this->user_functions
[$value]['callback'];
324 if (isset($update[$key])) {
325 $update[$key] = $insert[$key];
328 foreach ($this->field_value
as $key=>$value) {
329 $insert[$key] = $value;
332 if ($current == 'valid' && Env
::has('csv_valid')) {
333 $this->run($_SESSION['csv_action'], $insert, $update);
334 $page->assign('csv_done', true
);
335 $this->cleanSession($sesfields);
338 foreach ($this->data
as $line) {
339 $preview[] = $this->makeAssoc($line, $insert);
341 $page->assign('csv_preview', $preview);
344 $page->assign('csv_index', $this->index
);
345 $page->assign('csv_functions', $this->user_functions
);
346 $page->assign('csv_field_desc', $this->field_desc
);
347 $page->assign('csv_page', $next);
348 $page->assign('csv_path', $url);
349 $page->assign('csv_fields', $fields);
353 // vim:set et sw=4 sts=4 sws=4 foldmethod=marker enc=utf-8: