/** * @link http://clangers.collectiveaccess.org/jira/browse/PROV-1026 */ public function testDataExporterCanLoadFromFile() { $t_locale = new ca_locales(); $va_locales = $t_locale->getLocaleList(); $vn_locale_id = key($va_locales); $t_exporter = new ca_data_exporters(); $va_errors = array(); ca_data_exporters::loadExporterFromFile(__DIR__ . '/data/list_item_export_mapping.xlsx', $va_errors, array('locale_id' => $vn_locale_id)); $vo_exporter = ca_data_exporters::loadExporterByCode('testmappingforunittests'); $this->assertEmpty($va_errors, 'Should be no error messages'); $this->assertTrue(is_object($vo_exporter), 'Should have found an exporter by the correct name'); $this->assertInstanceOf('ca_data_exporters', $vo_exporter, 'Incorrect type loaded'); $vo_exporter->setMode(ACCESS_WRITE); $vo_exporter->delete(true, array('hard' => true)); $vo_exporter = $t_exporter->load(array('exporter_code' => 'testmappingforunittests')); $this->assertFalse($vo_exporter, 'Should no longer have an exporter loaded'); }
public static function export_data($po_opts = null) { require_once __CA_MODELS_DIR__ . "/ca_data_exporters.php"; $vs_search = $po_opts->getOption('search'); $vs_id = $po_opts->getOption('id'); $vb_rdf = (bool) $po_opts->getOption('rdf'); if (!$vb_rdf && !$vs_search && !$vs_id) { print _t('You must specify either an idno or a search expression to select a record or record set for export or activate RDF mode.') . "\n"; return false; } if (!($vs_filename = $po_opts->getOption('file'))) { print _t('You must specify a file to write export output to.') . "\n"; return false; } if (@file_put_contents($vs_filename, "") === false) { // probably a permission error print _t("Can't write to file %1. Check the permissions.", $vs_filename) . "\n"; return false; } // RDF mode if ($vb_rdf) { if (!($vs_config = $po_opts->getOption('config'))) { print _t('You must specify a configuration file that contains the export definition for the RDF mode.') . "\n"; return false; } // test config syntax if (!Configuration::load($vs_config)) { print _t('Syntax error in configuration file %s.', $vs_config) . "\n"; return false; } if (ca_data_exporters::exportRDFMode($vs_config, $vs_filename, array('showCLIProgressBar' => true))) { print _t("Exported data to %1", CLIUtils::textWithColor($vs_filename, 'yellow')); return true; } else { print _t("Could not run RDF mode export") . "\n"; return false; } } // Search or ID mode if (!($vs_mapping = $po_opts->getOption('mapping'))) { print _t('You must specify a mapping for export.') . "\n"; return false; } if (!ca_data_exporters::loadExporterByCode($vs_mapping)) { print _t('Mapping %1 does not exist', $vs_mapping) . "\n"; return false; } if (sizeof($va_errors = ca_data_exporters::checkMapping($vs_mapping)) > 0) { print _t("Mapping %1 has errors: %2", $vs_mapping, join("; ", $va_errors)) . "\n"; return false; } if ($vs_search) { if (!ca_data_exporters::exportRecordsFromSearchExpression($vs_mapping, $vs_search, $vs_filename, array('showCLIProgressBar' => true, 'useNcurses' => true))) { print _t("Could not export mapping %1", $vs_mapping) . "\n"; return false; } else { print _t("Exported data to %1", $vs_filename) . "\n"; } } else { if ($vs_id) { if ($vs_export = ca_data_exporters::exportRecord($vs_mapping, $vs_id, $pa_options = array('singleRecord' => true))) { file_put_contents($vs_filename, $vs_export); print _t("Exported data to %1", CLIUtils::textWithColor($vs_filename, 'yellow')); } else { print _t("Could not export mapping %1", $vs_mapping) . "\n"; return false; } } } }
/** * Checks validity of request parameters * * @return boolean True if parameters are valid, fase if not. */ private function checkParameters($pa_required_parameters, $pa_optional_parameters) { $pa_required_parameters[] = 'verb'; // Check for duplicate parameters if ($_SERVER['REQUEST_METHOD'] == 'GET' && urldecode($_SERVER['QUERY_STRING']) != urldecode(http_build_query($_REQUEST))) { $this->throwError(self::OAI_ERR_BAD_ARGUMENT, _t("Duplicate parameters in request")); } if (!($vs_metadata_prefix = $this->opo_request->getParameter('metadataPrefix', pString)) && (in_array('metadataPrefix', $pa_required_parameters) || in_array('metadataPrefix', $pa_optional_parameters)) && $this->opa_provider_info['default_format']) { $_REQUEST['metadataPrefix'] = $vs_metadata_prefix = $this->opa_provider_info['default_format']; $this->opo_request->setParameter('metadataPrefix', $vs_metadata_prefix, 'REQUEST'); } $va_keys = array_keys($_REQUEST); foreach (array_diff($pa_required_parameters, $va_keys) as $vs_arg) { $this->throwError(self::OAI_ERR_BAD_ARGUMENT, _t("Missing required parameter %1", $vs_arg)); } foreach (array_diff($va_keys, $pa_required_parameters, $pa_optional_parameters) as $vs_arg) { $this->throwError(self::OAI_ERR_BAD_ARGUMENT, _t("Unknown parameter %1", $vs_arg)); } $vs_from = $this->opo_request->getParameter('from', pString); $vs_until = $this->opo_request->getParameter('until', pString); $vs_from_gran = self::getGranularity($vs_from); $vs_until_gran = self::getGranularity($vs_until); if ($vs_from && !$vs_from_gran) { $this->throwError(self::OAI_ERR_BAD_ARGUMENT, _t("Invalid date/time parameter")); } if ($vs_until && !$vs_until_gran) { $this->throwError(self::OAI_ERR_BAD_ARGUMENT, _t("Invalid date/time parameter")); } if ($vs_from && $vs_until && $vs_from_gran != $vs_until_gran) { $this->throwError(self::OAI_ERR_BAD_ARGUMENT, _t("Date/time parameter of differing granularity")); } if (!is_array($this->opa_provider_info['formats'])) { $this->throwError(self::OAI_ERR_CANNOT_DISSEMINATE_FORMAT, _t("Invalid format configuration")); } if ($vs_metadata_prefix) { if (!in_array($vs_metadata_prefix, array_keys($this->opa_provider_info['formats']))) { $this->throwError(self::OAI_ERR_CANNOT_DISSEMINATE_FORMAT, _t("Unknown format %1", $vs_metadata_prefix)); } } if ($vs_mapping = $this->getMappingCode()) { if ($this->exporter = ca_data_exporters::loadExporterByCode($this->getMappingCode())) { if ($this->exporter->getSetting('exporter_format') != "XML") { $this->throwError(self::OAI_ERR_BAD_ARGUMENT, _t("Selected mapping %1 is invalid", $this->getMappingCode())); } $this->table = $this->exporter->getAppDatamodel()->getTableName($this->exporter->get('table_num')); } else { $this->throwError(self::OAI_ERR_CANNOT_DISSEMINATE_FORMAT, _t("Exporter with code %1 does not exist", $this->getMappingCode())); } } else { $this->throwError(self::OAI_ERR_CANNOT_DISSEMINATE_FORMAT, _t("metadataPrefix or default_format is invalid", $this->getMappingCode())); } return !$this->error; }
/** * Export a single record using the mapping defined by this exporter and return as string * @param string $ps_exporter_code defines the exporter to use * @param int $pn_record_id Primary key of the record to export. Record type is determined by the table_num field for this exporter. * @param array $pa_options * singleRecord = Gives a signal to the export format implementation that this is a single record export. For certain formats * this might trigger different behavior, for instance the XML export format prepends the item-level output with <?xml ... ?> * in those cases. * rdfMode = Signals the implementation that this is an RDF mode export * logDirectory = path to directory where logs should be written * logLevel = KLogger constant for minimum log level to record. Default is KLogger::INFO. Constants are, in descending order of shrillness: * KLogger::EMERG = Emergency messages (system is unusable) * KLogger::ALERT = Alert messages (action must be taken immediately) * KLogger::CRIT = Critical conditions * KLogger::ERR = Error conditions * KLogger::WARN = Warnings * KLogger::NOTICE = Notices (normal but significant conditions) * KLogger::INFO = Informational messages * KLogger::DEBUG = Debugging messages * logger = Optional ready-to-use instance of KLogger to use for logging/debugging * @return string Exported record as string */ public static function exportRecord($ps_exporter_code, $pn_record_id, $pa_options = array()) { // The variable cache is valid for the whole record export. // It's being modified in ca_data_exporters::processExporterItem // and then reset here if we move on to the next record. ca_data_exporters::$s_variables = array(); $o_log = caGetOption('logger', $pa_options); // only set up new logging facilities if no existing one has been passed down if (!$o_log || !$o_log instanceof KLogger) { $vs_log_dir = caGetOption('logDirectory', $pa_options); if (!file_exists($vs_log_dir) || !is_writable($vs_log_dir)) { $vs_log_dir = caGetTempDirPath(); } if (!($vn_log_level = caGetOption('logLevel', $pa_options))) { $vn_log_level = KLogger::INFO; } $o_log = new KLogger($vs_log_dir, $vn_log_level); } // make sure we pass logger to item processor $pa_options['logger'] = $o_log; ca_data_exporters::$s_instance_cache = array(); $t_exporter = ca_data_exporters::loadExporterByCode($ps_exporter_code); if (!$t_exporter) { $o_log->logError(_t("Failed to load exporter with code '%1' for item with ID %2", $ps_exporter_code, $pn_record_id)); return false; } $o_log->logInfo(_t("Successfully loaded exporter with code '%1' for item with ID %2", $ps_exporter_code, $pn_record_id)); $va_export = array(); foreach ($t_exporter->getTopLevelItems() as $va_item) { $va_export = array_merge($va_export, $t_exporter->processExporterItem($va_item['item_id'], $t_exporter->get('table_num'), $pn_record_id, $pa_options)); } $o_log->logInfo(_t("The export tree for exporter code '%1' and item with ID %2 is now ready to be processed by the export format (i.e. transformed to XML, for example).", $ps_exporter_code, $pn_record_id)); $o_log->logDebug(print_r($va_export, true)); // we may wanna auto-load this? switch ($t_exporter->getSetting('exporter_format')) { case 'XML': $o_export = new ExportXML(); break; case 'MARC': $o_export = new ExportMARC(); break; case 'CSV': $o_export = new ExportCSV(); break; case 'ExifTool': $o_export = new ExportExifTool(); break; default: return; } $o_export->setLogger($o_log); // if someone wants to mangle the whole tree ... well, go right ahead $o_manager = new ApplicationPluginManager(); $o_manager->hookExportRecord(array('exporter_instance' => $t_exporter, 'record_id' => $pn_record_id, 'export' => &$va_export)); $pa_options['settings'] = $t_exporter->getSettings(); $vs_wrap_before = $t_exporter->getSetting('wrap_before_record'); $vs_wrap_after = $t_exporter->getSetting('wrap_after_record'); if ($vs_wrap_before || $vs_wrap_after) { $pa_options['singleRecord'] = false; } $vs_export = $o_export->processExport($va_export, $pa_options); if (strlen($vs_wrap_before) > 0) { $vs_export = $vs_wrap_before . "\n" . $vs_export; } if (strlen($vs_wrap_after) > 0) { $vs_export = $vs_export . "\n" . $vs_wrap_after; } return $vs_export; }
/** * Export a single record using the mapping defined by this exporter and return as string * @param string $ps_exporter_code defines the exporter to use * @param int $pn_record_id Primary key of the record to export. Record type is determined by the table_num field for this exporter. * @param array $pa_options * singleRecord = Gives a signal to the export format implementation that this is a single record export. For certain formats * this might trigger different behavior, for instance the XML export format prepends the item-level output with <?xml ... ?> * in those cases. * @return string Exported record as string */ public static function exportRecord($ps_exporter_code, $pn_record_id, $pa_options = array()) { ca_data_exporters::$s_instance_cache = array(); $t_exporter = ca_data_exporters::loadExporterByCode($ps_exporter_code); if (!$t_exporter) { return false; } $va_export = array(); foreach ($t_exporter->getTopLevelItems() as $va_item) { $va_export = array_merge($va_export, $t_exporter->processExporterItem($va_item['item_id'], $t_exporter->get('table_num'), $pn_record_id, $pa_options)); } // TODO: we may wanna auto-load this switch ($t_exporter->getSetting('exporter_format')) { case 'XML': $o_export = new ExportXML(); break; case 'MARC': $o_export = new ExportMARC(); break; case 'CSV': $o_export = new ExportCSV(); break; default: return; } // if someone wants to mangle the whole tree ... well, go right ahead $o_manager = new ApplicationPluginManager(); //caDebug($va_export, "Export before tree plugin hook"); if (is_null($va_plugin_export = $o_manager->hookExportRecord(array('exporter_instance' => $t_exporter, 'record_id' => $pn_record_id, 'export' => $va_export)))) { return; // skip this record if plugin returns null } else { $va_export = $va_plugin_export['export']; } //caDebug($va_export,"Export after tree plugin hook"); $pa_options['settings'] = $t_exporter->getSettings(); return $o_export->processExport($va_export, $pa_options); }