Example #1
0
 /**
  * Return the Indicia form code
  * @param array $args Input parameters.
  * @param array $node Drupal node object
  * @param array $response Response from Indicia services after posting a verification.
  * @return HTML string
  */
 public static function get_form($args, $node, $response)
 {
     require_once drupal_get_path('module', 'iform') . '/client_helpers/import_helper.php';
     $auth = import_helper::get_read_write_auth($args['website_id'], $args['password']);
     if ($args['model'] == 'url') {
         if (!isset($_GET['type'])) {
             return "This form is configured so that it must be called with a type parameter in the URL";
         }
         $model = $_GET['type'];
     } else {
         $model = $args['model'];
     }
     if (isset($args['presetSettings'])) {
         $presets = array();
         $presetLines = explode("\n", $args['presetSettings']);
         foreach ($presetLines as $preset) {
             $preset = explode('=', $preset);
             // skip any invalid data for the presets
             if (count($preset) == 2) {
                 $presets[$preset[0]] = $preset[1];
             }
         }
         $presets = array_merge(array('website_id' => $args['website_id'], 'password' => $args['password']), $presets);
     } else {
         $presets = array('website_id' => $args['website_id'], 'password' => $args['password']);
     }
     $r = import_helper::importer(array('model' => $model, 'auth' => $auth, 'presetSettings' => $presets));
     return $r;
 }
Example #2
0
 /**
  * Return the Indicia form code
  * @param array $args Input parameters.
  * @param array $node Drupal node object
  * @param array $response Response from Indicia services after posting a verification.
  * @return HTML string
  */
 public static function get_form($args, $node, $response)
 {
     iform_load_helpers(array('import_helper'));
     $auth = import_helper::get_read_write_auth($args['website_id'], $args['password']);
     if ($args['model'] == 'url') {
         if (!isset($_GET['type'])) {
             return "This form is configured so that it must be called with a type parameter in the URL";
         }
         $model = $_GET['type'];
     } else {
         $model = $args['model'];
     }
     if (isset($args['presetSettings'])) {
         $presets = get_options_array_with_user_data($args['presetSettings']);
         $presets = array_merge(array('website_id' => $args['website_id'], 'password' => $args['password']), $presets);
     } else {
         $presets = array('website_id' => $args['website_id'], 'password' => $args['password']);
     }
     $r = import_helper::importer(array('model' => $model, 'auth' => $auth, 'presetSettings' => $presets));
     return $r;
 }
