21 $xml =
"\n<DataSyncMap>";
24 $xml .=
"</DataSyncMap>";
29 function import($doc,
$tx)
68 $fullpath =
$config[
"uploadbase"] . DIRECTORY_SEPARATOR . basename(
$file);
70 if (file_exists($fullpath))
75 trace(
"Uploading $file to $fullpath", 3);
77 move_uploaded_file(
$file, $fullpath);
78 chmod($fullpath, 0755);
87 $fp = fopen_utf8(
$file);
101 trace(
"Reading columns for $file", 3);
103 $fp = fopen_utf8(
$file);
105 $fields = fgetcsv_noBOM($fp);
110 foreach($fields as
$field)
122 $offset = checkNumeric($_GET[
"offset"]);
138 if (!file_exists(
$file))
143 trace(
"Opening import file $file", 3);
146 $fp = fopen_utf8(
$file);
148 $fields = fgetcsv_noBOM($fp);
150 foreach($fields as
$field)
160 $record = fgetcsv($fp);
164 $record = array_combine(
$columns, $record);
242 Settings::setDefaultValue(
"data_sync",
"import_in_chunks",
false, Boolean,
"Specifies whether to limit the number of records being imported at one time.");
243 Settings::setDefaultValue(
"data_sync",
"records_per_page", 500, Number,
"The number of records to import at one time when chunked import is enabled.");
244 Settings::setDefaultValue(
"data_sync",
"multiple_import_profiles",
false, Boolean,
"Turn on support for configuring multiple import profile for each sync target.");
256 "Upload File" =>
"data_import",
257 "Select Target" =>
"data_import_select_target",
258 "Choose Fields" =>
"data_import_field_mapping",
259 "Select Records" =>
"data_import_select"
262 $tabBar =
new TabBar(
"tabs",
$tabs);
263 $tabBar->useQueryString =
false;
271 "Upload File" =>
"/admin/data_import",
272 "Select Target" =>
"/admin/data_import_select_target",
273 "Choose Fields" =>
"/admin/data_import_field_mapping",
274 "Select Records" =>
"/admin/data_import_select"
277 $tabBar =
new TabBar(
"tabs",
$tabs);
278 $tabBar->useQueryString =
false;
291 return $adapter->countRecords(
$file);
298 $offset = checkNumeric($_GET[
"offset"]);
364 if (
$field ==
$obj->getPrimaryKey())
continue;
385 if (
$field ==
$obj->getPrimaryKey())
continue;
406 $matchingFields = Query::create(
DataImportFieldMapping,
"WHERE class=:cl AND import_profile_id=:pr AND matching=1")
412 foreach($matchingFields as $matchingField)
414 $mf[] = $matchingField->client_field;
424 $matchingFormat = implode(
"##", $mf);
426 return $matchingFormat;
439 $filter =
new InclusionFilter();
440 $filter->add($item->getPrimaryKey());
441 foreach($matchingFields as
$field)
446 $existingItems = IteratedQuery::create(
$class)
450 $existingItemIDs = array();
452 foreach($existingItems as $item)
454 $existingItemIDs[$item->format($matchingFormat)] = $item->get($item->getPrimaryKey());
457 return $existingItemIDs;
465 trace(
"Retrieving field mapping for $class profile $import_profile_id", 3);
468 IndexedQuery::create(
DataImportFieldMapping,
"WHERE class=:cl AND import_profile_id=:pr AND import_column != ''",
"client_field")
492 $filter =
new InclusionFilter();
510 private static function getRecord($adapter, $fp,
$columns,
$helper =
null, $performLookups =
true)
513 $record = $adapter->getRecord($fp,
$columns);
519 $record =
$helper->processRecord($record, $performLookups);
526 private static function populateItem($item, $record,
$fieldMapping, $lastItem =
null)
531 if ($record[
"__skip__"] ===
true)
return true;
535 if (!
$mapping->import_column)
continue;
541 foreach($cols as $col)
545 $vals[] = $record[$col];
549 $separator = ($item->getType(
$field) == Text) ?
"\n" :
" ";
551 $value = trim(implode($separator, $vals));
553 if (!$value &&
$mapping->grouped && $lastItem)
555 $value = $lastItem->get(
$field);
560 trace(
"Required field $field not set in record. Skipping", 3);
566 $item->set(
$field, $value);
570 if (!$skip) $item->unpack();
605 $matchingFields = Query::create(
DataImportFieldMapping,
"WHERE class=:cl AND import_profile_id=:pr AND matching=1")
610 $matchingConstraint =
"";
612 foreach($matchingFields as $mf)
614 if ($matchingConstraint) $matchingConstraint .=
" AND ";
615 $matchingConstraint .=
"{$mf->client_field}=:{$c}";
619 $matchingQuery = Query::create(
$class,
"WHERE $matchingConstraint");
620 $matchingQuery->filter =
new InclusionFilter($item->getPrimaryKey());
629 $skip = DataSyncManager::populateItem($item, $record,
$fieldMapping, $lastItem);
646 if ($item->hasField(
"owner_id")) $item->set(
"owner_id",
$user->get(
$user->getPrimaryKey()));
650 foreach($matchingFields as $mf)
652 $matchingQuery->bind(
":{$c}", $item->get($mf->client_field));
659 $match = $matchingQuery->executeSingle();
661 $item->set($item->getPrimaryKey(), $match->get($match->getPrimaryKey()));
663 catch(DataNotFoundException $e)
685 trace(
"Batching importing $class profile $import_profile_id from $file", 3);
694 throw new FakoliException(
"DataSyncManager::batchImportItems cannot be used within a browser request");
705 $process->setProgress(
"Running",
"Scanning file", 0);
709 $process->setProgress(
"Running", pluralize(
"$numRecords record").
" found", 0);
714 $matchingFields = Query::create(
DataImportFieldMapping,
"WHERE class=:cl AND import_profile_id=:pr AND matching=1")
719 $matchingConstraint =
"";
721 foreach($matchingFields as $mf)
723 if ($matchingConstraint) $matchingConstraint .=
" AND ";
724 $matchingConstraint .=
"{$mf->client_field}=:{$c}";
728 trace(
"Matching Constraint: $matchingConstraint", 3);
739 $matchingQuery = Query::create(
$class,
"WHERE $matchingConstraint");
740 $matchingQuery->filter =
new InclusionFilter($item->getPrimaryKey());
742 while($record = DataSyncManager::getRecord($adapter, $fp,
$columns,
$helper))
750 $skip = DataSyncManager::populateItem($item, $record,
$fieldMapping, $lastItem);
756 foreach($matchingFields as $mf)
758 trace(
"Matching: {$mf->client_field} = ".$item->get($mf->client_field), 3);
759 $matchingQuery->bind(
":{$c}", $item->get($mf->client_field));
766 $match = $matchingQuery->executeSingle();
768 $item->set($item->getPrimaryKey(), $match->get($match->getPrimaryKey()));
770 catch(DataNotFoundException $e)
779 if (($match && !$importMatching) || (!$match && !$importNew))
786 if (method_exists(
$helper,
'postProcess'))
788 $helper->postProcess($item, $record);
799 $counter = $skipped + $imported;
801 $percentage = intval((100 * $counter) / $numRecords);
803 $process->setProgress(
"Running",
"Processed record $counter of $numRecords", $percentage);
809 $process->setProgress(
"Completed",
"$imported records imported, $skipped records skipped", 100);
814 $process->setProgress(
"Error", $e->getMessage(), $percentage);
820 $val = $item->get($item->getPrimaryKey());
821 return ($val) ?
"matching" :
"new";
834 $syncTargets = array();
854 $mgr->upgrade($version);
862 return (
$mapping->import_column) ?
"mapped" :
"";
static fireEvent($event, $parameter=null, $mustBeConsumed=false)
Fire an event to all subscribers as detailed in their manifests.
openImportFile($file, &$columns)
uploadDataImportFile($field)
skipToOffset($fp, $offset=-1)
Provides a central management class for event handlers and common functionality for the data_sync com...
static registerSyncHelper($class, $helper)
static getAvailableDataAdapters()
static upgradeComponent($version)
static fieldMappingHasMatchField($fieldMappings)
static getFieldMapping($class, $import_profile_id)
static getImportColumns($class, $file="", $format=null)
static registerSerializationHandler()
static createImportItems($class, $import_profile_id=0, $file="", $format=null)
static registerCSVAdapter()
static registerDataSyncAdapter($format, $adapter)
static batchImportItems($class, $import_profile_id, $file, $importMatching, $importNew, $process, $format=null)
static generateFilter($fieldMapping)
static getDataAdapter($format=null)
static isRowSelected($row)
static $import_profile_id
static getAdminImportTabs()
static skipToOffset($fp, $offset=-1)
static getFieldMappings($class, $profile_id=0)
static countRecords($file="", $format=null)
static getActiveFieldMapping($class)
Serialization handler for Link Libraries and Link Records.
FakoliException is the base exception class for all Fakoli errors.
static onItemRow($mapping)
static serialize($class, $constraint="")
Serializes the specified DataItems to XML.
registerHandler($component, $title, $handler)
Registers a serialization handler for a component.
static unserialize($class, $doc, $tx, $save=true)
Instantiates DataItems from the supplied XML document and stores them in the database.
static getValue($component, $name)
Retrieve the value of the specified Setting.
static setDefaultValue($component, $name, $value, $field_type="String", $annotation="", $category="", $options="", $weight=0)
Sets the default value of the given component setting.
if(!checkRole("admin")) $c
skipToOffset($fp, $offset=-1)
uploadDataImportFile($field)
openImportFile($file, &$columns)
IDataSyncHelper defines the interface that application should implement when providing sync helpers t...
getAdditionalColumns($columns)