71 require_once realpath(dirname(__FILE__)).
"/data_view.inc";
101 $this->
id = (
$id) ? $id :
codify(strtolower($this->class_name)) .
"_data_import";
105 $this->
import =
true;
118 function column($field, $position, $label =
"", $options = array(), $importer =
"", $update_empty =
true)
123 $label = $obj->prettifyFieldName(
$field);
145 $label = $obj->prettifyFieldName(
$field);
154 foreach(func_get_args() as
$field)
156 $this->matches[
$field] =
true;
170 if(count($items) == 0)
176 foreach($items as $item)
178 $pk = $item->getPrimaryKey();
179 $out[$item->$pk] = $item->$nameField;
213 function button($text, $url, $confirm =
null, $isScript =
false)
215 $this->buttons[] = array(
'text' => $text,
'url' => $url,
'confirm' => $confirm,
'isScript' => $isScript);
224 trace(
"Loading Data...", 3);
231 while (($row = fgetcsv($fp)) !== FALSE)
234 if($first && $this->validateDataFile && !call_user_func($this->validateDataFile, $row))
242 $this->objs[$obj->row_number] = $obj;
247 trace(
"Read {$row_number} objects from {$read} rows", 3);
258 $this->
log .= $text .
"</br></br>";
281 $this->
init($obj, $row_number);
283 foreach($this->columns as $column)
285 $position = $column->position;
286 if($position == 0)
continue;
287 $this->
importCell($column, $obj, $row[$position-1]);
292 foreach($this->columns as $column)
294 if($column->position > 0)
continue;
312 if(count($this->matches))
318 $this->savedObjs[$savedObj->$pk] = $savedObj;
319 $obj->$pk = $savedObj->$pk;
321 if(!$obj->getFilter())
return null;
325 if ($this->onPreProcessRow)
327 call_user_func($this->onPreProcessRow, $obj, $savedObj);
345 if(array_key_exists($obj->$pk, $this->savedObjs))
347 return $this->savedObjs[$obj->$pk];
361 if(!count($this->matches))
366 foreach($this->matches as
$field => $dump)
368 $constraint[] =
$field .
"=:$field";
371 $query =
Query::create($this->class_name,
"WHERE " . implode(
" AND ", $constraint));
373 foreach($this->matches as
$field => $dump)
375 $query->bind(
":$field", $obj->$field);
378 $foundObjs = $query->execute();
380 return (count($foundObjs)) ? $foundObjs[0] :
null;
393 $fields = $obj->getFields();
398 foreach($fields as
$field => $type)
401 if(!$column)
continue;
402 $value = $obj->$field;
403 if(($value || $column->update_empty) && $obj->$field != $old->$field)
406 $obj->filter->add(
$field);
407 $old->filter->add(
$field);
420 if(!count($this->columns))
return false;
422 if(count($this->columns))
424 foreach($this->columns as $column)
426 if($column->field ==
$field)
442 function init(&$obj, $row_number)
445 $obj->set(
"row_number", $row_number);
450 if(count($this->objs) == 0)
455 foreach($this->objs as $row_number => $obj)
468 if ($this->onSaveComplete)
470 call_user_func_array($this->onSaveComplete, array($this));
489 $fields = $obj->getFields();
494 $filter = $obj->getFilter();
495 foreach($fields as
$field => $type)
497 if($filter && !$filter->isExcluded(
$field))
499 $out[] =
$field .
" " . $obj->$field;
502 $text =
"<b>Updated</b> $name from row number $row_number $pk {$obj->$pk} " . implode(
" ", $out);
506 foreach($fields as
$field => $type)
508 $out[] =
$field .
" " . $obj->$field;
511 $text =
"<b>Inserted</b> into $name from row number $row_number $pk {$obj->$pk} " . implode(
" ", $out);
514 foreach($this->columns as $column)
516 $warning = $column->getWarning($obj);
519 $text .=
"<span class='warning'>{$warning}</warning>";
530 return $obj->getPrimaryKey();
541 return $obj->prettifyClassName();
551 $table->column(
"Column Name",
"{field}")
552 ->column(
"Title/Label",
"{label}")
553 ->column(
"Options",
"{formatOptions()}")
554 ->column(
"Position",
"{position}")
574 echo
"<div id='data_import'{$class}>\n";
580 else if(!$this->
import)
607 if(count($this->table->items))
609 echo
"<form method='POST' action='' enctype='multipart/form-data'>\n";
610 echo
"<input type='hidden' name='{$this->field}' value='{$this->filepath}'/>\n";
615 $this->table->drawView();
617 if(!count($this->table->items) && !$this->filepath)
624 if(count($this->table->items))
637 echo
"<p><label>Description of columns expected in import file:</label></p>\n";
640 echo
"</br></br><form method='POST' action='' enctype='multipart/form-data'>
641 <label>CSV file to import: </label><input type='file' name='{$this->field}'/><br/><br/>
642 <input type='submit' name='import' class='button' value='Import File'/>
643 <input type='submit' name='preview' class='button' value='Preview Import'/>
658 $fullpath = $config[
"uploadbase"] . DIRECTORY_SEPARATOR . basename($file);
660 if (file_exists($fullpath))
665 trace(
"Uploading $file to $fullpath", 3);
667 move_uploaded_file($file, $fullpath);
668 chmod($fullpath, 0755);
670 $this->filepath = $fullpath;
681 foreach($this->buttons as $button)
683 $url = ($button[
'isScript']) ? $button[
'url'] :
"go('{$button['url']}');";
685 if ($button[
'confirm'])
687 $link =
"if (confirm('".jsSafe($button[
'confirm']).
"')) $url; return false;";
691 $link =
"$url; return false;";
694 if(preg_match(
"/import=1/", $url) && !count($this->objs))
698 $buttons[] =
"<input type='button' class='{$this->buttonCSS}' onclick=\"$link\" value=\"{$button['text']}\"/>";
701 if($this->
preview && $this->table && count($this->table->items))
703 array_unshift(
$buttons,
"<input type='submit' name='import' class='button' value='Import File'/>\n");
706 echo
"<div class='button_row'>" . implode(
" ",
$buttons) .
"</div>";
714 if (fgetcsv($fp) == FALSE)
716 echo
"<div class='error'>Cannot open data file {$filepath}.</div>\n";
735 else if($_FILES[$this->field][
"tmp_name"])
739 else if($_POST[$this->field])
761 foreach($this->columns as $column)
764 $table->column($column->label,
"{{$field}}");
768 $table->emptyMessage =
"No data to be imported.";
781 return "data_import_row_new";
795 foreach($this->columns as $column)
797 $filter->add($column->field);
801 if(count($this->objs))
803 foreach($this->objs as $obj)
806 $pObj->filter = $filter;
807 foreach($this->columns as $column)
809 $pObj->filter->add($column->field);
810 $pObj->set($column->field, $this->formatPreviewCell($pObj, $column));
832 if(is_callable($column->preview_template))
834 return call_user_func($column->preview_template, $obj, $old);
853 if (is_callable($column->importer) && $column->position > 0)
855 return call_user_func($column->importer, $obj, $value);
857 else if (is_callable($column->importer) && $column->position == 0)
859 return call_user_func($column->importer, $obj);
862 else $column->import($obj, $value);
867 return $obj->row_number;
876 "position" => Number,
877 "update_empty" => Boolean,
898 $this->primary_key =
"field";
899 $this->table =
"import_column";
901 $this->field = $field;
902 $this->label = $label;
903 $this->position = $position;
906 $this->update_empty = $update_empty;
922 $this->
template =
"{{$field}}";
935 $field = $this->field;
941 $value .= $this->options[$obj->$field] .
" (" . $obj->format($this->
template) .
")";
964 $obj->fields[$field] = HTML;
965 $value =
"<span class='warning'>{$warning}</warning>\n";
970 $obj->fields[$field] = HTML;
979 if(array_key_exists($obj->row_number, $this->warnings))
981 return $this->warnings[$obj->row_number];
999 $value .=
"</b></br><i>" . $old->format($this->
template) .
"</i>";
1017 if(!$old)
return false;
1037 $field = $this->field;
1041 $value .= $obj->format($this->
template);
1060 $label = $this->label;
1062 $options = array_flip($this->options);
1064 if(array_key_exists($value,
$options))
1070 $this->warning[$obj->row_number] =
"{$label} $value not found";
1080 if(!count($this->options))
1085 foreach($this->options as $key => $value)
1089 $out = implode(
"<br>", $out);
1091 return "<div class='scrollbox' style='height: 200px; overflow: scroll; border: none'>$out</div>";
1100 function import($obj, $value)
1102 $field = $this->field;
1103 $obj->$field = $value;
$template
formatting template for preview display of the data item field
formatOptionPreview($obj, $old)
For fields whose value is derived from a provided options array, format the display of the column in ...
isChanged($old, $field)
Determine if the value has changed.
formatPreview($obj, $old)
Default preview table formatter.
$warnings
store warnings indexed by the object row number pseudo field
endFormatPreview($old, $field)
If the value has changed, show the old value in the table preview.
__construct($field, $position, $label="", $options, $importer, $update_empty=true)
Creates a data import column definition.
$importer
optional callback to handle customized login on import of a column
formatOptions()
Called by input table - show the set of options that represent valid input for the column.
$preview_template
formatting template for preview display of the entire cell
startFormatPreview($obj, $old, $field)
If the value has changed, show the new value in bold.
importOption($obj, $value)
If no customized callback function for setting the columns value on import is provided for a column w...
$options
optional - from related table or DataItem array whose value must match imported value
Import data from a cvs file.
createPreviewData()
Clone each of the objs that would be saved to the db on import and set into a preview object that has...
preProcessRow($obj)
If implementing classes may wish to add custom logic for handling a row before it is saved or display...
importCell($column, $obj, $value)
Given the input value read in, set the value into the field of the object.
$buttons
The custom buttons collection.
getClassName()
Get the display (prettified) version of the class name for the import.
$matches
Field(s) to use to check for a match in db - can be empty.
importOneRow($row, $row_number)
Given a data row, set the value into each field of the DataItem object.
$validateDataFile
optional callback to validate data contents of the file
$class_name
name of data item class to be updated
$objs
Contains data read in from the input file.
getSavedObj($obj)
Called by the build preview table method.
buildInputTable()
Describe the expected columns to the user above the Browse File form.
formatPreviewCell($obj, $column)
When building the preview table, format the column using the supplied DataImportColumn preview templa...
log($text)
Store info, errors, and warnings in a log file and ouput.
$savedObjs
Matches found in the db for data in the import file, indexed by primary key.
$onSaveComplete
Callback event handler that is fired after all the imported rows are saved.
drawButtons()
Draws any additional buttons specified in the calling script.
findMatch($obj)
Check the db for a record that matches the values for the field(s) given in the matches array.
loadData($fp)
Load the data from the spreadsheet (cvs file) into the DataItem objects.
getFilePath()
Implementing classes may wish to retrieve differently (e.g., document library)
button($text, $url, $confirm=null, $isScript=false)
Adds a custom button to the form.
$quiet
Quiet mode - generate no output to the HTML stream.
preview()
Load the data into preview objects and display in a table.
$preview
whether we are in preview mode
setFilter($obj, $old)
If a match to a saved obj is found, set the filter to include only those fields that have changed.
__construct($class_name, $id="")
formatList($items, $nameField)
When instantiating a DataImportColumn, use this function to build an array of option key/value pairs ...
drawForm()
Display the expected input column layout and show a File upload renderer for the user to select the c...
buildPreviewTable()
Display in a DataListView the values read in and set into the data objects and show a Warnings column...
formatSaveLogText($row_number, $obj, $new)
For each row saved, output text stating the row was updated and which fields set.
writeLog()
Output the log.
$filepath
optionally set known file path for csv file; otherwise provide form for user to specify
additional($field, $label="", $template="", $update_empty)
If values are set using logic that does not refer to data in a particular column, use additional with...
column($field, $position, $label="", $options=array(), $importer="", $update_empty=true)
Adds a data import column definition.
$onPreProcessRow
callback for after each row of data is loaded and before it is saved or displayed in preview table
DataItem is the generic base class for database mapped classes.
DataListView displays a list of DataItems (or InnerJoinResults) in tabular format.
Used to place a filter on the contents of a DataItem-derived object.
static create($class, $constraints="")
Static factory method to create a new Query.
codify($name)
Takes a text string and converts it into a code-compliant format, suitable for use as a variable name...
trace($msg, $lvl=3, $callStack=null)
Send output to the trace log.
prettify($name)
Takes a variable or field name and converts it into a human-readable version (assuming that the origi...