Example #3
0
 /**
  * Return the Indicia form code
  * @param array $args Input parameters.
  * @param array $node Drupal node object
  * @param array $response Response from Indicia services after posting a verification.
  * @return HTML string
  */
 public static function get_form($args, $node, $response)
 {
     iform_load_helpers(array('import_helper'));
     $auth = import_helper::get_read_write_auth($args['website_id'], $args['password']);
     group_authorise_form($args, $auth['read']);
     if ($args['model'] == 'url') {
         if (!isset($_GET['type'])) {
             return "This form is configured so that it must be called with a type parameter in the URL";
         }
         $model = $_GET['type'];
     } else {
         $model = $args['model'];
     }
     if (isset($args['presetSettings'])) {
         $presets = get_options_array_with_user_data($args['presetSettings']);
         $presets = array_merge(array('website_id' => $args['website_id'], 'password' => $args['password']), $presets);
     } else {
         $presets = array('website_id' => $args['website_id'], 'password' => $args['password']);
     }
     if (!empty($_GET['group_id'])) {
         // loading data into a recording group.
         $group = data_entry_helper::get_population_data(array('table' => 'group', 'extraParams' => $auth['read'] + array('id' => $_GET['group_id'], 'view' => 'detail')));
         $group = $group[0];
         $presets['sample:group_id'] = $_GET['group_id'];
         hostsite_set_page_title(lang::get('Import data into the {1} group', $group['title']));
         // if a single survey specified for this group, then force the data into the correct survey
         $filterdef = json_decode($group['filter_definition'], true);
         if (!empty($filterdef['survey_list_op']) && $filterdef['survey_list_op'] === 'in' && !empty($filterdef['survey_list'])) {
             $surveys = explode(',', $filterdef['survey_list']);
             if (count($surveys) === 1) {
                 $presets['survey_id'] = $surveys[0];
             }
         }
     }
     try {
         $r = import_helper::importer(array('model' => $model, 'auth' => $auth, 'presetSettings' => $presets));
     } catch (Exception $e) {
         hostsite_show_message($e->getMessage(), 'warning');
         $reload = import_helper::get_reload_link_parts();
         unset($reload['params']['total']);
         unset($reload['params']['uploaded_csv']);
         $reloadpath = $reload['path'] . '?' . import_helper::array_to_query_string($reload['params']);
         $r = "<p>" . lang::get('Would you like to ') . "<a href=\"{$reloadpath}\">" . lang::get('import another file?') . "</a></p>";
     }
     return $r;
 }
 /**
  * Outputs the form for mapping columns to the import fields.
  * @param array $options Options array passed to the import control.
  */
 private static function upload_mappings_form($options)
 {
     ini_set('auto_detect_line_endings', 1);
     if (!file_exists($_SESSION['uploaded_file'])) {
         return lang::get('upload_not_available');
     }
     self::add_resource('jquery_ui');
     $filename = basename($_SESSION['uploaded_file']);
     // If the last step was skipped because the user did not have any settings to supply, presetSettings contains the presets.
     // Otherwise we'll use the settings form content which already in $_POST so will overwrite presetSettings.
     if (isset($options['presetSettings'])) {
         $settings = array_merge($options['presetSettings'], $_POST);
     } else {
         $settings = $_POST;
     }
     // only want defaults that actually have a value - others can be set on a per-row basis by mapping to a column
     foreach ($settings as $key => $value) {
         if (empty($value)) {
             unset($settings[$key]);
         }
     }
     // cache the mappings
     $metadata = array('settings' => json_encode($settings));
     $post = array_merge($options['auth']['write_tokens'], $metadata);
     $request = parent::$base_url . "index.php/services/import/cache_upload_metadata?uploaded_csv={$filename}";
     $response = self::http_post($request, $post);
     if (!isset($response['output']) || $response['output'] != 'OK') {
         return "Could not upload the settings metadata. <br/>" . print_r($response, true);
     }
     $request = parent::$base_url . "index.php/services/import/get_import_fields/" . $options['model'];
     $request .= '?' . self::array_to_query_string($options['auth']['read']);
     // include survey and website information in the request if available, as this limits the availability of custom attributes
     if (!empty($settings['website_id'])) {
         $request .= '&website_id=' . trim($settings['website_id']);
     }
     if (!empty($settings['survey_id'])) {
         $request .= '&survey_id=' . trim($settings['survey_id']);
     }
     if (!empty($settings['useAssociations']) && $settings['useAssociations']) {
         $request .= '&use_associations=true';
     }
     $response = self::http_post($request, array());
     $fields = json_decode($response['output'], true);
     if (!is_array($fields)) {
         return "curl request to {$request} failed. Response " . print_r($response, true);
     }
     $request = str_replace('get_import_fields', 'get_required_fields', $request);
     $response = self::http_post($request);
     $responseIds = json_decode($response['output'], true);
     if (!is_array($responseIds)) {
         return "curl request to {$request} failed. Response " . print_r($response, true);
     }
     $model_required_fields = self::expand_ids_to_fks($responseIds);
     if (!empty($settings)) {
         $preset_fields = self::expand_ids_to_fks(array_keys($settings));
     } else {
         $preset_fields = array();
     }
     if (!empty($preset_fields)) {
         $unlinked_fields = array_diff_key($fields, array_combine($preset_fields, $preset_fields));
     } else {
         $unlinked_fields = $fields;
     }
     // only use the required fields that are available for selection - the rest are handled somehow else
     $unlinked_required_fields = array_intersect($model_required_fields, array_keys($unlinked_fields));
     $handle = fopen($_SESSION['uploaded_file'], "r");
     $columns = fgetcsv($handle, 1000, ",");
     $reload = self::get_reload_link_parts();
     $reloadpath = $reload['path'] . '?' . self::array_to_query_string($reload['params']);
     self::clear_website_survey_fields($unlinked_fields, $settings);
     self::clear_website_survey_fields($unlinked_required_fields, $settings);
     $savedFieldMappings = array();
     //get the user's checked preference for the import page
     if (function_exists('hostsite_get_user_field')) {
         $json = hostsite_get_user_field('import_field_mappings');
         if ($json === false) {
             if (!hostsite_set_user_field('import_field_mappings', '[]')) {
                 self::$rememberingMappings = false;
             }
         } else {
             $json = trim($json);
             $savedFieldMappings = json_decode(trim($json), true);
         }
     } else {
         // host does not support user profiles, so we can't remember mappings
         self::$rememberingMappings = false;
     }
     //  if the user checked the Remember All checkbox need to remember this setting
     $checkedRememberAll = isset($savedFieldMappings['RememberAll']) ? ' checked="checked"' : '';
     $r = "<form method=\"post\" id=\"entry_form\" action=\"{$reloadpath}\" class=\"iform\">\n" . '<p>' . lang::get('column_mapping_instructions') . '</p>' . '<div class="ui-helper-clearfix import-mappings-table"><table class="ui-widget ui-widget-content">' . '<thead class="ui-widget-header">' . "<tr><th>" . lang::get('Column in CSV File') . "</th><th>" . lang::get('Maps to attribute') . "</th>";
     if (self::$rememberingMappings) {
         $r .= "<th id='remember-all-header' name='remember-all-header'>" . lang::get('Remember choice?') . "<br/><input type='checkbox' name='RememberAll' id='RememberAll' value='1' title='" . lang::get('Tick all boxes to remember every column mapping next time you import.') . "'{$checkedRememberAll}/></th>";
         self::$javascript .= "\$('#RememberAll').change(function() {\n  if (this.checked) {\n   \$(\".rememberField\").attr(\"checked\",\"checked\")\n  } else {\n   \$(\".rememberField\").removeAttr(\"checked\")\n  }\n});\n";
     }
     $r .= '</tr></thead><tbody>';
     foreach ($columns as $column) {
         $colFieldName = preg_replace('/[^A-Za-z0-9]/', '_', $column);
         $r .= "<tr><td>{$column}</td><td><select name=\"{$colFieldName}\" id=\"{$colFieldName}\">";
         $r .= self::get_column_options($options['model'], $unlinked_fields, $column, ' ', $savedFieldMappings);
         $r .= "</select></td></tr>\n";
     }
     $r .= '</tbody>';
     $r .= '</table>';
     $r .= '<div id="required-instructions" class="import-mappings-instructions"><h2>' . lang::get('Tasks') . '</h2><span>' . lang::get('The following database attributes must be matched to a column in your import file before you can continue') . ':</span><ul></ul><br/></div>';
     $r .= '<div id="duplicate-instructions" class="import-mappings-instructions"><span id="duplicate-instruct">' . lang::get('There are currently two or more drop-downs allocated to the same value.') . '</span><ul></ul><br/></div></div>';
     $r .= '<input type="hidden" name="import_step" value="2" />';
     $r .= '<input type="submit" name="submit" id="submit" value="' . lang::get('Upload') . '" class="ui-corner-all ui-state-default button" />';
     $r .= '</form>';
     self::$javascript .= "function detect_duplicate_fields() {\n      var valueStore = [];\n      var duplicateStore = [];\n      var valueStoreIndex = 0;\n      var duplicateStoreIndex = 0;\n      \$.each(\$('#entry_form select'), function(i, select) {\n        if (valueStoreIndex==0) {\n          valueStore[valueStoreIndex] = select.value;\n          valueStoreIndex++;\n        } else {\n          for(i=0; i<valueStoreIndex; i++) {\n            if (select.value==valueStore[i] && select.value != '<" . lang::get('Not imported') . ">') {\n              duplicateStore[duplicateStoreIndex] = select.value;\n              duplicateStoreIndex++;\n            }\n             \n          }\n          valueStore[valueStoreIndex] = select.value;\n          valueStoreIndex++;\n        }      \n      })\n      if (duplicateStore.length==0) {\n        DuplicateAllowsUpload = 1;\n        \$('#duplicate-instruct').css('display', 'none');\n      } else {\n        DuplicateAllowsUpload = 0;\n        \$('#duplicate-instruct').css('display', 'inline');\n      }\n    }\n";
     self::$javascript .= "function update_required_fields() {\n      // copy the list of required fields\n      var fields = \$.extend(true, {}, required_fields),\n          sampleVagueDates = [],\n    \t  locationReference = false,\n          fieldTokens, thisValue;\n      \$('#required-instructions li').remove();\n      // strip out the ones we have already allocated\n      \$.each(\$('#entry_form select'), function(i, select) {\n        thisValue = select.value;\n        // If there are several options of how to search a single lookup then they\n        // are identified by a 3rd token, e.g. occurrence:fk_taxa_taxon_list:search_code.\n        // These cases fulfil the needs of a required field so we can remove them.\n        fieldTokens = thisValue.split(':');\n        if (fieldTokens.length>2) {\n          fieldTokens.pop();\n          thisValue = fieldTokens.join(':');\n        }\n        delete fields[thisValue];\n        // special case for vague dates - if we have a complete sample vague date, then can strike out the sample:date required field\n        if (select.value.substr(0,12)=='sample:date_') {\n          sampleVagueDates.push(thisValue);\n        }\n    \t// and another special case for samples: can either include the sref or a foreign key reference to a location.\n    \tif (select.value.substr(0,18)=='sample:fk_location') { // catches the code based fk as well\n          locationReference = true;\n        }\n      });\n      if (sampleVagueDates.length==3) {\n        // got a full vague date, so can remove the required date field\n        delete fields['sample:date'];\n      }\n      if (locationReference) {\n        // got a location foreign key reference, so can remove the required entered sref fields\n        delete fields['sample:entered_sref'];\n    \tdelete fields['sample:entered_sref_system']\n      }\n      var output = '';\n      \$.each(fields, function(field, caption) {\n        output += '<li>'+caption+'</li>';\n      });\n      if (output==='') {\n        \$('#required-instructions').css('display', 'none');\n        RequiredAllowsUpload = 1;\n      } else {\n        \$('#required-instructions').css('display', 'inline');\n        RequiredAllowsUpload = 0;\n      }\n      if (RequiredAllowsUpload == 1 && DuplicateAllowsUpload == 1) {\n        \$('#submit').attr('disabled', false);\n      } else {\n        \$('#submit').attr('disabled', true);\n      }\n      \$('#required-instructions ul').html(output);\n    }\n";
     self::$javascript .= "required_fields={};\n";
     foreach ($unlinked_required_fields as $field) {
         $caption = $unlinked_fields[$field];
         if (empty($caption)) {
             $tokens = explode(':', $field);
             $fieldname = $tokens[count($tokens) - 1];
             $caption = lang::get(self::processLabel(preg_replace(array('/^fk_/', '/_id$/'), array('', ''), $fieldname)));
         }
         $caption = self::translate_field($field, $caption);
         self::$javascript .= "required_fields['{$field}']='{$caption}';\n";
     }
     self::$javascript .= "detect_duplicate_fields();\n";
     self::$javascript .= "update_required_fields();\n";
     self::$javascript .= "\$('#entry_form select').change(function() {detect_duplicate_fields(); update_required_fields();});\n";
     return $r;
 }
