Squiz Matrix  4.12.2
 All Data Structures Namespaces Functions Variables Pages
csv_to_xml_actions.php
1 <?php
102 function printUsage()
103 {
104  printStdErr("CSV and metadata mapping to XML converter\n");
105  printStdErr('Usage: csv_to_xml_actions [system root] [csv file] [mapping file] [parent id] [asset type] (-unique) (-ignore_blank)');
106  printStdErr('system root : The Matrix System root directory');
107  printStdErr('csv file : A comma separated values file that represents the site structure');
108  printStdErr('mapping file : An XML file containing column name to metadata mapping data');
109  printStdErr('parent id : The parent asset ID');
110  printStdErr('asset type : Asset type to create for each entry (eg; data_record)');
111  printStdErr('-unique : The "-unique" option will instruct the exporter to exclude duplicate records');
112  printStdErr('-ignore_blank: The "-ignore_blank" option will not attempt to import fields which are blank*');
113  printStdErr(" (* = empty fields or those composed entirely of spaces or dashes)\n");
114 
115 }//end printUsage()
116 
117 
130 function printCreateAssetAction($action_id, $action_type, $type_code, $link_type, $parent_id)
131 {
132  echo "<action>\n";
133  echo ' <action_id>'.$action_id."</action_id>\n";
134  echo ' <action_type>'.$action_type."</action_type>\n";
135  echo ' <type_code>'.$type_code."</type_code>\n";
136  echo ' <link_type>'.$link_type."</link_type>\n";
137  echo ' <parentid>'.$parent_id."</parentid>\n";
138  echo "</action>\n";
139 
140 }//end printCreateAssetAction()
141 
142 
154 function printCreateTriggerAction($action_id, $action_type, $asset, $settings=Array())
155 {
156  echo "<action>\n";
157  echo ' <action_id>'.$action_id."</action_id>\n";
158  echo ' <action_type>'.$action_type."</action_type>\n";
159  echo ' <asset>[['.$asset."]]</asset>\n";
160 
161  foreach ($settings as $setting => $value) {
162  echo ' <'.$setting.'>'.$value.'</'.$setting.">\n";
163  }
164 
165  echo "</action>\n";
166 
167 }//end printCreateTriggerAction()
168 
169 
178 function compactSpaces($string)
179 {
180  return compactCharacters($string, ' ');
181 
182 }//end compactSpaces()
183 
184 
194 function compactCharacters($string, $char)
195 {
196  $orig_string = '';
197  while ($orig_string != $string) {
198  $orig_string = $string;
199  $string = str_replace($char.$char, $char, $string);
200  }
201 
202  return $string;
203 
204 }//end compactCharacters()
205 
206 
215 function getMetadataMapping($mapping_filename)
216 {
217  include_once $GLOBALS['SYSTEM_ROOT'].'/fudge/general/xml_converter.inc';
218 
219  $metadata_mapping = Array(
220  'metadata_schema_id' => 0,
221  'metadata_fields' => Array(),
222  'metadata_ignore_fields' => Array(),
223  'metadata_required_fields' => Array(),
224  'metadata_field_types' => Array(),
225  );
226 
227  // Read metadata mapping info
228  $xml = new XML_Converter();
229  $xml_array = $xml->getArrayFromFile($mapping_filename);
230 
231  // No, not schemii
232  $num_schemata = count($xml_array);
233 
234  // There should only be one schema defined in the mapping file
235  if ($num_schemata != 1) {
236  printStdErr("* A single metadata schema must be defined in the mapping file <schema id=\"[id]\" group_by_field=\"[field_id]\">...</schema>\n");
237  exit(-11);
238  }
239 
240  $schema = $xml_array['schema'];
241  if ($num_schemata != 1) {
242  printStdErr("* The mapping file must contain one root element named 'schema'\n");
243  exit(-12);
244  }
245 
246  $metadata_mapping['metadata_schema_id'] = (int)(trim($schema[0]['@id']));
247  if ($metadata_mapping['metadata_schema_id'] == 0) {
248  printStdErr("* A metadata schema asset id must be specified in the 'id' attribute of the <schema> tag\n");
249  exit(-13);
250  }
251 
252  $metadata_mapping['metadata_schema_group_field'] = 0;
253  if (isset($schema[0]['@group_by_field_id'])) {
254  $metadata_mapping['metadata_schema_group_field'] = (int)(trim($schema[0]['@group_by_field_id']));
255  }
256 
257  $metadata_mapping['metadata_schema_asset_field'] = '';
258  if (isset($schema[0]['@group_by_asset_field'])) {
259  $metadata_mapping['metadata_schema_asset_field'] = trim($schema[0]['@group_by_asset_field']);
260  }
261 
262  $metadata_mapping['metadata_schema_name_field'] = 0;
263  if (isset($schema[0]['@name_field'])) {
264  $metadata_mapping['metadata_schema_name_field'] = trim($schema[0]['@name_field']);
265  }
266 
267  // There should be one level here, with all lines in the form <field id="[id]" alias="[alias]" ... />
268  $num_levels = count($schema);
269  if ($num_levels != 1) {
270  printStdErr("* A single level of field definitions should be defined in the <schema> section in the form <field id=\"[id]\" alias=\"[alias]\" />...\n");
271  exit(-14);
272  }
273 
274  // Reduce the schema to one level only
275  $schema = $schema[0];
276 
277  // Now hopefully the next (and only) lines are single tags called "field"
278  $fields = $schema['field'];
279 
280  $num_fields = count($fields);
281 
282  // There is not much point continuing without the fields
283  if ($num_fields == 0) {
284  printStdErr("* Metadata fields must be defined in the <schema> section in the form <field id=\"[id]\" alias=\"[alias]\" />...\n");
285  exit(-15);
286  }
287 
288  $group_by_field_specified = ($metadata_mapping['metadata_schema_group_field'] > 0);
289  $group_by_field_found = FALSE;
290 
291  $group_by_asset_specified = ($metadata_mapping['metadata_schema_asset_field'] != '');
292  if ($group_by_field_specified && $group_by_asset_specified) {
293  printStdErr("* Group by field and group by parent asset must be used separately\n");
294  exit(-19);
295  }
296 
297  $name_field_specified = ($metadata_mapping['metadata_schema_name_field'] != '');
298  $name_field_found = FALSE;
299 
300  // Assign the mappings for each field
301  foreach ($fields as $field) {
302  $field_id = (int)trim($field['@id']);
303  $field_alias = trim($field['@alias']);
304 
305  // All fields apart from the 'name' field which are present in the CSV file *must* be defined in the XML mapping, however fields
306  // can be "ignored" and therefore will not be used in the import. Ignored fields can still be used for sorting which is nice
307  $ignore_field = ((isset($field['@ignore'])) ? ((int)trim($field['@ignore']) == 1) : 0);
308 
309  if ($field_id == 0) {
310  printStdErr("* A field id must be specified in the 'id' attribute of the <field /> tag\n");
311  exit(-16);
312  }
313 
314  // Check to see if this field is the specified group by field
315  if ($group_by_field_specified) {
316  if ($field_id == $metadata_mapping['metadata_schema_group_field']) {
317  $group_by_field_found = TRUE;
318  }
319  }
320 
321  $metadata_mapping['metadata_fields'][$field_alias] = $field_id;
322 
323  if ($ignore_field) {
324  $metadata_mapping['metadata_ignore_fields'][$field_alias] = 1;
325  }
326 
327  }//end foreach
328 
329  // Perform a check to verify that the specified group by field is defined in the mapping file
330  if ($group_by_field_specified && !$group_by_field_found) {
331  printStdErr("* The specified group_by_field ID was not defined as a <field> in the mapping file\n");
332  exit(-17);
333  }
334 
335  // Perform a check to verify that the specified group by field is defined in the mapping file
336  if (!$name_field_specified) {
337  printStdErr("* A name_field must be specified in the <schema> tag\n");
338  exit(-18);
339  }
340 
341  return $metadata_mapping;
342 
343 }//end getMetadataMapping()
344 
345 
354 function printStdErr($string)
355 {
356  fwrite(STDERR, "$string\n");
357 
358 }//end printStdErr()
359 
360 
369 function validateMetadataMapping(&$metadata_mapping)
370 {
371  // Start Matrix
372  printStdErr('- Initialising Matrix...');
373 
374  // Check the schema is available in the system
375  $schema_asset = $GLOBALS['SQ_SYSTEM']->am->getAsset($metadata_mapping['metadata_schema_id']);
376  if (!$schema_asset) {
377  printStdErr('* The supplied schema (ID: '.$metadata_mapping['metadata_schema_id'].") could not be found in the system\n");
378  exit(-21);
379  }
380  if ($schema_asset->type() != 'metadata_schema') {
381  printStdErr('* The supplied schema (ID: '.$metadata_mapping['metadata_schema_id'].") is not a valid Metadata Schema in the system\n");
382  exit(-22);
383  }
384 
385  // Now we have the schema, find its fields and make sure that they were specified
386  $mm = $GLOBALS['SQ_SYSTEM']->getMetadataManager();
387  $metadata_fields = $mm->getMetadataFields(Array($metadata_mapping['metadata_schema_id']));
388 
389  // Fields specified in the system...
390  $metadata_system_field_ids = array_keys($metadata_fields);
391  $metadata_mapping_field_ids = array_values($metadata_mapping['metadata_fields']);
392 
393  $metadata_differences = array_diff($metadata_system_field_ids, $metadata_mapping_field_ids);
394 
395  if (count($metadata_differences) > 0) {
396  printStdErr('* One or more system metadata fields were not specified in the mapping file');
397  printStdErr(' The following metadata field IDs are required:');
398  foreach ($metadata_differences as $metadata_field_id) {
399  printStdErr(' '.$metadata_field_id);
400  }
401  exit(-23);
402  }
403 
404  // All expected metadata fields were defined in the mapping file. Add the data types to our mapping.
405  // This will be used while importing to verify that the fields are correct
406  $metadata_mapping['metadata_field_types'] = $metadata_fields;
407 
408  $am = $GLOBALS['SQ_SYSTEM']->am;
409 
410  foreach ($metadata_fields as $metadata_field_id => $metadata_field_type) {
411  $metadata_field_type = $metadata_field_type[0]['type_code'];
412  $field = $am->getAsset($metadata_field_id, $metadata_field_type);
413  $metadata_mapping['metadata_field_objects'][$metadata_field_id] = $field;
414 
415  if ($field->attr('required')) {
416  if (isset($metadata_mapping['metadata_ignored_fields'][$metadata_field_id])) {
417  printStdErr('* The metadata field (ID '.$metadata_field_id.') cannot be ignored upon import as it is mandatory');
418  exit(-24);
419  }
420 
421  $metadata_mapping['metadata_required_fields'][$metadata_field_id] = 1;
422  }
423  }
424 
425 }//end validateMetadataMapping()
426 
427 
437 function validateMetadataField(&$metadata_field_object, $value)
438 {
439  $valid_value = FALSE;
440 
441  $metadata_field_type = get_class($metadata_field_object);
442  if ($metadata_field_type == 'Metadata_Field_Text') {
443  $valid_value = TRUE;
444  } else if ($metadata_field_type == 'Metadata_Field_Select') {
445  // Verify that the intended value is available as a selection for this field
446  $selection = $metadata_field_object->getSelectionAttribute();
447  $valid_value = $selection->validateValue($value);
448  } else if ($metadata_field_type == 'Metadata_Field_Thesaurus') {
449  // Ensure that the supplied value is an asset ID of an existing Thesaurus asset
450  $asset_id = (int)($value);
451  if (($asset_id == $value) && ($asset_id > 0)) {
452  $thesaurus = $GLOBALS['SQ_SYSTEM']->am->getAsset($asset_id);
453  $asset_id = $thesaurus->id;
454  }
455  $valid_value = ($asset_id > 0);
456  } else if ($metadata_field_type == 'Metadata_Field_Date') {
457  include_once $GLOBALS['SYSTEM_ROOT'].'/fudge/general/datetime.inc';
458  $valid_value = is_iso8601($value);
459  }
460 
461  return $valid_value;
462 
463 }//end validateMetadataField()
464 
465 
466 /************************** MAIN PROGRAM ****************************/
467 
468 if ((php_sapi_name() != 'cli')) {
469  trigger_error("You can only run this script from the command line\n", E_USER_ERROR);
470 }
471 
472 // Matrix system root directory
473 $argv = $_SERVER['argv'];
474 $GLOBALS['SYSTEM_ROOT'] = (isset($argv[1])) ? $argv[1] : '';
475 if (empty($GLOBALS['SYSTEM_ROOT'])) {
476  printUsage();
477  printStdErr("* The Matrix system root directory must be specified as the first parameter\n");
478  exit(-99);
479 }
480 
481 require_once $GLOBALS['SYSTEM_ROOT'].'/core/include/init.inc';
482 
483 // Has a CSV filename been supplied?
484 $csv_filename = $argv[2];
485 if (empty($csv_filename)) {
486  printUsage();
487  printStdErr("* A CSV filename must be specified as the second parameter\n");
488  exit(-1);
489 }
490 
491 // Has a mapping filename been supplied?
492 $mapping_filename = $argv[3];
493 if (empty($mapping_filename)) {
494  printUsage();
495  printStdErr("* A mapping filename must be specified as the third parameter\n");
496  exit(-2);
497 }
498 
499 // Has a parent ID been supplied?
500 $global_parent_id = $argv[4];
501 if (empty($global_parent_id)) {
502  printUsage();
503  printStdErr("* A parent ID must be specified as the fourth parameter\n");
504  exit(-3);
505 }
506 
507 // Has an asset type been supplied?
508 $global_asset_type = $argv[5];
509 if (empty($global_asset_type)) {
510  printUsage();
511  printStdErr("* An asset type must be specified as the fifth parameter\n");
512  exit(-4);
513 }
514 
515 $export_unique_records_only = FALSE;
516 $ignore_blank_fields = FALSE;
517 
518 if (isset($argv[6])) {
519  $export_unique_records_only = (strtolower($argv[6]) == '-unique');
520  $ignore_blank_fields = (strtolower($argv[6]) == '-ignore_blank');
521 }
522 
523 if (isset($argv[7])) {
524  $export_unique_records_only = ($export_unique_records_only || (strtolower($argv[7]) == '-unique'));
525  $ignore_blank_fields = ($ignore_blank_fields || (strtolower($argv[7]) == '-ignore_blank'));
526 }
527 
528 // Do the supplied files exist?
529 $csv_fd = fopen($csv_filename, 'r');
530 if (!$csv_fd) {
531  printUsage();
532  printStdErr("* The supplied CSV file was not found\n");
533  exit(-5);
534 }
535 
536 $mapping_fd = fopen($mapping_filename, 'r');
537 if (!$mapping_fd) {
538  printUsage();
539  printStdErr("* The supplied mapping file was not found\n");
540  exit(-6);
541 }
542 fclose($mapping_fd);
543 
544 // Yippee, we have the appropriate files. Let's process them now
545 $headers = Array();
546 $metadata_mapping = getMetadataMapping($mapping_filename);
547 
548 $group_by_field = $metadata_mapping['metadata_schema_group_field'];
549 $name_field = $metadata_mapping['metadata_schema_name_field'];
550 
551 $is_header_line = TRUE;
552 
553 // Store the action IDs so we don't clash with namespace
554 $action_ids = Array();
555 
556 validateMetadataMapping($metadata_mapping);
557 
558 printStdErr("- Exporting XML...\n");
559 
560 echo "<?xml version=\"1.0\" encoding=\"iso-8859-1\" ?>\n";
561 echo "<actions>\n";
562 
563 $group_names = Array();
564 
565 // Find the name of the group by field if this was specified
566 $group_by_field_name = '';
567 $group_by_field_column = -1;
568 $group_by_asset_field_column = -1;
569 $name_field_column = -1;
570 
571 if ($group_by_field > 0) {
572  foreach ($metadata_mapping['metadata_fields'] as $field_name => $field_id) {
573  if ($field_id == $group_by_field) {
574  $group_by_field_name = $field_name;
575  break;
576  }
577  }
578 }
579 
580 $num_folders_created = 0;
581 $num_assets_created = 0;
582 $num_fields_ignored = 0;
583 $num_fields_blank = 0;
584 $num_records_ignored = 0;
585 
586 $imported_records = Array();
587 
588 while (($data = fgetcsv($csv_fd, 1024, ',')) !== FALSE) {
589  $num_fields = count($data);
590 
591  if ($num_fields >= 1) {
592  if ($is_header_line) {
593  $headers = $data;
594 
595  // Find the column ID of the group by field if this was specified
596  if ($group_by_field_name != '') {
597  foreach ($headers as $key => $field_name) {
598  if ($field_name == $group_by_field_name) {
599  $group_by_field_column = $key;
600  break;
601  }
602  }
603  }
604 
605  // Find the column ID of the group by asset field if this was specified
606  if (isset($metadata_mapping['metadata_schema_asset_field'])) {
607  if ($metadata_mapping['metadata_schema_asset_field'] != '') {
608  foreach ($headers as $key => $field_name) {
609  if ($field_name == $metadata_mapping['metadata_schema_asset_field']) {
610  $group_by_asset_field_column = $key;
611  break;
612  }
613  }
614  }
615  }
616 
617  // Find the 'name' field - the column to be used to name the asset
618  foreach ($headers as $key => $field_name) {
619  if ($field_name == $name_field) {
620  $name_field_column = $key;
621 
622  // By definition, the 'name' field will be ignored (ie; not imported as metadata), unless it is specified as a <field>.
623  // If this field is required in metadata, the schema should be configured to use %asset_name%
624  // It is assumed that the 'name' field is populated with data for each record, although this does not need to be unique
625  if (!isset($metadata_mapping['metadata_fields'][$name_field])) {
626  $metadata_mapping['metadata_ignore_fields'][$name_field] = 1;
627  }
628 
629  break;
630  }
631  }
632 
633  // The name field must be defined in the mapping file
634  if ($name_field_column < 0) {
635  printStdErr('* The specified name field "'.$name_field."\" was not found in the CSV file\n");
636  exit(-7);
637  }
638 
639  $is_header_line = FALSE;
640  } else {
641 
642  // Ensure that we have all required fields before attempting to create this asset
643  if (count($metadata_mapping['metadata_required_fields'])) {
644  $data_available = TRUE;
645 
646  foreach ($metadata_mapping['metadata_required_fields'] as $required_field_id => $val) {
647  // Check that the data is populated for each required column
648  for ($n=0; $n<count($headers); $n++) {
649  $column_name = $headers[$n];
650  if (!isset($metadata_mapping['metadata_ignore_fields'][$column_name])) {
651  $metadata_field_id = $metadata_mapping['metadata_fields'][$column_name];
652 
653  if ($metadata_field_id == $required_field_id) {
654  $value = trim(compactSpaces($data[$n]));
655 
656  if ($value == '') {
657  $data_available = FALSE;
658  break;
659  }
660  }
661  }
662 
663  }
664  if (!$data_available) break;
665 
666  }
667 
668  // Skip ahead to the next record in the CSV file if the required fields are not populated
669  if (!$data_available) {
670  $num_records_ignored++;
671  continue;
672  }
673  }
674 
675  // Remove extra spaces from the record name. Name the alias using the 'name' field
676  $name = trim($data[$name_field_column]);
677  $name = compactSpaces($name);
678 
679  // Tidy up the action ID
680  $action_id = strtolower($name);
681  $action_id = ereg_replace(' ', '_', $action_id);
682  $action_id = ereg_replace(',', '', $action_id);
683 
684  // Aargh - a namespace clash! Better assign a new action ID for triggering purposes. This does not affect the asset name
685  $n = 0;
686  if (isset($action_ids[$action_id])) {
687  $n = 1;
688  while (isset($action_ids[$action_id.'_'.$n])) {
689  $n++;
690  }
691  }
692 
693  // All better now, let's bags this action ID
694  if ($n > 0) $action_id = $action_id.'_'.$n;
695  $action_ids[$action_id] = 1;
696 
697  // Create a folder to house the assets if a group by field was specified and one does not already exist from this import
698  $group_by_folder_name = '';
699  $folder_name_orig = '';
700  $folder_name = '';
701  if ($group_by_field_column >= 0) {
702  $value = trim($data[$group_by_field_column]);
703  $value = compactSpaces($value);
704 
705  $folder_name_orig = $value;
706  $folder_name = ereg_replace(' ', '_', $value);
707  $folder_name = ereg_replace(',', ' ', $folder_name);
708 
709  $group_by_folder_name = 'create_folder_'.$folder_name;
710 
711  // Create a folder if one has not been created during this import with the specified name
712  if (!isset($group_names[$value])) {
713  $group_names[$value] = 1;
714 
715  // Create folder asset
716  printStdErr('- Creating folder '.$value);
717  printCreateAssetAction('create_folder_'.$folder_name, 'create_asset', 'folder', '1', $global_parent_id);
718 
719  $num_folders_created++;
720 
721  // Then name the folder...
722  $settings = Array(
723  'attribute' => 'name',
724  'value' => $value,
725  );
726  printCreateTriggerAction('set_folder_'.$folder_name.'_name', 'set_attribute_value', 'output://create_folder_'.$folder_name.'.assetid', $settings);
727  }
728 
729  // ...and give it a web path
730  $settings = Array(
731  'path' => $folder_name,
732  );
733  printCreateTriggerAction('set_folder_'.$folder_name.'_path', 'add_web_path', 'output://create_folder_'.$folder_name.'.assetid', $settings);
734  }//end if
735 
736  // Now create an asset of the specified type (under the relevant group by folder, if specified)
737  $asset_parent_id = $global_parent_id;
738  if ($folder_name != '') {
739  $asset_parent_id = '[[output://create_folder_'.$folder_name.'.assetid]]';
740  }
741 
742  // Hold on to our metadata for exporting later. This is done so we can exclude duplicate records if they are encountered
743  $record_metadata = Array();
744  for ($n=0; $n<$num_fields; $n++) {
745  $column_name = trim($headers[$n]);
746 
747  // Only process fields in which we are interested (ie; where "ignore" is not set)
748  if (!isset($metadata_mapping['metadata_ignore_fields'][$column_name])) {
749  // Any value set to dashes only OR blank denotes an empty field, so don't bother with this one. Otherwise compact contiguous spaces
750  $value = trim(compactSpaces($data[$n]));
751 
752  if ($ignore_blank_fields && ((compactCharacters($value, '-') == '-') || ($value == ''))) {
753  $num_fields_blank++;
754  continue;
755  }
756 
757  $metadata_field_id = $metadata_mapping['metadata_fields'][$column_name];
758 
759  if (!isset($metadata_field_id)) {
760  printStdErr('* Metadata schema mapping is missing for the "'.$column_name."\" field. Cannot continue\n");
761  exit(-8);
762  }
763 
764  $record_metadata[$metadata_field_id] = $value;
765  }
766  }
767 
768  // If we are after unique records only (ie; the '-unique' parameter was specified), then ensure that this record is not a duplicate of one already processed. If it is, then it will be ignored
769  if ($export_unique_records_only) {
770  $record_serialised = serialize($record_metadata);
771 
772  if (isset($imported_records[$record_serialised])) {
773  // This record has already been imported. Continue with the next record
774  printStdErr('--- Ignoring duplicate asset '.$name.(($folder_name_orig != '') ? (' in folder "'.$folder_name_orig).'"' : ''));
775  $num_records_ignored++;
776  continue;
777  } else {
778  $imported_records[$record_serialised] = 1;
779  }
780  }
781 
782  // Find the parent so we can dynamically associate the child assets - this should be an Asset ID
783  if ($group_by_asset_field_column >= 0) {
784  $asset_parent_id = (int)$data[$group_by_asset_field_column];
785  printStdErr('-- Targeting asset '.$asset_parent_id);
786  }
787 
788  printStdErr('-- Creating asset '.$name.(($folder_name_orig != '') ? (' in folder "'.$folder_name_orig).'"' : ''));
789  printCreateAssetAction($action_id, 'create_asset', $global_asset_type, '1', $asset_parent_id);
790 
791  $num_assets_created++;
792 
793  // Then name the asset...
794  $settings = Array(
795  'attribute' => 'name',
796  'value' => $name,
797  );
798  printCreateTriggerAction('set_'.$action_id.'_name', 'set_attribute_value', 'output://'.$action_id.'.assetid', $settings);
799 
800  // ...and give it a web path
801  $settings = Array(
802  'path' => $action_id,
803  );
804  printCreateTriggerAction('set_'.$action_id.'_path', 'add_web_path', 'output://'.$action_id.'.assetid', $settings);
805 
806  // Set the appropriate metadata schema for this asset
807  $settings = Array(
808  'schemaid' => $metadata_mapping['metadata_schema_id'],
809  'granted' => 1,
810  );
811  printCreateTriggerAction('set_'.$action_id.'_metadata_schema', 'set_metadata_schema', 'output://'.$action_id.'.assetid', $settings);
812 
813  // Finally, assign the relevant metadata
814  foreach ($record_metadata as $metadata_field_id => $value) {
815  $metadata_value_valid = validateMetadataField($metadata_mapping['metadata_field_objects'][$metadata_field_id], $value);
816 
817  if ($metadata_value_valid) {
818  $settings = Array(
819  'fieldid' => $metadata_field_id,
820  'value' => $value,
821  );
822  printCreateTriggerAction('set_'.$action_id.'_metadata_value_'.$metadata_field_id, 'set_metadata_value', 'output://'.$action_id.'.assetid', $settings);
823  } else {
824  printStdErr("\n* The value (".$value.') set for field '.$metadata_field_id.' is invalid for a '.get_class($metadata_mapping['metadata_field_objects'][$metadata_field_id])." field\n");
825  printStdErr('User Options ------------');
826  printStdErr('(I)gnore this field and continue exporting subsequent records');
827  printStdErr('(C)ancel export');
828 
829  $valid_choice = FALSE;
830  while (!$valid_choice) {
831  $user_choice = rtrim(strtolower(fgets(STDIN, 3)));
832  $valid_choice = (($user_choice == 'i') || ($user_choice == 'c'));
833  }
834 
835  if ($user_choice == 'c') {
836  printStdErr("\n- Export cancelled by user");
837  exit(-9);
838  }
839 
840  $num_fields_ignored++;
841 
842  }
843 
844  }
845 
846  }//end else
847  }//end if
848 }//end while
849 
850 echo "</actions>\n";
851 
852 fclose($csv_fd);
853 
854 // We're done. Display some totals to show what has been accomplished
855 printStdErr("\n- All done, stats below:");
856 printStdErr('Folders created: '.$num_folders_created);
857 printStdErr('Assets created : '.$num_assets_created);
858 printStdErr('Records ignored: '.$num_records_ignored);
859 printStdErr('Fields ignored (by user) : '.$num_fields_ignored);
860 printStdErr('Fields ignored (blank) : '.$num_fields_blank."\n");
861 
862 // That's all folks :-D
863 
864 ?>