Squiz Matrix  4.12.2
 All Data Structures Namespaces Functions Variables Pages
import_asset_csv_to_matrix.php
1 <?php
60 define('IMPORT_ADD_RECORD', 1);
61 define('IMPORT_EDIT_RECORD', 2);
62 define('IMPORT_DELETE_RECORD', 4);
63 
64 
71 function printUsage()
72 {
73  printStdErr("Source CSV file to Matrix importer\n\n");
74  printStdErr("Usage: import_asset_csv_to_matrix [system root] [type code] [csv import file] [parent id] [schema id] [meta map file] [attr map file] (new assets live) (unique field name) (add edit delete field name)\n\n");
75  printStdErr("REQUIRED ARGUMENTS\n");
76  printStdErr("====================================================\n");
77  printStdErr("system root : The Matrix System root directory\n");
78  printStdErr("type code : The Matrix Asset Type Code of the assets to import\n");
79  printStdErr("csv import file : A CSV file containing the records to import as Matrix assets\n");
80  printStdErr("parent id : The asset ID of a Folder etc. under which the assets are to reside\n");
81  printStdErr("schema id : The asset ID of the Metadata Schema to apply to each asset\n");
82  printStdErr("meta map file : A CSV file containing attribute name-to-metadata field ID associations\n");
83  printStdErr("attr map file : A CSV file containing attribute name-to-asset attribute field associations\n");
84  printStdErr("\n");
85  printStdErr("OPTIONAL ARGUMENTS\n");
86  printStdErr("====================================================\n");
87  printStdErr("new assets live : When set to '1' all assets added by the import will be set to 'Live'\n");
88  printStdErr("unique field name : The field in the CSV file to be used for (A)dding, (E)diting, or (D)eleting\n");
89  printStdErr(" assets referenced by imported data\n");
90  printStdErr("add edit delete\n");
91  printStdErr(" field name : The field in the CSV file used to determine the operation performed on imported data\n");
92  printStdErr("ignore csv file : A single column file which specifies the fields to be ignored when editing an existing asset (eg; when importing User\n");
93  printStdErr(" passwords from an Add operation but don't want to overwrite them during an Edit operation\n");
94 
95 }//end printUsage()
96 
97 
106 function printStdErr($string)
107 {
108  fwrite(STDERR, "$string");
109 
110 }//end printStdErr()
111 
112 
130 function importAssets($source_csv_filename, $asset_type_code, $parent_id, $schema_id, Array $metadata_mapping, Array $attribute_mapping, $new_assets_live = FALSE, $unique_record_field = '', $record_modification_field = '', Array $ignore_fields = Array())
131 {
132  $GLOBALS['SQ_SYSTEM']->setRunLevel(SQ_RUN_LEVEL_FORCED);
133 
134  $num_assets_imported = 0;
135  $num_assets_modified = 0;
136  $num_assets_deleted = 0;
137 
138  $csv_fd = fopen($source_csv_filename, 'r');
139  if (!$csv_fd) {
140  printUsage();
141  printStdErr("* The supplied CSV import file was not found\n\n");
142  fclose($csv_fd);
143  exit(-6);
144  }
145 
146  $parent_asset = $GLOBALS['SQ_SYSTEM']->am->getAsset($parent_id);
147  if (!$parent_asset->id) {
148  printUsage();
149  printStdErr("* The specified parent asset was not found\n\n");
150  exit(-7);
151  }
152 
153  $header_line = TRUE;
154  $headers = Array();
155 
156  $trash = $GLOBALS['SQ_SYSTEM']->am->getSystemAsset('trash_folder');
157  $root_folder = $GLOBALS['SQ_SYSTEM']->am->getSystemAsset('root_folder');
158 
159  // Set to true if temporary trash folder is created, where all the assets to be deleted are moved to
160  $temp_trash_folder = FALSE;
161 
162  while (($data = fgetcsv($csv_fd, 0, ',')) !== FALSE) {
163  $num_fields = count($data);
164 
165  $asset_spec = Array();
166 
167  foreach ($data as $key => $val) {
168  if ($header_line) {
169  $headers[$key] = trim($val);
170  } else {
171  $asset_spec[$headers[$key]] = $val;
172  }
173  }
174 
175  if ($header_line) {
176  $header_line = FALSE;
177  } else {
178  // If a Record Modification Field was specified, we also require that a Unique Field was specified for the import
179  // These two fields must be present in the CSV file for us to Edit and Delete existing assets. Otherwise, we'll just add
180  $record_handling = IMPORT_ADD_RECORD;
181 
182  if (!empty($unique_record_field) && !empty($record_modification_field) && isset($asset_spec[$unique_record_field]) && isset($asset_spec[$record_modification_field])) {
183  $record_modification_state = strtoupper($asset_spec[$record_modification_field]);
184  switch ($record_modification_state) {
185  case 'D': $record_handling = IMPORT_DELETE_RECORD;
186  break;
187 
188  case 'E': $record_handling = IMPORT_EDIT_RECORD;
189  break;
190  }
191 
192  // Okey dokey, let's find the existing asset as we are either performing an (E)dit or (D)elete operation...
193  // Also try to find an existing asset as we may be unfortunately performing an (A)dd that matches the unique
194  // identifier, in which case we are probably intending to (E)dit the existing matching asset
195  $existing_asset_id = 0;
196 
197  // Our search is limited to the exact asset type used for the import, and the parent root node (and children) specified
198  // The unique field may be either one to be assigned to an attribute or to a metadata field
199  $search_field = '';
200  $search_value = '';
201 
202  if (isset($metadata_mapping[$unique_record_field])) {
203  $search_type = 'metadata';
204  $search_field = $metadata_mapping[$unique_record_field];
205  $search_value = $asset_spec[$unique_record_field];
206  }
207 
208  if (isset($attribute_mapping[$unique_record_field])) {
209  $search_type = 'attribute';
210  $search_field = $attribute_mapping[$unique_record_field];
211  $search_value = $asset_spec[$unique_record_field];
212  }
213 
214  $search = Array($search_type => Array(
215  'field' => $search_field,
216  'value' => $search_value,
217  )
218  );
219 
220  $existing_assets = findAsset($parent_id, $asset_type_code, $search);
221  if (count($existing_assets) > 1) {
222  // Multiple matching assets - skip
223  printStdErr("\n*\t* The record for '".$search_value."' matched multiple existing assets. Cannot determine how to proceed - continuing to the next record.\n");
224  continue;
225  }
226 
227  $existing_asset_id = reset($existing_assets);
228 
229  // If it is an (E)dit request and the asset was not found, then let's make it an (A)dd instead
230  if (empty($existing_assets) && ($record_handling == IMPORT_EDIT_RECORD)) {
231  printStdErr("\n*\t* The following 'Edit' request for '".$search_value."' has been changed to 'Add' as there is not an existing matching asset\n");
232  $record_handling = IMPORT_ADD_RECORD;
233  }
234 
235  // If it's there and we wanted to (A)dd, then make it an (E)dit instead
236  if (($existing_asset_id > 0) && ($record_handling == IMPORT_ADD_RECORD)) {
237  printStdErr("\n*\t* The following 'Add' request for '".$search_value."' has been changed to 'Edit' as this asset already exists.\n");
238  $record_handling = IMPORT_EDIT_RECORD;
239  }
240 
241  // If it is a (D)elete request and the asset was not found, then skip this record gracefully
242  if (empty($existing_assets) && ($record_handling == IMPORT_DELETE_RECORD)) {
243  printStdErr("\n*\t* Deletion request for asset with unique field value '".$search_value."' was aborted due to a missing matching asset. Continuing to the next record.\n");
244  continue;
245  }
246 
247  if ($record_handling == IMPORT_DELETE_RECORD) {
248 
249  // Deletify
250  printStdErr('- Deleting asset');
251  $asset = $GLOBALS['SQ_SYSTEM']->am->getAsset($existing_asset_id);
252 
253  if ($asset) {
254 
255  // Create temporary trash folder, if not already created
256  if (!$temp_trash_folder) {
257 
258  $GLOBALS['SQ_SYSTEM']->am->includeAsset('folder');
259  $temp_trash_folder = new Folder();
260 
261  $temp_trash_folder->setAttrValue('name','temp_trash_folder');
262  $link_array = Array (
263  'asset' => $root_folder,
264  'value' => '',
265  'link_type' => SQ_LINK_TYPE_1,
266  );
267  $linkid = $temp_trash_folder->create($link_array);
268 
269  // If cannot create the temporary trash folder then we cannot delete any asset
270  if (!$linkid) {
271  printStdErr("\n*\t* Deletion request for asset with unique field value '".$search_value."' was aborted due to unable to create temporary trash folder. Continuing to the next record.\n");
272 
273  $GLOBALS['SQ_SYSTEM']->am->forgetAsset($asset);
274  continue;
275  }
276  }
277 
278  // Move the asset to the temporary trash folder
279  $asset_linkid_old = $GLOBALS['SQ_SYSTEM']->am->getLinkByAsset($parent_id, $asset->id);
280  $linkid = $GLOBALS['SQ_SYSTEM']->am->moveLink($asset_linkid_old['linkid'], $temp_trash_folder->id, SQ_LINK_TYPE_1, -1);
281 
282  // If cannot move the asset to temporary trash folder then it cannot be deleted
283  if (!$linkid) {
284  printStdErr("\n*\t* Deletion request for asset with unique field value '".$search_value."' was aborted due to unable to move this asset to temporary trash folder. Continuing to the next record.\n");
285 
286  $GLOBALS['SQ_SYSTEM']->am->forgetAsset($asset);
287  continue;
288  }
289 
290  echo $search_value.','.$existing_asset_id.",D\n";
291  $num_assets_deleted++;
292 
293  } // End if asset
294  } else if ($record_handling == IMPORT_EDIT_RECORD) {
295  // Editise
296 
297  // Ok we are editing - has the user specified fields to ignore at this point? If so, let's eliminificate
298  foreach ($ignore_fields as $ignore_field_name => $val) {
299  if (isset($asset_spec[$ignore_field_name])) {
300  unset($asset_spec[$ignore_field_name]);
301  }
302  }
303 
304  printStdErr('- Modifying asset with unique field value');
305  editAsset($existing_asset_id, $asset_spec, $attribute_mapping, $metadata_mapping, $schema_id);
306  echo $search_value.','.$existing_asset_id.",E\n";
307  $num_assets_modified++;
308  }
309  }
310 
311  if ($record_handling == IMPORT_ADD_RECORD) {
312  $asset_info = createAsset($asset_spec, $asset_type_code, $parent_asset, $schema_id, $metadata_mapping, $attribute_mapping);
313  $asset_id = 0;
314  if (is_array($asset_info)) {
315  $asset_id = reset($asset_info);
316  }
317 
318  if ($asset_id) {
319  // Ok see if we need to set it live
320  if ($new_assets_live) {
321  $new_asset = $GLOBALS['SQ_SYSTEM']->am->getAsset($asset_id);
322  $new_asset->processStatusChange(SQ_STATUS_LIVE);
323  $GLOBALS['SQ_SYSTEM']->am->forgetAsset($new_asset);
324  }
325 
326  echo key($asset_info).','.$asset_id.",A\n";
327  $num_assets_imported++;
328  }
329  }
330 
331 
332  }
333  }// End while
334 
335  fclose($csv_fd);
336 
337  $GLOBALS['SQ_SYSTEM']->restoreRunLevel();
338 
339  // Now actually delete all the assets moved to "temporary purge folder" by purging this folder
340  if ($temp_trash_folder && $GLOBALS['SQ_SYSTEM']->am->trashAsset($temp_trash_folder->id)) {
341 
342  $trash_folder = $GLOBALS['SQ_SYSTEM']->am->getSystemAsset('trash_folder');
343  $trash_linkid = $GLOBALS['SQ_SYSTEM']->am->getLinkByAsset($trash_folder->id, $temp_trash_folder->id);
344 
345  if (isset($trash_linkid['linkid']) && $trash_linkid['linkid'] > 0) {
346 
347  $hh = $GLOBALS['SQ_SYSTEM']->getHipoHerder();
348 
349  $vars = Array(
350  'purge_root_linkid' => $trash_linkid['linkid'],
351  );
352 
353  $errors = $hh->freestyleHipo('hipo_job_purge_trash', $vars);
354 
355  if (!empty($errors)) {
356  $error_msg = '';
357  foreach($errors as $error) {
358  $error_msg .= ' * '.$error['message'];
359  }
360  echo "Following errors occured while deleting asset(s):\n$error_msg\n";
361  }
362  }
363 
364  }
365 
366  $status_report = Array(
367  'num_added' => $num_assets_imported,
368  'num_modified' => $num_assets_modified,
369  'num_deleted' => $num_assets_deleted,
370  );
371 
372  return $status_report;
373 
374 }//end importAssets()
375 
376 
383 function editAsset($asset_id, Array $asset_spec, Array $attribute_mapping, Array $metadata_mapping, $schema_id)
384 {
385  $asset = $GLOBALS['SQ_SYSTEM']->am->getAsset($asset_id);
386 
387  // Set attributes
388  editAttributes($asset, $asset_spec, $attribute_mapping);
389  printStdErr('.');
390 
391  // Assign metadata schema and values to the asset
392  editMetadata($asset, $asset_spec, $metadata_mapping, $schema_id);
393  printStdErr('.');
394 
395  // Free memory
396  $GLOBALS['SQ_SYSTEM']->am->forgetAsset($asset);
397 
398  printStdErr(' => asset ID '.$asset_id."\n");
399 
400 }//end editAsset()
401 
402 
409 function findAsset($root_asset_id, $asset_type_code, Array $search)
410 {
411  // Begin uberquery!
412  $db = MatrixDAL::getDb();
413 
414  $search_type_attribute = isset($search['attribute']);
415  $field_name = '';
416  $field_value = '';
417 
418  if ($search_type_attribute) {
419  $field_name = $search['attribute']['field'];
420  $field_value = $search['attribute']['value'];
421  } else {
422  $field_name = $search['metadata']['field'];
423  $field_value = $search['metadata']['value'];
424  }
425 
426  $tree_id = '';
427 
428  // Grab a single tree ID so we can search our entire root asset
429  $sql = 'SELECT t.treeid FROM sq_ast_lnk_tree t, sq_ast_lnk l WHERE l.linkid = t.linkid AND l.minorid = :root_asset_id LIMIT 1';
430  try {
431  $query = MatrixDAL::preparePdoQuery($sql);
432  MatrixDAL::bindValueToPdo($query, 'root_asset_id', $root_asset_id);
433 
434  $tree_id = MatrixDAL::executePdoOne($query);
435  } catch (Exception $e) {
436  throw new Exception('Unable to search for an existing '.$asset_type_code.' asset: '.$e->getMessage());
437  }
438 
439  if ($tree_id == '') return Array();
440 
441  // Query portion for restricting by attribute
442  $attribute_sql_from = 'sq_ast_attr r, sq_ast_attr_val v ';
443 
444  // Query portion for restricting by metadata field value
445  $metadata_sql_from = 'sq_ast_mdata_val m ';
446 
447  $sql = 'SELECT a.assetid, a.name '.
448  'FROM sq_ast a, sq_ast_lnk l, sq_ast_lnk_tree t, '.(($search_type_attribute) ? $attribute_sql_from : $metadata_sql_from).
449  'WHERE t.treeid LIKE :tree_id '.
450  'AND l.linkid = t.linkid AND a.assetid = l.minorid ';
451 
452  if (!empty($asset_type_code)) {
453  $sql .= 'AND a.type_code = :type_code ';
454  }
455 
456  if ($search_type_attribute) {
457  $sql .= ' AND v.assetid = a.assetid AND r.name = :field_name AND v.attrid = r.attrid AND v.custom_val = :field_val';
458  } else {
459  $sql .= ' AND m.assetid = a.assetid AND m.fieldid = :field_name AND m.value = :field_val';
460  }
461 
462  try {
463  $query = MatrixDAL::preparePdoQuery($sql);
464  MatrixDAL::bindValueToPdo($query, 'tree_id', $tree_id.'%');
465  MatrixDAL::bindValueToPdo($query, 'field_name', $field_name);
466  MatrixDAL::bindValueToPdo($query, 'field_val', $field_value);
467  if (!empty($asset_type_code)) {
468  MatrixDAL::bindValueToPdo($query, 'type_code', $asset_type_code);
469  }
470  $matching_assets = MatrixDAL::executePdoAssoc($query, 0);
471  } catch (Exception $e) {
472  throw new Exception('Unable to search for an existing '.$asset_type_code.' asset: '.$e->getMessage());
473  }
474 
475  return $matching_assets;
476 
477 }//end findAsset()
478 
479 
489 function createLink(Asset &$parent_asset, Asset &$child_asset)
490 {
491  // Link the asset to the parent asset
492  $link = Array(
493  'asset' => &$parent_asset,
494  'link_type' => 1,
495  'value' => '',
496  'sort_order' => NULL,
497  'is_dependant' => FALSE,
498  'is_exclusive' => FALSE,
499  );
500 
501  $link_id = $child_asset->create($link);
502 
503  return $link_id;
504 
505 }//end createLink()
506 
507 
521 function createAsset(Array $asset_spec, $asset_type_code, Asset &$parent_asset, $schema_id, Array $metadata_mapping, Array $attribute_mapping)
522 {
523  $attribs = Array();
524 
525  printStdErr('- Creating asset');
526 
527  $asset = new $asset_type_code();
528  printStdErr('.');
529 
530  // Set attributes
531  editAttributes($asset, $asset_spec, $attribute_mapping);
532  printStdErr('.');
533 
534  // Link the new asset under the parent folder
535  $link_id = createLink($parent_asset, $asset);
536  printStdErr('.');
537 
538  // Assign metadata schema and values to the asset
539  editMetadata($asset, $asset_spec, $metadata_mapping, $schema_id);
540  printStdErr('.');
541 
542  // Free memory
543  $GLOBALS['SQ_SYSTEM']->am->forgetAsset($asset);
544 
545  printStdErr(' => asset ID '.$asset->id."\n");
546 
547  return Array(reset($asset_spec) => $asset->id);
548 
549 }//end createAsset()
550 
551 
556 function editAttributes(Asset &$asset, Array $asset_spec, Array $attribute_mapping)
557 {
558  $first_attr_name = '';
559  $attrs_modified = FALSE;
560 
561  foreach ($attribute_mapping as $supplied_name => $attribute_name) {
562  if ($first_attr_name == '') {
563  $first_attr_name = $supplied_name;
564  printStdErr(' '.$asset_spec[$first_attr_name]);
565  }
566 
567  // Only set attributes when they are not set to that value already
568  if (isset($asset_spec[$supplied_name]) && ($asset->attr($attribute_name) != $asset_spec[$supplied_name])) {
569  $asset->setAttrValue($attribute_name, $asset_spec[$supplied_name]);
570  $attrs_modified = TRUE;
571  }
572  }
573 
574  // Save attribute values and run updated (default behaviour)
575  // As fixed in Bug 4141
576  if ($attrs_modified) {
577  $asset->saveAttributes();
578  }
579 
580 }//end editAttributes()
581 
582 
587 function editMetadata(Asset &$asset, Array $asset_spec, Array $metadata_mapping, $schema_id)
588 {
589  $mm = $GLOBALS['SQ_SYSTEM']->getMetadataManager();
590  $mm->setSchema($asset->id, $schema_id, TRUE);
591 
592  foreach ($metadata_mapping as $supplied_field_name => $metadata_field_id) {
593  if (isset($asset_spec[$supplied_field_name])) {
594  $metadata = Array($metadata_field_id => Array (
595  0 => Array(
596  'value' => $asset_spec[$supplied_field_name],
597  'name' => $supplied_field_name,
598  )
599  )
600  );
601 
602  $mm->setMetadata($asset->id, $metadata);
603  }
604  }
605 
606  // Be nice and regen the metadata for the lovely people out there
607  $mm->regenerateMetadata($asset->id);
608 
609 }//end editMetadata()
610 
611 
612 /************************** MAIN PROGRAM ****************************/
613 
614 if (ini_get('memory_limit') != '-1') ini_set('memory_limit', '-1');
615 
616 if ((php_sapi_name() != 'cli')) {
617 trigger_error("You can only run this script from the command line\n", E_USER_ERROR);
618 }
619 
620 // Matrix system root directory
621 $argv = $_SERVER['argv'];
622 $GLOBALS['SYSTEM_ROOT'] = (isset($argv[1])) ? $argv[1] : '';
623 if (empty($GLOBALS['SYSTEM_ROOT'])) {
624  printUsage();
625  printStdErr("* The Matrix system root directory must be specified as the first argument\n\n");
626  exit(-99);
627 }
628 
629 require_once $GLOBALS['SYSTEM_ROOT'].'/core/include/init.inc';
630 
631 // Has a Matrix Type Code been supplied?
632 $asset_type_code = $argv[2];
633 if (empty($asset_type_code)) {
634  printUsage();
635  printStdErr("* A Matrix Type Code must be specified as the second argument\n\n");
636  exit(-1);
637 } else {
638  // Check Matrix Type Code
639  $GLOBALS['SQ_SYSTEM']->am->includeAsset($asset_type_code);
640 }
641 
642 // Has an XML filename been supplied?
643 $source_csv_filename = $argv[3];
644 if (empty($source_csv_filename)) {
645  printUsage();
646  printStdErr("* A source CSV filename must be specified as the third argument\n\n");
647  exit(-2);
648 }
649 
650 // Has a parent ID been supplied?
651 $parent_id = (int)$argv[4];
652 if ($parent_id == 0) {
653  printUsage();
654  printStdErr("* A Parent asset ID must be specified as the fourth argument\n\n");
655  exit(-3);
656 }
657 
658 // Has a schema ID been supplied?
659 $schema_id = (int)$argv[5];
660 if ($schema_id == 0) {
661  printUsage();
662  printStdErr("* A Metadata Schema asset ID must be specified as the fifth argument\n\n");
663  exit(-4);
664 }
665 
666 // Has a CSV mapping file been supplied?
667 $mapping_filename = $argv[6];
668 if (empty($mapping_filename)) {
669  printUsage();
670  printStdErr("* A Metadata Field CSV mapping file must be specified as the sixth argument\n\n");
671  exit(-5);
672 }
673 
674 // Has a CSV attribute mapping file been supplied?
675 $attribute_mapping_filename = $argv[7];
676 if (empty($mapping_filename)) {
677  printUsage();
678  printStdErr("* An attribute CSV mapping file must be specified as the seventh argument\n\n");
679  exit(-6);
680 }
681 
682 // Matrix status code for new assets
683 $new_assets_live = (isset($argv[8]) && ($argv[8] == 1));
684 
685 // Has a Unique Record field been specified? (This is optional)
686 $unique_record_field = (isset($argv[9])) ? $argv[9] : '';
687 
688 // Has a Record add / edit / delete column been specified? (This is optional)
689 $record_modification_field = (isset($argv[10])) ? $argv[10] : '';
690 
691 // A file which determines the fields to ignore upon (E)dit (optional)
692 $ignore_csv_filename = (isset($argv[11])) ? $argv[11] : '';
693 
694 // Do the supplied files exist?
695 $csv_fd = fopen($mapping_filename, 'r');
696 if (!$csv_fd) {
697  printUsage();
698  printStdErr("* The supplied metadata mapping file was not found\n\n");
699  fclose($csv_fd);
700  exit(-7);
701 }
702 
703 $metadata_mapping = Array();
704 
705 while (($data = fgetcsv($csv_fd, 0, ',')) !== FALSE) {
706  $num_fields = count($data);
707 
708  if ($num_fields == 2) {
709  $metadata_mapping[trim($data[1])] = (int)$data[0];
710  }
711 }
712 fclose($csv_fd);
713 
714 $csv_fd = fopen($attribute_mapping_filename, 'r');
715 if (!$csv_fd) {
716  printUsage();
717  printStdErr("* The supplied attribute mapping file was not found\n\n");
718  fclose($csv_fd);
719  exit(-8);
720 }
721 
722 $attribute_mapping = Array();
723 
724 while (($data = fgetcsv($csv_fd, 0, ',')) !== FALSE) {
725  $num_fields = count($data);
726 
727  if ($num_fields == 2) {
728  $attribute_mapping[trim($data[0])] = trim($data[1]);
729  }
730 }
731 fclose($csv_fd);
732 
733 $ignore_fields = Array();
734 
735 if ($ignore_csv_filename != '') {
736  $csv_fd = fopen($ignore_csv_filename, 'r');
737  if (!$csv_fd) {
738  printUsage();
739  printStdErr("* The supplied ignore fields file was not found\n\n");
740  fclose($csv_fd);
741  exit(-42);
742  }
743 
744  while (($data = fgetcsv($csv_fd, 0, ',')) !== FALSE) {
745  $num_fields = count($data);
746 
747  if ($num_fields == 1) {
748  $ignore_fields[trim($data[0])] = 1;
749  }
750  }
751  fclose($csv_fd);
752 }
753 
754 $root_user = $GLOBALS['SQ_SYSTEM']->am->getSystemAsset('root_user');
755 $GLOBALS['SQ_SYSTEM']->setCurrentUser($root_user);
756 
757 $status_report = importAssets($source_csv_filename, $asset_type_code, $parent_id, $schema_id, $metadata_mapping, $attribute_mapping, $new_assets_live, $unique_record_field, $record_modification_field, $ignore_fields);
758 
759 $GLOBALS['SQ_SYSTEM']->restoreCurrentUser();
760 
761 printStdErr("\n- All done\n");
762 printStdErr("\tAssets added : ".$status_report['num_added']."\n");
763 printStdErr("\tAssets modified : ".$status_report['num_modified']."\n");
764 printStdErr("\tAssets deleted : ".$status_report['num_deleted']."\n");
765 
766 ?>