Example #5
0
 *
 * This program is free software: you can redistribute it and/or modify
 * it under the terms of the GNU General Public License as published by
 * the Free Software Foundation, either version 3 of the License, or
 * any later version.
 * This program is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 * GNU General Public License for more details.
 * You should have received a copy of the GNU General Public License
 * along with this program.  If not, see http://www.gnu.org/licenses/gpl.html.
 *
 * @package    Core
 * @subpackage Libraries
 * @author    Indicia Team
 * @license    http://www.gnu.org/licenses/gpl.html GPL
 * @link     http://code.google.com/p/indicia/
 */
/**
 * This is a view which outputs a parameters entry form to capture values that will apply to every row during an import, such as the website id.
 */
require_once DOCROOT . 'client_helpers/import_helper.php';
$auth = import_helper::get_read_write_auth(0 - $_SESSION['auth_user']->id, kohana::config('indicia.private_key'));
echo import_helper::importer(array('model' => $this->controllerpath, 'auth' => $auth));
import_helper::$dumped_resources[] = 'jquery';
import_helper::$dumped_resources[] = 'jquery-ui';
echo import_helper::dump_javascript();
?>


 protected function submit_data_if_new_parent_sample_required(&$values, $data, $args, $writeAuth, $occurrenceNumber, &$submission)
 {
     //There are 2 arrays we are dealing with. $_POST contains the name of the column as a key and then the format
     //of the key required for submission as its value. The $data array is a numbered list of columns with a data
     //value. So in order to submit to the database, we need to use the $_POST data value as the key and the value from the $data
     //array as the value. The two arrays match up with each other e.g. the second item in the $_POST array relates to the
     //second item in the data array. So by counting as we look at each item in the $_POST array, we can then get the equivalent
     //item in the $data array as required.
     $postCounter = 0;
     //Assume to start with that we are going to use the parent sample from the previous row.
     $newSampleRequired = false;
     foreach ($_POST as $fieldName => $fieldInPostFormat) {
         //Check if any of the sample attributes have changed and also data held in the sample row in the database (as opposed to data held in the sample_attributes table)
         if ($fieldInPostFormat == 'sample:entered_sref' || $fieldInPostFormat == 'sample:date' || $fieldInPostFormat == 'sample:comment' || $fieldInPostFormat == 'sample:location_name' || substr($fieldInPostFormat, 0, 8) === "smpAttr:") {
             if (!empty($values[$fieldInPostFormat]) && $values[$fieldInPostFormat] != $data[$postCounter]) {
                 $newSampleRequired = true;
             }
         }
         //For the Site we submit an id rather than the raw name.
         if ($fieldName == 'Site') {
             //If there is no main location, this is still a valid scenerio as there can be an "Other Site"
             if (empty($data[$postCounter])) {
                 $values['sample:location_id'] = '';
             } else {
                 $readAuth = data_entry_helper::get_read_auth($args['website_id'], $args['password']);
                 $locationRecord = data_entry_helper::get_population_data(array('table' => 'location', 'extraParams' => $readAuth + array('name' => $data[$postCounter])));
                 //If we can't find an id for the location name in the database, then warn the user.
                 if (!empty($locationRecord[0]['id'])) {
                     //Still need to do the same check for location_id to see if it has changed from the previous row.
                     if (!empty($values['sample:location_id']) && $values['sample:location_id'] != $locationRecord[0]['id']) {
                         $newSampleRequired = true;
                     }
                     $values['sample:location_id'] = $locationRecord[0]['id'];
                 } else {
                     drupal_set_message('<B>Warning: The location ' . $data[$postCounter] . ' is not currently present in the database. .</B>');
                     if ($args['keep_going_after_error']) {
                         drupal_set_message('<i>I will attempt to continue with the import but errors may occur or there might be inconsistent data entered into the database.</i>');
                     } else {
                         drupal_set_message('<i>The import has been stopped.</i>');
                     }
                     return array($occurrenceNumber, true);
                 }
             }
         }
         //Move onto the next column.
         $postCounter++;
     }
     if ($newSampleRequired === true) {
         $submission = self::get_submission($values, $args, true);
         $authentication = import_helper::get_read_write_auth($args['website_id'], $args['password']);
         $response = data_entry_helper::forward_post_to('save', $submission, $authentication['write_tokens']);
         //Once we know we need a new sample, we start building the values array again.
         $occurrenceNumber = 0;
         $values = array();
         self::get_initial_values_array_values($values, $args);
     }
     return array($occurrenceNumber, false);
 }