Пример #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.
  * @return HTML string
  */
 public static function get_form($args, $node, $response)
 {
     iform_load_helpers(array('report_helper', 'map_helper'));
     $auth = report_helper::get_read_auth($args['website_id'], $args['password']);
     $reportOptions = iform_report_get_report_options($args, $auth);
     $r = '<div class="ui-helper-clearfix">';
     $reportOptions['geoserverLayer'] = $args['geoserver_layer'];
     $reportOptions['geoserverLayerStyle'] = $args['geoserver_layer_style'];
     $reportOptions['cqlTemplate'] = $args['cql_template'];
     $reportOptions['clickable'] = $args['click_on_map_mode'] != 'none';
     $reportOptions['clickableLayersOutputDiv'] = $args['click_on_map_div'];
     if (!empty($args['click_on_map_columns'])) {
         $reportOptions['clickableLayersOutputColumns'] = helper_base::explode_lines_key_value_pairs($args['click_on_map_columns']);
     }
     if ($args['click_on_map_mode'] != 'none') {
         $reportOptions['clickableLayersOutputMode'] = $args['click_on_map_mode'];
     }
     // Use the proxy module if enabled, to get round limitations in URL length for
     // filtered WMS requests.
     if (defined('DRUPAL_BOOTSTRAP_CONFIGURATION') && module_exists('iform_proxy')) {
         global $base_url;
         $reportOptions['proxy'] = $base_url . '/?q=' . variable_get('iform_proxy_path', 'proxy') . '&url=';
     }
     $r .= '<br/>' . report_helper::report_map($reportOptions);
     $options = iform_map_get_map_options($args, $readAuth);
     $olOptions = iform_map_get_ol_options($args);
     // This is used for drawing, so need an editlayer, but not used for input
     $options['editLayer'] = true;
     $options['editLayerInSwitcher'] = true;
     $options['clickForSpatialRef'] = false;
     if ($args['layer_picker'] != 'none') {
         $picker = array('id' => 'map-layer-picker', 'includeIcons' => false, 'includeSwitchers' => true, 'includeHiddenLayers' => true);
         if ($args['layer_picker'] == 'before') {
             $r .= map_helper::layer_list($picker);
         }
         // as we have a layer picker, we can drop the layerSwitcher from the OL map.
         if (array_search('layerSwitcher', $options['standardControls']) !== false) {
             unset($options['standardControls'][array_search('layerSwitcher', $options['standardControls'])]);
         }
     }
     if ($args['legend'] != 'none') {
         $legend = array('id' => 'map-legend', 'includeIcons' => true, 'includeSwitchers' => false, 'includeHiddenLayers' => false);
         if ($args['legend'] == 'before') {
             $r .= map_helper::layer_list($legend);
         }
     }
     if (isset($args['map_toolbar_pos'])) {
         $options['toolbarDiv'] = $args['map_toolbar_pos'];
     }
     $r .= map_helper::map_panel($options, $olOptions);
     if ($args['layer_picker'] == 'after') {
         $r .= map_helper::layer_list($picker);
     }
     if ($args['legend'] == 'after') {
         $r .= map_helper::layer_list($legend);
     }
     $r .= '</div>';
     return $r;
 }
 /**
  * Return the generated output for the occurrences grid tab.
  * @param array $args List of parameter values passed through to the form depending on how the form has been configured.
  *                    This array always contains a value for language.
  * @param integer $nid The Drupal node object's ID.
  * @param object $auth The full read-write authorisation.
  * @return HTML.
  */
 private static function get_occurrences_tab($args, $nid, $auth, $packageAttr)
 {
     global $user;
     global $indicia_templates;
     // initially not ajax due to uncertainty over mandatory status of sample attributes.
     $r = '';
     // In the situation where there are multiple species packages to be selected from, we can't
     // display the species grid until that decision is made.
     if (self::$multiPackageOptions) {
         return '<div id="occurrences">' . '<p>' . lang::get('There are multiple possible species packages: you must select the species package (on the first tab) and then save the record before you can enter data on the species tab.') . '</p>' . data_entry_helper::hidden_text(array('fieldname' => 'force_page_reload')) . '</div>';
     }
     // Because the initial save sets the species package
     // remove the ctrlWrap as it complicates the grid & JavaScript unnecessarily
     $oldCtrlWrapTemplate = $indicia_templates['controlWrap'];
     $indicia_templates['controlWrap'] = '{control}';
     data_entry_helper::add_resource('jquery_form');
     $defaults = helper_base::explode_lines_key_value_pairs($args['defaults']);
     $record_status = isset($defaults['occurrence:record_status']) ? $defaults['occurrence:record_status'] : 'C';
     // find any attributes that apply to quadrat samples.
     // We need attribute list in both ordered and indexed formats
     $attributes = data_entry_helper::getAttributes(array('valuetable' => 'sample_attribute_value', 'attrtable' => 'sample_attribute', 'key' => 'sample_id', 'fieldprefix' => 'smpAttr', 'extraParams' => $auth['read'], 'survey_id' => $args['survey_id'], 'sample_method_id' => $args['quadrat_level_sample_method_id']));
     $attributesIdx = data_entry_helper::getAttributes(array('valuetable' => 'sample_attribute_value', 'attrtable' => 'sample_attribute', 'key' => 'sample_id', 'fieldprefix' => 'smpAttr', 'extraParams' => $auth['read'], 'survey_id' => $args['survey_id'], 'sample_method_id' => $args['quadrat_level_sample_method_id'], 'multiValue' => false));
     $occ_attributes = data_entry_helper::getAttributes(array('valuetable' => 'occurrence_attribute_value', 'attrtable' => 'occurrence_attribute', 'key' => 'occurrence_id', 'fieldprefix' => 'occAttr', 'extraParams' => $auth['read'], 'survey_id' => $args['survey_id'], 'multiValue' => false));
     if (self::$sampleId == null) {
         $subSamples = array();
         $o = array();
     } else {
         $subSamples = data_entry_helper::get_population_data(array('report' => 'library/samples/samples_list_for_parent_sample', 'extraParams' => $auth['read'] + array('sample_id' => self::$sampleId, 'date_from' => '', 'date_to' => '', 'sample_method_id' => $args['quadrat_level_sample_method_id'], 'smpattrs' => implode(',', array_keys($attributesIdx))), 'nocache' => true));
         $o = data_entry_helper::get_population_data(array('report' => 'reports_for_prebuilt_forms/UKBMS/ukbms_occurrences_list_for_parent_sample', 'extraParams' => $auth['read'] + array('sample_id' => self::$sampleId, 'survey_id' => $args['survey_id'], 'date_from' => '', 'date_to' => '', 'taxon_group_id' => '', 'smpattrs' => '', 'occattrs' => implode(',', array_keys($occ_attributes)), 'orderby' => 'occurrence_id'), 'nocache' => true));
     }
     // build an array of occurrence and attribute data keyed for easy lookup
     $occurrences = array();
     if (self::$readOnly) {
         $taxalist = array();
     } else {
         $taxalist = self::_get_species($user->uid, $args, $packageAttr['default']);
     }
     foreach ($o as $occurrence) {
         $occurrences[$occurrence['sample_id'] . ':' . $occurrence['taxa_taxon_list_id']] = array('ttl_id' => $occurrence['taxa_taxon_list_id'], 'o_id' => $occurrence['occurrence_id'], 'processed' => false);
         if (!in_array($occurrence['taxa_taxon_list_id'], $taxalist)) {
             // ensure taxa list includes all old data. Required if going into view old data when list has changed.
             $taxalist[] = $occurrence['taxa_taxon_list_id'];
         }
         foreach ($occ_attributes as $attr => $defn) {
             $occurrences[$occurrence['sample_id'] . ':' . $occurrence['taxa_taxon_list_id']]['value_' . $attr] = $occurrence['attr_occurrence_' . $attr];
             $occurrences[$occurrence['sample_id'] . ':' . $occurrence['taxa_taxon_list_id']]['a_id_' . $attr] = $occurrence['attr_id_occurrence_' . $attr];
         }
     }
     $limit1 = $args['sample_attribute_id_1_limit'];
     if (!in_array($args['sample_attribute_id_1'], array_keys($attributesIdx))) {
         return "INTERNAL CONFIGURATION ERROR: Supplied primary sample loop attribute (ID " . $args['sample_attribute_id_1'] . ") is not in the list of sample attributes configured for this survey (Survey ID " . $args['survey_id'] . ", attribute IDs " . implode(',', array_keys($attributes)) . "). Ensure that the Indicia Cache is cleared.<br/>";
     }
     $limit2 = $args['sample_attribute_id_2_limit'];
     if (isset($args['sample_attribute_id_2']) && $args['sample_attribute_id_2'] != "") {
         if (!in_array($args['sample_attribute_id_2'], array_keys($attributesIdx))) {
             return "INTERNAL CONFIGURATION ERROR: Supplied optional secondary sample loop attribute (ID " . $args['sample_attribute_id_2'] . ") is not in the list of sample attributes configured for this survey (Survey ID " . $args['survey_id'] . ", attribute IDs " . implode(',', array_keys($attributes)) . "). Ensure that the Indicia Cache is cleared.<br/>";
         }
     } else {
         $limit2 = 1;
     }
     foreach ($subSamples as $subSample) {
         $attrVal = self::_get_sample_attr_value($subSample, $args['sample_attribute_id_1_limit']);
         if ($attrVal > $limit1) {
             $limit1 = $attrVal;
         }
         if (isset($args['sample_attribute_id_2']) && $args['sample_attribute_id_2'] != "") {
             $attrVal = self::_get_sample_attr_value($subSample, $args['sample_attribute_id_2_limit']);
             if ($attrVal > $limit2) {
                 $limit2 = $attrVal;
             }
         }
     }
     $t = data_entry_helper::get_population_data(array('table' => 'taxa_taxon_list', 'extraParams' => $auth['read'] + array('view' => 'detail', 'id' => $taxalist)));
     $r .= '<div id="occurrences">' . '<input type="hidden" id="occurrence:record_status" name="occurrence:record_status" value="' . $record_status . '" />' . "\n" . '<p>' . lang::get('Using Species Package : ') . species_packages_get_name($packageAttr['default']) . '</p>' . '<table id="transect-input1" class="ui-widget species-grid"><thead class="table-header">';
     // Build header
     $r .= '<tr>' . '<th class="ui-widget-header"></th>' . '<th class="ui-widget-header">' . $attributesIdx[$args['sample_attribute_id_1']]['caption'] . '</th>' . (!isset($args['sample_attribute_id_2']) || $args['sample_attribute_id_2'] == "" ? '' : '<th class="ui-widget-header">' . $attributesIdx[$args['sample_attribute_id_2']]['caption'] . '</th>');
     foreach ($attributes as $smpAttr) {
         if ($smpAttr['attributeId'] != $args['sample_attribute_id_1'] && (!isset($args['sample_attribute_id_2']) || $args['sample_attribute_id_2'] == "" || $smpAttr['attributeId'] != $args['sample_attribute_id_2'])) {
             $r .= '<th class="ui-widget-header">' . $smpAttr['caption'] . '</th>';
         }
     }
     // need to maintain order as defined in $taxalist
     $extraDetails = array();
     if (isset($args['taxon_headings_extras']) && $args['taxon_headings_extras'] != '') {
         $extras = explode(',', $args['taxon_headings_extras']);
         foreach ($extras as $extra) {
             $parts = explode(':', $extra);
             $extraDetails[$parts[0]] = $parts[1];
         }
     }
     foreach ($taxalist as $ttlid) {
         foreach ($t as $taxon) {
             if ($ttlid == $taxon['id']) {
                 $attr = self::_get_species_attribute($user->uid, $args, $packageAttr['default'], $ttlid);
                 $r .= '<th class="ui-widget-header"' . ($taxon['common'] != '' && $taxon['taxon'] != $taxon['common'] ? ' title="' . $taxon['common'] . '"' : '') . '>' . $taxon['taxon'] . (isset($extraDetails[$attr]) ? ' (' . $extraDetails[$attr] . ')' : '') . (isset($extraDetails[$taxon['common']]) ? ' (' . $extraDetails[$taxon['common']] . ')' : '') . '</th>';
             }
         }
     }
     $r .= '</tr></thead><tbody class="ui-widget-content">';
     // fieldname naming conventions
     // Each sample attribute has a fieldname "Grid:Row<rowNumber>:[subsampleID]:smpAttr:<attributeID>:[<attributeValueID>]"
     // Each occurrence attribute has a fieldname "Grid:Row<rowNumber>:[subsampleID]:occ:<ttlid>:[occurrenceID]:occAttr:<attributeID>[:<attributeValueID>]"
     // If any smpAttr is filled in, or any occAttr is filled in, then the other occAttr on that line are set to zero
     // If any occAttr is set to zero, the zero abundance flag is set.
     $altRow = false;
     $defAttrOptions = array('extraParams' => $auth['read']);
     $roAttrOptions = array('extraParams' => $auth['read'], 'readonly' => 'readonly="readonly"', 'class' => 'ignore', 'ctrl' => 'hidden');
     $rowNumber = 1;
     unset($attributesIdx[$args['sample_attribute_id_1']]['caption']);
     if (isset($args['sample_attribute_id_2']) && $args['sample_attribute_id_2'] != "") {
         unset($attributesIdx[$args['sample_attribute_id_2']]['caption']);
     }
     foreach ($attributes as &$attr) {
         unset($attr['caption']);
     }
     foreach ($occ_attributes as &$attr) {
         unset($attr['caption']);
     }
     for ($loop1 = 1; $loop1 <= $limit1; $loop1++) {
         for ($loop2 = 1; $loop2 <= $limit2; $loop2++) {
             $existingSample = self::_get_row_sample($subSamples, $args['sample_attribute_id_1'], $loop1, isset($args['sample_attribute_id_2']) && $args['sample_attribute_id_2'] != "" ? $args['sample_attribute_id_2'] : false, $loop2);
             $rowPrefix = "Grid:Row" . $rowNumber . ":" . ($existingSample ? $existingSample['sample_id'] : '') . ":";
             $r .= '<tr class="datarow' . ($loop2 == 1 ? ' level1' : ' level2') . '">';
             $r .= '<td class="ui-state-default clear-row" style="width: 1%" title="' . lang::get('Clear all contents of this row') . '">X</td>';
             $roAttrOptions['id'] = $roAttrOptions['fieldname'] = self::_get_sample_attr_name($rowPrefix, $existingSample, $args['sample_attribute_id_1']);
             $roAttrOptions['default'] = $loop1;
             $r .= '<td>' . data_entry_helper::outputAttribute($attributesIdx[$args['sample_attribute_id_1']], $roAttrOptions) . '</td>';
             if (isset($args['sample_attribute_id_2']) && $args['sample_attribute_id_2'] != "") {
                 $roAttrOptions['id'] = $roAttrOptions['fieldname'] = self::_get_sample_attr_name($rowPrefix, $existingSample, $args['sample_attribute_id_2']);
                 $roAttrOptions['default'] = $loop2;
                 $r .= '<td>' . data_entry_helper::outputAttribute($attributesIdx[$args['sample_attribute_id_2']], $roAttrOptions) . '</td>';
             }
             foreach ($attributes as $smpAttr) {
                 if ($smpAttr['attributeId'] != $args['sample_attribute_id_1'] && (!isset($args['sample_attribute_id_2']) || $args['sample_attribute_id_2'] == "" || $smpAttr['attributeId'] != $args['sample_attribute_id_2'])) {
                     unset($defAttrOptions['class']);
                     $defAttrOptions['id'] = $defAttrOptions['fieldname'] = self::_get_sample_attr_name($rowPrefix, $existingSample, $smpAttr['attributeId']);
                     $defAttrOptions['default'] = self::_get_sample_attr_value($existingSample, $smpAttr['attributeId']);
                     if ($loop2 == 1 || !in_array($smpAttr['attributeId'], explode(',', $args['level_1_attributes']))) {
                         if (in_array($smpAttr['attributeId'], explode(',', $args['level_1_attributes']))) {
                             $defAttrOptions['class'] = 'lvl1Master lvl1-' . $loop1 . '-' . $smpAttr['attributeId'];
                         }
                         $r .= '<td>' . data_entry_helper::outputAttribute($smpAttr, $defAttrOptions) . '</td>';
                     } else {
                         $r .= '<td><input class="ignore copydown lvl1-' . $loop1 . '-' . $smpAttr['attributeId'] . '" readonly="readonly" type="hidden" name="' . $defAttrOptions['fieldname'] . '" value="' . $defAttrOptions['default'] . '" /></td>';
                     }
                 }
             }
             // need to maintain order as defined in $taxalist
             $first = true;
             foreach ($taxalist as $ttlid) {
                 foreach ($t as $taxon) {
                     if ($ttlid == $taxon['id']) {
                         $defOccAttrOptions = array('extraParams' => $auth['read']);
                         $occAttrID = self::_get_species_attribute($user->uid, $args, $packageAttr['default'], $ttlid);
                         if ($occAttrID === false) {
                             foreach ($occ_attributes as $attrID => $occ_attribute) {
                                 if (isset($occurrences[$existingSample['sample_id'] . ':' . $ttlid]) && isset($occurrences[$existingSample['sample_id'] . ':' . $ttlid]['value_' . $attrID]) && $occurrences[$existingSample['sample_id'] . ':' . $ttlid]['value_' . $attrID] != '') {
                                     $occAttrID = $attrID;
                                     break;
                                 }
                             }
                         }
                         if ($occAttrID === false) {
                             // old data - ttl no longer in list, no detectable attr held: enter dummy
                             $r .= '<td title="Taxon no longer in Species Package. No old data found."></td>';
                         } else {
                             $defOccAttrOptions['id'] = $defOccAttrOptions['fieldname'] = self::_get_occurrence_attr_name($rowPrefix, $existingSample, $ttlid, $occAttrID, $occurrences);
                             $defOccAttrOptions['default'] = self::_get_occurrence_attr_value($existingSample, $ttlid, $occAttrID, $occurrences);
                             $defOccAttrOptions['class'] = self::_get_occurrence_attr_class($first, $existingSample, $ttlid, $occurrences);
                             $r .= '<td>' . data_entry_helper::outputAttribute($occ_attributes[$occAttrID], $defOccAttrOptions) . '</td>';
                         }
                     }
                 }
             }
             $r .= '</tr>';
             $altRow = !$altRow;
             $rowNumber++;
         }
     }
     $r .= '</table>' . (self::$readOnly ? '' : '<br/><input type="submit" value="' . lang::get('Save') . '" title="' . lang::get('Saves any data entered across all the tabs.') . '" />') . '</div>';
     data_entry_helper::add_resource('jquery_ui');
     data_entry_helper::$javascript .= "indiciaData.fill_zeroes=" . (isset($args['fill_zeroes']) && $args['fill_zeroes'] ? 'true' : 'false') . ";\n";
     return $r;
 }
 /**
  * Convert the unstructured textarea of default values into a structured array.
  */
 protected static function parse_defaults(&$args)
 {
     $result = array();
     if (isset($args['defaults'])) {
         $result = helper_base::explode_lines_key_value_pairs($args['defaults']);
     }
     $args['defaults'] = $result;
 }
 /**
  * Overrides the postSubmit function to add in additional metadata and data values. 
  */
 protected function postSubmit($isInsert)
 {
     require_once DOCROOT . 'client_helpers/helper_base.php';
     $result = true;
     if (isset($this->submission['metaFields'])) {
         $currentRule = data_cleaner::get_rule($this->test_type);
         if (isset($this->submission['metaFields']['metadata']['value'])) {
             $metadata = helper_base::explode_lines_key_value_pairs($this->submission['metaFields']['metadata']['value']);
             $this->save_verification_rule_metadata($currentRule, $metadata);
             $data = data_cleaner::parse_test_file($this->submission['metaFields']['data']['value']);
             $this->save_verification_rule_data($currentRule, $data);
             $this->postProcessRule($currentRule);
         }
     }
     return true;
 }
 public static function get_occurrences_form($args, $node, $response)
 {
     global $user;
     if (!module_exists('iform_ajaxproxy')) {
         return 'This form must be used in Drupal with the Indicia AJAX Proxy module enabled.';
     }
     drupal_add_js('misc/tableheader.js');
     // for sticky heading
     data_entry_helper::add_resource('jquery_form');
     $auth = data_entry_helper::get_read_write_auth($args['website_id'], $args['password']);
     // did the parent sample previously exist? Default is no.
     $existing = false;
     $url = explode('?', $args['my_walks_page'], 2);
     $params = NULL;
     $fragment = NULL;
     // fragment is always at the end.
     if (count($url) > 1) {
         $params = explode('#', $url[1], 2);
         if (count($params) > 1) {
             $fragment = $params[1];
         }
         $params = $params[0];
     } else {
         $url = explode('#', $url[0], 2);
         if (count($url) > 1) {
             $fragment = $url[1];
         }
     }
     $args['my_walks_page'] = url($url[0], array('query' => $params, 'fragment' => $fragment, 'absolute' => TRUE));
     if (isset($_POST['sample:id'])) {
         // have just posted an edit to the existing parent sample, so can use it to get the parent location id.
         $parentSampleId = $_POST['sample:id'];
         $existing = true;
         data_entry_helper::load_existing_record($auth['read'], 'sample', $parentSampleId);
     } else {
         if (isset($response['outer_id'])) {
             // have just posted a new parent sample, so can use it to get the parent location id.
             $parentSampleId = $response['outer_id'];
         } else {
             $parentSampleId = $_GET['sample_id'];
             $existing = true;
         }
     }
     $sample = data_entry_helper::get_population_data(array('table' => 'sample', 'extraParams' => $auth['read'] + array('view' => 'detail', 'id' => $parentSampleId, 'deleted' => 'f')));
     $sample = $sample[0];
     $parentLocId = $sample['location_id'];
     $date = $sample['date_start'];
     if (!function_exists('module_exists') || !module_exists('easy_login')) {
         // work out the CMS User sample ID.
         $sampleMethods = helper_base::get_termlist_terms($auth, 'indicia:sample_methods', array('Transect'));
         $attributes = data_entry_helper::getAttributes(array('valuetable' => 'sample_attribute_value', 'attrtable' => 'sample_attribute', 'key' => 'sample_id', 'fieldprefix' => 'smpAttr', 'extraParams' => $auth['read'], 'survey_id' => $args['survey_id'], 'sample_method_id' => $sampleMethods[0]['id']));
         if (false == ($cmsUserAttr = extract_cms_user_attr($attributes))) {
             return 'Easy Login not active: This form is designed to be used with the CMS User ID attribute setup for samples in the survey.';
         }
     }
     // find any attributes that apply to transect section samples.
     $sampleMethods = helper_base::get_termlist_terms($auth, 'indicia:sample_methods', array('Transect Section'));
     $attributes = data_entry_helper::getAttributes(array('valuetable' => 'sample_attribute_value', 'attrtable' => 'sample_attribute', 'key' => 'sample_id', 'fieldprefix' => 'smpAttr', 'extraParams' => $auth['read'], 'survey_id' => $args['survey_id'], 'sample_method_id' => $sampleMethods[0]['id'], 'multiValue' => false));
     //  the parent sample and sub-samples have already been created: can't cache in case a new section added.
     // need to specify sample_method as this must be different to those used in species map.
     // Only returns section based subsamples, not map.
     $subSamples = data_entry_helper::get_population_data(array('report' => 'library/samples/samples_list_for_parent_sample', 'extraParams' => $auth['read'] + array('sample_id' => $parentSampleId, 'date_from' => '', 'date_to' => '', 'sample_method_id' => $sampleMethods[0]['id'], 'smpattrs' => implode(',', array_keys($attributes))), 'nocache' => true));
     // transcribe the response array into a couple of forms that are useful elsewhere - one for outputting JSON so the JS knows about
     // the samples, and another for lookup of sample data by code later.
     $subSampleJson = array();
     $subSamplesByCode = array();
     foreach ($subSamples as $subSample) {
         $subSampleJson[] = '"' . $subSample['code'] . '": ' . $subSample['sample_id'];
         $subSamplesByCode[$subSample['code']] = $subSample;
     }
     data_entry_helper::$javascript .= "indiciaData.samples = { " . implode(', ', $subSampleJson) . "};\n";
     if ($existing) {
         // Only need to load the occurrences for a pre-existing sample
         $attrs = array($args['occurrence_attribute_id']);
         if (isset($args['occurrence_attribute_id_2']) && $args['occurrence_attribute_id_2'] != "") {
             $attrs[] = $args['occurrence_attribute_id_2'];
         }
         if (isset($args['occurrence_attribute_id_3']) && $args['occurrence_attribute_id_3'] != "") {
             $attrs[] = $args['occurrence_attribute_id_3'];
         }
         if (isset($args['occurrence_attribute_id_4']) && $args['occurrence_attribute_id_4'] != "") {
             $attrs[] = $args['occurrence_attribute_id_4'];
         }
         $o = data_entry_helper::get_population_data(array('report' => 'reports_for_prebuilt_forms/UKBMS/ukbms_occurrences_list_for_parent_sample', 'extraParams' => $auth['read'] + array('view' => 'detail', 'sample_id' => $parentSampleId, 'survey_id' => $args['survey_id'], 'date_from' => '', 'date_to' => '', 'taxon_group_id' => '', 'smpattrs' => '', 'occattrs' => implode(',', $attrs)), 'nocache' => true));
         // build an array keyed for easy lookup
         $occurrences = array();
         foreach ($o as $occurrence) {
             $occurrences[$occurrence['sample_id'] . ':' . $occurrence['taxon_meaning_id']] = array('ttl_id' => $occurrence['taxa_taxon_list_id'], 'taxon_meaning_id' => $occurrence['taxon_meaning_id'], 'o_id' => $occurrence['occurrence_id'], 'processed' => false);
             foreach ($attrs as $attr) {
                 $occurrences[$occurrence['sample_id'] . ':' . $occurrence['taxon_meaning_id']]['value_' . $attr] = $occurrence['attr_occurrence_' . $attr];
                 $occurrences[$occurrence['sample_id'] . ':' . $occurrence['taxon_meaning_id']]['a_id_' . $attr] = $occurrence['attr_id_occurrence_' . $attr];
             }
         }
         // store it in data for JS to read when populating the grid
         data_entry_helper::$javascript .= "indiciaData.existingOccurrences = " . json_encode($occurrences) . ";\n";
     } else {
         data_entry_helper::$javascript .= "indiciaData.existingOccurrences = {};\n";
     }
     $occ_attributes = data_entry_helper::getAttributes(array('valuetable' => 'occurrence_attribute_value', 'attrtable' => 'occurrence_attribute', 'key' => 'occurrence_id', 'fieldprefix' => 'occAttr', 'extraParams' => $auth['read'], 'survey_id' => $args['survey_id'], 'multiValue' => false));
     data_entry_helper::$javascript .= "indiciaData.occurrence_attribute = [];\n";
     data_entry_helper::$javascript .= "indiciaData.occurrence_attribute_ctrl = [];\n";
     $defAttrOptions = array('extraParams' => $auth['read'] + array('orderby' => 'id'), 'suffixTemplate' => 'nosuffix');
     foreach (array($args['occurrence_attribute_id'], isset($args['occurrence_attribute_id_2']) && $args['occurrence_attribute_id_2'] != "" ? $args['occurrence_attribute_id_2'] : $args['occurrence_attribute_id'], isset($args['occurrence_attribute_id_3']) && $args['occurrence_attribute_id_3'] != "" ? $args['occurrence_attribute_id_3'] : $args['occurrence_attribute_id'], isset($args['occurrence_attribute_id_4']) && $args['occurrence_attribute_id_4'] != "" ? $args['occurrence_attribute_id_4'] : $args['occurrence_attribute_id']) as $idx => $attr) {
         unset($occ_attributes[$attr]['caption']);
         $ctrl = data_entry_helper::outputAttribute($occ_attributes[$attr], $defAttrOptions);
         data_entry_helper::$javascript .= "indiciaData.occurrence_attribute[" . ($idx + 1) . "] = {$attr};\n";
         data_entry_helper::$javascript .= "indiciaData.occurrence_attribute_ctrl[" . ($idx + 1) . "] = jQuery('" . str_replace("\n", "", $ctrl) . "');\n";
     }
     $sections = data_entry_helper::get_population_data(array('table' => 'location', 'extraParams' => $auth['read'] + array('view' => 'detail', 'parent_id' => $parentLocId, 'deleted' => 'f'), 'nocache' => true));
     usort($sections, "ukbms_stis_sectionSort");
     $location = data_entry_helper::get_population_data(array('table' => 'location', 'extraParams' => $auth['read'] + array('view' => 'detail', 'id' => $parentLocId)));
     $r = "<h2>" . $location[0]['name'] . " on " . $date . "</h2><div id=\"tabs\">\n";
     $tabs = array('#grid1' => t($args['species_tab_1']));
     // tab 1 is required.
     if (isset($args['second_taxon_list_id']) && $args['second_taxon_list_id'] != '') {
         $tabs['#grid2'] = t(isset($args['species_tab_2']) && $args['species_tab_2'] != '' ? $args['species_tab_2'] : 'Species Tab 2');
     }
     if (isset($args['third_taxon_list_id']) && $args['third_taxon_list_id'] != '') {
         $tabs['#grid3'] = t(isset($args['species_tab_3']) && $args['species_tab_3'] != '' ? $args['species_tab_3'] : 'Species Tab 3');
     }
     if (isset($args['fourth_taxon_list_id']) && $args['fourth_taxon_list_id'] != '') {
         $tabs['#grid4'] = t(isset($args['species_tab_4']) && $args['species_tab_4'] != '' ? $args['species_tab_4'] : 'Species Tab 4');
     }
     if (isset($args['map_taxon_list_id']) && $args['map_taxon_list_id'] != '') {
         $tabs['#gridmap'] = t(isset($args['species_map_tab']) && $args['species_map_tab'] != '' ? $args['species_map_tab'] : 'Map Based Tab');
     }
     $tabs['#notes'] = lang::get('Notes');
     $r .= data_entry_helper::tab_header(array('tabs' => $tabs));
     data_entry_helper::enable_tabs(array('divId' => 'tabs', 'style' => 'Tabs'));
     $commonSelected = isset($args['start_with_common_species']) && $args['start_with_common_species'] ? 'selected="selected"' : '';
     // will assume that first table is based on abundance count, so do totals
     $r .= '<div id="grid1">' . '<label for="listSelect">' . lang::get('Use species list') . ' :</label><select id="listSelect"><option value="full">' . lang::get('All species') . '</option><option value="common"' . $commonSelected . '>' . lang::get('Common species') . '</option><option value="here">' . lang::get('Species known at this site') . '</option><option value="mine">' . lang::get('Species I have recorded') . '</option><option value="filled">' . lang::get('Species with data') . '</option></select>' . '<span id="listSelectMsg"></span>';
     $r .= '<table id="transect-input1" class="ui-widget species-grid"><thead class="table-header">';
     $r .= '<tr><th class="ui-widget-header">' . lang::get('Sections') . '</th>';
     foreach ($sections as $idx => $section) {
         $r .= '<th class="ui-widget-header col-' . ($idx + 1) . '">' . $section['code'] . '</th>';
     }
     $r .= '<th class="ui-widget-header">' . lang::get('Total') . '</th>';
     $r .= '</tr></thead>';
     $r .= '<tbody class="ui-widget-content">';
     // output rows at the top for any transect section level sample attributes
     $rowClass = '';
     foreach ($attributes as $attr) {
         $r .= '<tr ' . $rowClass . ' id="smp-' . $attr['attributeId'] . '"><td>' . $attr['caption'] . '</td>';
         $rowClass = $rowClass == '' ? 'class="alt-row"' : '';
         unset($attr['caption']);
         foreach ($sections as $idx => $section) {
             // output a cell with the attribute - tag it with a class & id to make it easy to find from JS.
             $attrOpts = array('class' => 'smp-input smpAttr-' . $section['code'], 'id' => $attr['fieldname'] . ':' . $section['code'], 'extraParams' => $auth['read']);
             // if there is an existing value, set it and also ensure the attribute name reflects the attribute value id.
             if (isset($subSamplesByCode[$section['code']])) {
                 // but have to take into account possibility that this field has been blanked out, so deleting the attribute.
                 if (isset($subSamplesByCode[$section['code']]['attr_id_sample_' . $attr['attributeId']]) && $subSamplesByCode[$section['code']]['attr_id_sample_' . $attr['attributeId']] != '') {
                     $attrOpts['fieldname'] = $attr['fieldname'] . ':' . $subSamplesByCode[$section['code']]['attr_id_sample_' . $attr['attributeId']];
                     $attr['default'] = $subSamplesByCode[$section['code']]['attr_sample_' . $attr['attributeId']];
                 } else {
                     $attr['default'] = isset($_POST[$attr['fieldname']]) ? $_POST[$attr['fieldname']] : '';
                 }
             } else {
                 $attr['default'] = isset($_POST[$attr['fieldname']]) ? $_POST[$attr['fieldname']] : '';
             }
             $r .= '<td class="col-' . ($idx + 1) . ' ' . ($idx % 5 == 0 ? 'first' : '') . '">' . data_entry_helper::outputAttribute($attr, $attrOpts) . '</td>';
         }
         $r .= '<td class="ui-state-disabled first"></td>';
         $r .= '</tr>';
     }
     $r .= '</tbody>';
     $r .= '<tbody class="ui-widget-content occs-body"></tbody>';
     $r .= '<tfoot><tr><td>Total</td>';
     foreach ($sections as $idx => $section) {
         $r .= '<td class="col-' . ($idx + 1) . ' ' . ($idx % 5 == 0 ? 'first' : '') . ' col-total"></td>';
     }
     $r .= '<td class="ui-state-disabled first"></td></tr></tfoot>';
     $r .= '</table>' . '<span id="taxonLookupControlContainer"><label for="taxonLookupControl" class="auto-width">' . lang::get('Add species to list') . ':</label> <input id="taxonLookupControl" name="taxonLookupControl" ></span>';
     $r .= '<br /><a href="' . $args['my_walks_page'] . '" class="button">' . lang::get('Finish') . '</a></div>';
     $extraParams = array_merge($auth['read'], array('taxon_list_id' => $args['taxon_list_id'], 'preferred' => 't', 'allow_data_entry' => 't', 'view' => 'cache', 'orderby' => 'taxonomic_sort_order'));
     if (!empty($args['main_taxon_filter_field']) && !empty($args['main_taxon_filter'])) {
         $extraParams[$args['main_taxon_filter_field']] = helper_base::explode_lines($args['main_taxon_filter']);
     }
     $taxa = data_entry_helper::get_population_data(array('table' => 'taxa_taxon_list', 'extraParams' => $extraParams));
     data_entry_helper::$javascript .= "indiciaData.speciesList1List = [";
     $first = true;
     foreach ($taxa as $taxon) {
         data_entry_helper::$javascript .= ($first ? "\n" : ",\n") . "{'id':" . $taxon['id'] . ",'taxon_meaning_id':" . $taxon['taxon_meaning_id'] . ",'preferred_language_iso':'" . $taxon["preferred_language_iso"] . "','default_common_name':'" . str_replace("'", "\\'", $taxon["default_common_name"]) . "'}";
         $first = false;
     }
     data_entry_helper::$javascript .= "];\n";
     if (!empty($args['common_taxon_list_id'])) {
         $extraParams = array_merge($auth['read'], array('taxon_list_id' => $args['common_taxon_list_id'], 'preferred' => 't', 'allow_data_entry' => 't', 'view' => 'cache', 'orderby' => 'taxonomic_sort_order'));
         if (!empty($args['common_taxon_filter_field']) && !empty($args['common_taxon_filter'])) {
             $extraParams[$args['common_taxon_filter_field']] = helper_base::explode_lines($args['common_taxon_filter']);
         }
         $taxa = data_entry_helper::get_population_data(array('table' => 'taxa_taxon_list', 'extraParams' => $extraParams));
         data_entry_helper::$javascript .= "indiciaData.speciesList1SubsetList = [";
         $first = true;
         foreach ($taxa as $taxon) {
             data_entry_helper::$javascript .= ($first ? "\n" : ",\n") . "{'id':" . $taxon['id'] . ",'taxon_meaning_id':" . $taxon['taxon_meaning_id'] . ",'preferred_language_iso':'" . $taxon["preferred_language_iso"] . "','default_common_name':'" . str_replace("'", "\\'", $taxon["default_common_name"]) . "'}";
             $first = false;
         }
         data_entry_helper::$javascript .= "];\n";
         $swc = isset($args['start_with_common_species']) && $args['start_with_common_species'] ? 'true' : 'false';
         data_entry_helper::$javascript .= "indiciaData.startWithCommonSpecies={$swc};\n";
     }
     $allTaxonMeaningIdsAtTransect = data_entry_helper::get_population_data(array('report' => 'reports_for_prebuilt_forms/UKBMS/ukbms_taxon_meanings_at_transect', 'extraParams' => $auth['read'] + array('location_id' => $parentLocId, 'survey_id' => $args['survey_id']), 'nocache' => true));
     data_entry_helper::$javascript .= "indiciaData.allTaxonMeaningIdsAtTransect = [";
     $first = true;
     foreach ($allTaxonMeaningIdsAtTransect as $taxon) {
         data_entry_helper::$javascript .= ($first ? "" : ",") . $taxon['taxon_meaning_id'];
         $first = false;
     }
     data_entry_helper::$javascript .= "];\n";
     if (isset($args['second_taxon_list_id']) && $args['second_taxon_list_id'] != '') {
         $isNumber = $occ_attributes[isset($args['occurrence_attribute_id_2']) && $args['occurrence_attribute_id_2'] != "" ? $args['occurrence_attribute_id_2'] : $args['occurrence_attribute_id']]["data_type"] == 'I';
         $r .= '<div id="grid2"><p id="grid2-loading">' . lang::get('Loading - Please Wait') . '</p>' . (isset($args['supress_tab_msg']) && $args['supress_tab_msg'] ? '' : '<p>' . lang::get('LANG_Tab_Msg') . '</p>') . '<table id="transect-input2" class="ui-widget species-grid"><thead class="table-header">';
         $r .= '<tr><th class="ui-widget-header">' . lang::get('Sections') . '</th>';
         foreach ($sections as $idx => $section) {
             $r .= '<th class="ui-widget-header col-' . ($idx + 1) . '">' . $section['code'] . '</th>';
         }
         $r .= ($isNumber ? '<th class="ui-widget-header">' . lang::get('Total') . '</th>' : '') . '</tr></thead>';
         // No output rows at the top for any transect section level sample attributes in second grid.
         $r .= '<tbody class="ui-widget-content occs-body"></tbody>';
         if ($isNumber) {
             $r .= '<tfoot><tr><td>Total</td>';
             foreach ($sections as $idx => $section) {
                 $r .= '<td class="col-' . ($idx + 1) . ' ' . ($idx % 5 == 0 ? 'first' : '') . ' col-total"></td>';
             }
             $r .= '<td class="ui-state-disabled first"></td></tr></tfoot>';
         }
         $r .= '</table>';
         if (!isset($args['force_second']) || !$args['force_second']) {
             $r .= '<label for="taxonLookupControl2" class="auto-width">' . lang::get('Add species to list') . ':</label> <input id="taxonLookupControl2" name="taxonLookupControl2" >';
         }
         $r .= '<br /><a href="' . $args['my_walks_page'] . '" class="button">' . lang::get('Finish') . '</a></div>';
     }
     if (isset($args['third_taxon_list_id']) && $args['third_taxon_list_id'] != '') {
         $isNumber = $occ_attributes[isset($args['occurrence_attribute_id_3']) && $args['occurrence_attribute_id_3'] != "" ? $args['occurrence_attribute_id_3'] : $args['occurrence_attribute_id']]["data_type"] == 'I';
         $r .= '<div id="grid3"><p id="grid3-loading">' . lang::get('Loading - Please Wait') . '</p>' . (isset($args['supress_tab_msg']) && $args['supress_tab_msg'] ? '' : '<p>' . lang::get('LANG_Tab_Msg') . '</p>') . '<table id="transect-input3" class="ui-widget species-grid"><thead class="table-header">';
         $r .= '<tr><th class="ui-widget-header">' . lang::get('Sections') . '</th>';
         foreach ($sections as $idx => $section) {
             $r .= '<th class="ui-widget-header col-' . ($idx + 1) . '">' . $section['code'] . '</th>';
         }
         $r .= ($isNumber ? '<th class="ui-widget-header">' . lang::get('Total') . '</th>' : '') . '</tr></thead>';
         // No output rows at the top for any transect section level sample attributes in second grid.
         $r .= '<tbody class="ui-widget-content occs-body"></tbody>';
         if ($isNumber) {
             $r .= '<tfoot><tr><td>Total</td>';
             foreach ($sections as $idx => $section) {
                 $r .= '<td class="col-' . ($idx + 1) . ' ' . ($idx % 5 == 0 ? 'first' : '') . ' col-total"></td>';
             }
             $r .= '<td class="ui-state-disabled first"></td></tr></tfoot>';
         }
         $r .= '</table>';
         if (!isset($args['force_third']) || !$args['force_third']) {
             $r .= '<label for="taxonLookupControl3" class="auto-width">' . lang::get('Add species to list') . ':</label> <input id="taxonLookupControl3" name="taxonLookupControl3" >';
         }
         $r .= '<br /><a href="' . $args['my_walks_page'] . '" class="button">' . lang::get('Finish') . '</a></div>';
     }
     if (isset($args['fourth_taxon_list_id']) && $args['fourth_taxon_list_id'] != '') {
         $isNumber = $occ_attributes[isset($args['occurrence_attribute_id_4']) && $args['occurrence_attribute_id_4'] != "" ? $args['occurrence_attribute_id_4'] : $args['occurrence_attribute_id']]["data_type"] == 'I';
         $r .= '<div id="grid4"><p id="grid4-loading">' . lang::get('Loading - Please Wait') . '</p>' . (isset($args['supress_tab_msg']) && $args['supress_tab_msg'] ? '' : '<p>' . lang::get('LANG_Tab_Msg') . '</p>') . '<table id="transect-input4" class="ui-widget species-grid"><thead class="table-header">';
         $r .= '<tr><th class="ui-widget-header">' . lang::get('Sections') . '</th>';
         foreach ($sections as $idx => $section) {
             $r .= '<th class="ui-widget-header col-' . ($idx + 1) . '">' . $section['code'] . '</th>';
         }
         $r .= ($isNumber ? '<th class="ui-widget-header">' . lang::get('Total') . '</th>' : '') . '</tr></thead>';
         // No output rows at the top for any transect section level sample attributes in second grid.
         $r .= '<tbody class="ui-widget-content occs-body"></tbody>';
         if ($isNumber) {
             $r .= '<tfoot><tr><td>Total</td>';
             foreach ($sections as $idx => $section) {
                 $r .= '<td class="col-' . ($idx + 1) . ' ' . ($idx % 5 == 0 ? 'first' : '') . ' col-total"></td>';
             }
             $r .= '<td class="ui-state-disabled first"></td></tr></tfoot>';
         }
         $r .= '</table>';
         if (!isset($args['force_fourth']) || !$args['force_fourth']) {
             $r .= '<label for="taxonLookupControl4" class="auto-width">' . lang::get('Add species to list') . ':</label> <input id="taxonLookupControl4" name="taxonLookupControl4" >';
         }
         $r .= '<br /><a href="' . $args['my_walks_page'] . '" class="button">' . lang::get('Finish') . '</a></div>';
     }
     $reloadPath = self::getReloadPath();
     if (isset($args['map_taxon_list_id']) && $args['map_taxon_list_id'] != '') {
         // TODO convert to AJAX.
         data_entry_helper::enable_validation('entry_form');
         $value = helper_base::explode_lines_key_value_pairs($args['defaults']);
         $value = isset($value['occurrence:record_status']) ? $value['occurrence:record_status'] : 'C';
         $r .= '<div id="gridmap">' . "\n" . '<form method="post" id="entry_form" action="' . $reloadPath . '">' . $auth['write'] . '<p>When using this page, please remember that the data is not saved to the database as you go (which is the case for the previous tabs). In order to save the data entered in this page you must click on the Save button at the bottom of the page.</p>' . '<input type="hidden" id="website_id" name="website_id" value="' . $args["website_id"] . '" />' . '<input type="hidden" id="survey_id" name="sample:survey_id" value="' . $args["survey_id"] . '" />' . '<input type="hidden" id="occurrence:record_status" name="occurrence:record_status" value="' . $value . '" />' . '<input type="hidden" name="sample:id" value="' . data_entry_helper::$entity_to_load['sample:id'] . '"/>' . '<input type="hidden" name="page" value="speciesmap"/>' . '<input type="hidden" name="sample:location_id" value="' . $parentLocId . '"/>';
         if (preg_match('/^(\\d{4})/', data_entry_helper::$entity_to_load['sample:date'])) {
             // Date has 4 digit year first (ISO style) - convert date to expected output format
             $d = new DateTime(data_entry_helper::$entity_to_load['sample:date']);
             data_entry_helper::$entity_to_load['sample:date'] = $d->format('d/m/Y');
         }
         $r .= '<input type="hidden" name="sample:date" value="' . data_entry_helper::$entity_to_load['sample:date'] . '"/>';
         // leave the sample_method as it is stored now.
         // Dont need the place search, as we will zoom in to the main location. TODO
         $options = iform_map_get_map_options($args, $auth["read"]);
         if (isset(data_entry_helper::$entity_to_load["sample:geom"])) {
             $options["initialFeatureWkt"] = data_entry_helper::$entity_to_load["sample:wkt"];
         }
         $options["tabDiv"] = "gridmap";
         $olOptions = iform_map_get_ol_options($args);
         if (!isset($options["standardControls"])) {
             $options["standardControls"] = array("layerSwitcher", "panZoomBar");
         }
         $r .= data_entry_helper::map_panel($options, $olOptions);
         // [species map]
         $r .= self::control_speciesmap($auth, $args, "gridmap", array());
         /**
          * The speciesmapsummary is not implemented here
          */
         $r .= '<input type="submit" class="indicia-button" id="save-button" value="' . lang::get('Save') . '" /></form></div>';
         data_entry_helper::$javascript .= "var speciesMapTabHandler = function(event, ui) {\n  if (ui.panel.id=='" . $options["tabDiv"] . "') {\n    if (indiciaData.ParentSampleLayer.features.length > 0) {\n      var bounds=indiciaData.ParentSampleLayer.getDataExtent();\n      bounds.extend(indiciaData.SubSampleLayer.getDataExtent());\n      // extend the boundary to include a buffer, so the map does not zoom too tight.\n      bounds.scale(1.2);\n      indiciaData.ParentSampleLayer.map.zoomToExtent(bounds);\n    }\n  }\n};\njQuery(jQuery('#" . $options["tabDiv"] . "').parent()).bind('tabsshow', speciesMapTabHandler);\n";
     } else {
         // enable validation on the comments form in order to include the simplified ajax queuing for the autocomplete.
         data_entry_helper::enable_validation('notes_form');
     }
     // for the comment form, we want to ensure that if there is a timeout error that it reloads the
     // data as stored in the DB.
     $reloadParts = explode('?', $reloadPath, 2);
     // fragment is always at the end. discard this.
     if (count($reloadParts) > 1) {
         $params = explode('#', $reloadParts[1], 2);
         $params = $params[0] . "&sample_id=" . $parentSampleId;
     } else {
         $reloadParts = explode('#', $reloadParts[0], 2);
         $params = "sample_id=" . $parentSampleId;
     }
     $r .= "<div id=\"notes\">\n";
     $r .= "<form method=\"post\" id=\"notes_form\" action=\"" . $reloadParts[0] . '?' . $params . "#notes\">\n";
     $r .= $auth['write'];
     $r .= '<input type="hidden" name="sample:id" value="' . $parentSampleId . '" />';
     $r .= '<input type="hidden" name="website_id" value="' . $args['website_id'] . '"/>';
     $r .= '<input type="hidden" name="survey_id" value="' . $args['survey_id'] . '"/>';
     $r .= '<input type="hidden" name="page" value="notes"/>';
     $r .= '<p  class="page-notice ui-state-highlight ui-corner-all">' . lang::get('When using this page, please remember that the data is not saved to the database as you go (which is the case for the previous tabs). In order to save the data entered in this page you must click on the Submit button at the bottom of the page.') . '</p>';
     $r .= data_entry_helper::textarea(array('fieldname' => 'sample:comment', 'label' => lang::get('Notes'), 'helpText' => "Use this space to input comments about this week's walk."));
     $r .= '<input type="submit" value="' . lang::get('Submit') . '" id="save-button"/>';
     $r .= '</form>';
     $r .= '<br /><a href="' . $args['my_walks_page'] . '" class="button">' . lang::get('Finish') . '</a>';
     $r .= '</div></div>';
     // A stub form for AJAX posting when we need to create an occurrence
     $r .= '<form style="display: none" id="occ-form" method="post" action="' . iform_ajaxproxy_url($node, 'occurrence') . '">';
     $r .= '<input name="website_id" value="' . $args['website_id'] . '"/>';
     $r .= '<input name="survey_id" value="' . $args["survey_id"] . '" />';
     $r .= '<input name="occurrence:id" id="occid" />';
     $r .= '<input name="occurrence:deleted" id="occdeleted" />';
     $r .= '<input name="occurrence:zero_abundance" id="occzero" />';
     $r .= '<input name="occurrence:taxa_taxon_list_id" id="ttlid" />';
     $r .= '<input name="occurrence:sample_id" id="occ_sampleid"/>';
     if (isset($args["sensitiveAttrID"]) && $args["sensitiveAttrID"] != "" && isset($args["sensitivityPrecision"]) && $args["sensitivityPrecision"] != "") {
         $locationTypes = helper_base::get_termlist_terms($auth, 'indicia:location_types', array(empty($args['transect_type_term']) ? 'Transect' : $args['transect_type_term']));
         $site_attributes = data_entry_helper::getAttributes(array('valuetable' => 'location_attribute_value', 'attrtable' => 'location_attribute', 'key' => 'location_id', 'fieldprefix' => 'locAttr', 'extraParams' => $auth['read'] + array('id' => $args["sensitiveAttrID"]), 'location_type_id' => $locationTypes[0]['id'], 'survey_id' => $args['survey_id'], 'id' => $parentLocId));
         $r .= '<input name="occurrence:sensitivity_precision" id="occSensitive" value="' . (count($site_attributes) > 0 && $site_attributes[$args["sensitiveAttrID"]]['default'] == "1" ? $args["sensitivityPrecision"] : '') . '"/>';
     }
     $r .= '<input name="occAttr:' . $args['occurrence_attribute_id'] . '" id="occattr"/>';
     $r .= '<input name="transaction_id" id="transaction_id"/>';
     $r .= '<input name="user_id" value="' . hostsite_get_user_field('user_id', 1) . '"/>';
     $r .= '</form>';
     // A stub form for AJAX posting when we need to update a sample
     $r .= '<form style="display: none" id="smp-form" method="post" action="' . iform_ajaxproxy_url($node, 'sample') . '">';
     $r .= '<input name="website_id" value="' . $args['website_id'] . '"/>';
     $r .= '<input name="sample:id" id="smpid" />';
     $r .= '<input name="sample:parent_id" value="' . $parentSampleId . '" />';
     $r .= '<input name="sample:survey_id" value="' . $args['survey_id'] . '" />';
     $r .= '<input name="sample:sample_method_id" value="' . $sampleMethods[0]['id'] . '" />';
     $r .= '<input name="sample:entered_sref" id="smpsref" />';
     $r .= '<input name="sample:entered_sref_system" id="smpsref_system" />';
     $r .= '<input name="sample:location_id" id="smploc" />';
     $r .= '<input name="sample:date" value="' . $date . '" />';
     // include a stub input for each transect section sample attribute
     foreach ($attributes as $attr) {
         $r .= '<input id="' . $attr['fieldname'] . '" />';
     }
     $r .= '</form>';
     // tell the Javascript where to get species from.
     // @todo handle diff species lists.
     data_entry_helper::add_resource('jquery_ui');
     data_entry_helper::add_resource('json');
     data_entry_helper::add_resource('autocomplete');
     data_entry_helper::$javascript .= "indiciaData.speciesList1 = " . $args['taxon_list_id'] . ";\n";
     if (!empty($args['main_taxon_filter_field']) && !empty($args['main_taxon_filter'])) {
         data_entry_helper::$javascript .= "indiciaData.speciesList1FilterField = '" . $args['main_taxon_filter_field'] . "';\n";
         $filterLines = helper_base::explode_lines($args['main_taxon_filter']);
         data_entry_helper::$javascript .= "indiciaData.speciesList1FilterValues = '" . json_encode($filterLines) . "';\n";
     }
     data_entry_helper::$javascript .= "bindSpeciesAutocomplete(\"taxonLookupControl\",\"table#transect-input1\",\"" . data_entry_helper::$base_url . "index.php/services/data\", \"" . $args['taxon_list_id'] . "\",\n  indiciaData.speciesList1FilterField, indiciaData.speciesList1FilterValues, {\"auth_token\" : \"" . $auth['read']['auth_token'] . "\", \"nonce\" : \"" . $auth['read']['nonce'] . "\"},\n  \"" . lang::get('LANG_Duplicate_Taxon') . "\", 25, 1);\n\nindiciaData.speciesList1Subset = " . (isset($args['common_taxon_list_id']) && $args['common_taxon_list_id'] != "" ? $args['common_taxon_list_id'] : "-1") . ";\n";
     if (!empty($args['common_taxon_filter_field']) && !empty($args['common_taxon_filter'])) {
         data_entry_helper::$javascript .= "indiciaData.speciesList1SubsetFilterField = '" . $args['common_taxon_filter_field'] . "';\n";
         $filterLines = helper_base::explode_lines($args['common_taxon_filter']);
         data_entry_helper::$javascript .= "indiciaData.speciesList1SubsetFilterValues = '" . json_encode($filterLines) . "';\n";
     }
     data_entry_helper::$javascript .= "indiciaData.speciesList2 = " . (isset($args['second_taxon_list_id']) && $args['second_taxon_list_id'] != "" ? $args['second_taxon_list_id'] : "-1") . ";\n";
     if (!empty($args['second_taxon_filter_field']) && !empty($args['second_taxon_filter'])) {
         data_entry_helper::$javascript .= "indiciaData.speciesList2FilterField = '" . $args['second_taxon_filter_field'] . "';\n";
         $filterLines = helper_base::explode_lines($args['second_taxon_filter']);
         data_entry_helper::$javascript .= "indiciaData.speciesList2FilterValues = " . json_encode($filterLines) . ";\n";
     }
     data_entry_helper::$javascript .= "indiciaData.speciesList2Force = " . (isset($args['force_second']) && $args['force_second'] ? 'true' : 'false') . ";\n";
     if (!isset($args['force_second']) || !$args['force_second']) {
         data_entry_helper::$javascript .= "bindSpeciesAutocomplete(\"taxonLookupControl2\",\"table#transect-input2\",\"" . data_entry_helper::$base_url . "index.php/services/data\", indiciaData.speciesList2,\n  indiciaData.speciesList2FilterField, indiciaData.speciesList2FilterValues, {\"auth_token\" : \"" . $auth['read']['auth_token'] . "\", \"nonce\" : \"" . $auth['read']['nonce'] . "\"},\n  \"" . lang::get('LANG_Duplicate_Taxon') . "\", 25, 2);\n\n";
     }
     data_entry_helper::$javascript .= "indiciaData.speciesList3 = " . (isset($args['third_taxon_list_id']) && $args['third_taxon_list_id'] != "" ? $args['third_taxon_list_id'] : "-1") . ";\n";
     if (!empty($args['third_taxon_filter_field']) && !empty($args['third_taxon_filter'])) {
         data_entry_helper::$javascript .= "indiciaData.speciesList3FilterField = '" . $args['third_taxon_filter_field'] . "';\n";
         $filterLines = helper_base::explode_lines($args['third_taxon_filter']);
         data_entry_helper::$javascript .= "indiciaData.speciesList3FilterValues = " . json_encode($filterLines) . ";\n";
     }
     data_entry_helper::$javascript .= "indiciaData.speciesList3Force = " . (isset($args['force_third']) && $args['force_third'] ? 'true' : 'false') . ";\n";
     if (!isset($args['force_third']) || !$args['force_third']) {
         data_entry_helper::$javascript .= "bindSpeciesAutocomplete(\"taxonLookupControl3\",\"table#transect-input3\",\"" . data_entry_helper::$base_url . "index.php/services/data\", indiciaData.speciesList3,\n    indiciaData.speciesList3FilterField, indiciaData.speciesList3FilterValues, {\"auth_token\" : \"" . $auth['read']['auth_token'] . "\", \"nonce\" : \"" . $auth['read']['nonce'] . "\"},\n    \"" . lang::get('LANG_Duplicate_Taxon') . "\", 25, 3);\n\n";
     }
     data_entry_helper::$javascript .= "indiciaData.speciesList4 = " . (isset($args['fourth_taxon_list_id']) && $args['fourth_taxon_list_id'] != "" ? $args['fourth_taxon_list_id'] : "-1") . ";\n";
     if (!empty($args['fourth_taxon_filter_field']) && !empty($args['fourth_taxon_filter'])) {
         data_entry_helper::$javascript .= "indiciaData.speciesList4FilterField = '" . $args['fourth_taxon_filter_field'] . "';\n";
         $filterLines = helper_base::explode_lines($args['fourth_taxon_filter']);
         data_entry_helper::$javascript .= "indiciaData.speciesList4FilterValues = " . json_encode($filterLines) . ";\n";
     }
     data_entry_helper::$javascript .= "indiciaData.speciesList4Force = " . (isset($args['force_fourth']) && $args['force_fourth'] ? 'true' : 'false') . ";\n";
     // allow js to do AJAX by passing in the information it needs to post forms
     if (!isset($args['force_fourth']) || !$args['force_fourth']) {
         data_entry_helper::$javascript .= "bindSpeciesAutocomplete(\"taxonLookupControl4\",\"table#transect-input4\",\"" . data_entry_helper::$base_url . "index.php/services/data\", indiciaData.speciesList4,\n  indiciaData.speciesList4FilterField, indiciaData.speciesList4FilterValues, {\"auth_token\" : \"" . $auth['read']['auth_token'] . "\", \"nonce\" : \"" . $auth['read']['nonce'] . "\"},\n  \"" . lang::get('LANG_Duplicate_Taxon') . "\", 25, 4);\n\n";
     }
     data_entry_helper::$javascript .= "indiciaData.indiciaSvc = '" . data_entry_helper::$base_url . "';\n";
     data_entry_helper::$javascript .= "indiciaData.readAuth = {nonce: '" . $auth['read']['nonce'] . "', auth_token: '" . $auth['read']['auth_token'] . "'};\n";
     data_entry_helper::$javascript .= "indiciaData.transect = " . $parentLocId . ";\n";
     data_entry_helper::$javascript .= "indiciaData.parentSample = " . $parentSampleId . ";\n";
     data_entry_helper::$javascript .= "indiciaData.sections = " . json_encode($sections) . ";\n";
     if (function_exists('module_exists') && module_exists('easy_login')) {
         data_entry_helper::$javascript .= "indiciaData.easyLogin = true;\n";
         $userId = hostsite_get_user_field('indicia_user_id');
         if (!empty($userId)) {
             data_entry_helper::$javascript .= "indiciaData.UserID = " . $userId . ";\n";
         } else {
             return '<p>Easy Login active but could not identify user</p>';
         }
         // something is wrong
     } else {
         data_entry_helper::$javascript .= "indiciaData.easyLogin = false;\n";
         data_entry_helper::$javascript .= "indiciaData.CMSUserAttrID = " . $cmsUserAttr['attributeId'] . ";\n";
         data_entry_helper::$javascript .= "indiciaData.CMSUserID = " . $user->uid . ";\n";
     }
     // Do an AJAX population of the grid rows.
     data_entry_helper::$javascript .= "loadSpeciesList();\njQuery('#tabs').bind('tabsshow', function(event, ui) {\n    var target = ui.panel;\n    // first get rid of any previous tables\n    jQuery('table.sticky-header').remove();\n    jQuery('table.sticky-enabled thead.tableHeader-processed').removeClass('tableHeader-processed');\n    jQuery('table.sticky-enabled.tableheader-processed').removeClass('tableheader-processed');\n    jQuery('table.species-grid.sticky-enabled').removeClass('sticky-enabled');\n    var table = jQuery('#'+target.id+' table.species-grid');\n    if(table.length > 0) {\n        table.addClass('sticky-enabled');\n        if(typeof Drupal.behaviors.tableHeader == 'object') // Drupal 7\n          Drupal.behaviors.tableHeader.attach(table.parent());\n        else // Drupal6 : it is a function\n          Drupal.behaviors.tableHeader(target);\n    }\n    // remove any hanging autocomplete select list.\n    jQuery('.ac_results').hide();\n});";
     return $r;
 }
Пример #6
0
 private static function get_site_trees_tab($auth, $args, $settings)
 {
     global $indicia_templates;
     $r = '<div id="site-trees" class="ui-helper-clearfix">';
     $r .= '<form method="post" id="tree-form" action="' . self::$ajaxFormUrl . '">';
     $help = '<p>' . lang::get('To add a tree, click on the "Add Tree" button. You can then use the map\'s Location Tool to select the approximate location of your tree on the map. A new tree will then appear on the map.') . '</p>' . '<p>' . lang::get('To select a tree from the existing list of trees at this site you can either:') . '</p>' . '<ol><li>' . lang::get('Click on the button for the tree you wish to view, or') . '</li>' . '<li>' . lang::get('Use the map\'s Query Tool to click on the tree you wish to view on the map.') . '</li></ol>' . '<p>' . lang::get('To remove a tree, first select the tree you wish to remove, then click on the "Remove Tree" button. It will remove the current tree you are viewing completely.') . '</p>';
     $r .= '<div class="ui-state-highlight page-notice ui-corner-all">' . $help . '</div>';
     $r .= self::tree_selector($settings);
     $r .= '<input type="button" value="' . lang::get('Remove Tree') . '" class="remove-tree form-button right" title="' . lang::get('Completely remove the highlighted tree. The total number of tree will be reduced by one. The form will be reloaded after the tree is deleted.') . '">';
     $r .= '<input type="button" value="' . lang::get('Add Tree') . '" class="insert-tree form-button right" title="' . lang::get('This inserts an extra tree.') . '">';
     $r .= '<div id="cols" class="ui-helper-clearfix"><div class="left" style="width: ' . (98 - (isset($args['percent_width']) ? $args['percent_width'] : 50)) . '%">';
     $r .= '<fieldset><legend>' . lang::get('Tree Details') . '</legend>';
     $r .= '<input type="hidden" name="location:id" value="" id="tree-location-id" />';
     $r .= '<input type="hidden" name="locations_website:website_id" value="' . $args['website_id'] . '" id="locations-website-website-id" />';
     $r .= '<input type="hidden" name="location:parent_id" value="' . $settings['locationId'] . '" />';
     $r .= '<input type="hidden" name="location:location_type_id" value="' . $settings['TreeLocationType'][0]['id'] . '" />';
     $r .= '<input type="hidden" name="website_id" value="' . $args['website_id'] . "\" />\n";
     $r .= data_entry_helper::text_input(array('fieldname' => 'location:name', 'label' => lang::get('Tree ID'), 'class' => 'control-width-4 required'));
     $systems = array();
     $list = explode(',', str_replace(' ', '', $args['spatial_systems']));
     foreach ($list as $system) {
         $systems[$system] = lang::get($system);
     }
     $srefOptions = array('id' => 'imp-sref-tree', 'fieldname' => 'location:centroid_sref', 'geomid' => 'imp-geom-tree', 'geomFieldname' => 'location:centroid_geom', 'label' => 'Grid Ref', 'labelClass' => 'auto', 'class' => 'required', 'helpText' => lang::get('You can also click on the map to set the grid reference. If directly entering the coordinates from a GPS device, set the format to "Lat/Long" first. To enter an OS Grid square, choose the "OSGB" or "OSIE" formats.'));
     data_entry_helper::$javascript .= "\n\$('#imp-sref-tree').attr('title',\n    '" . lang::get("When directly entering coordinates as a GPS Lat/Long reading, there should be no spaces between the numbers and the letter. " . "The degrees, minutes and seconds must all be separated by a colon (:). The direction letter can be placed at the start or the end of the number (e.g. N56.532 or 56.532N). " . "The figures may be entered as decimal degrees (e.g. 56.532), degrees and decimal minutes (e.g. 56:31.92), or degrees, minutes and decimal seconds (e.g. 56:31:55.2). " . "You can mix the formats of the Latitude and Longitude, provided they each follow the previous guidelines and a space separates them (e.g. N56.532 2:30W).") . "  " . lang::get("When directly entering an OS map reference, there should be no spaces between any of the characters. " . "An OSGB reference should comprise of 2 letters followed by an even number of digits (e.g. NT274628). " . "An OSIE reference should comprise of of 1 letter followed by an even number of digits (e.g. J081880).") . "');\n";
     // Output the sref control
     $r .= data_entry_helper::sref_textbox($srefOptions);
     $srefOptions = array('id' => 'imp-sref-system-tree', 'fieldname' => 'location:centroid_sref_system', 'class' => 'required', 'systems' => $systems);
     // Output the system control
     if (count($systems) < 2) {
         // Hidden field for the system
         $keys = array_keys($options['systems']);
         $r .= "<input type=\"hidden\" id=\"imp-sref-system-tree\" name=\"" . $options['fieldname'] . "\" value=\"" . $keys[0] . "\" />\n";
         // TODO    	self::include_sref_handler_js($options['systems']);
     } else {
         $r .= data_entry_helper::sref_system_select($srefOptions);
     }
     $r .= '<input type="hidden" name="survey_id" value="' . $args['survey_id'] . '" />';
     $r .= '<input type="hidden" name="sample:survey_id" value="' . $args['survey_id'] . '" />';
     $r .= '<input type="hidden" name="sample:id" value="" />';
     // this sample will reference the location id.
     if (isset(data_entry_helper::$entity_to_load['sample:date']) && preg_match('/^(\\d{4})/', data_entry_helper::$entity_to_load['sample:date'])) {
         // Date has 4 digit year first (ISO style) - convert date to expected output format
         // @todo The date format should be a global configurable option. It should also be applied to reloading of custom date attributes.
         $d = new DateTime(data_entry_helper::$entity_to_load['sample:date']);
         data_entry_helper::$entity_to_load['sample:date'] = $d->format('d/m/Y');
     }
     $r .= data_entry_helper::date_picker(array('label' => lang::get('Date Tree Selected'), 'fieldname' => 'sample:date', 'class' => 'control-width-2 required'));
     $r .= '<input type="hidden" id="sample:sample_method_id" value="' . $settings['treeSampleMethod']['id'] . '" name="sample:sample_method_id">';
     $r .= '<input type="hidden" id="sample:location_name" value="" name="sample:location_name">';
     $r .= '<input type="hidden" name="occurrence:id" value="" id="occurrence:id" />';
     $r .= '<input type="hidden" name="occurrence:record_status" value="C" id="occurrence:record_status" />';
     $extraParams = $auth['read'];
     $extraParams['taxon_list_id'] = $args['taxon_list_id'];
     $options = array('speciesNameFilterMode' => $args['speciesNameFilterMode']);
     $ctrl = $args['species_ctrl'];
     $species_ctrl_opts = array_merge(array('fieldname' => 'occurrence:taxa_taxon_list_id', 'label' => lang::get('Tree Species'), 'columns' => 1, 'parentField' => 'parent_id', 'blankText' => lang::get('Please select'), 'cacheLookup' => false), $options);
     if (isset($species_ctrl_opts['extraParams'])) {
         $species_ctrl_opts['extraParams'] = array_merge($extraParams, $species_ctrl_opts['extraParams']);
     } else {
         $species_ctrl_opts['extraParams'] = $extraParams;
     }
     if (!empty($args['taxon_filter'])) {
         $species_ctrl_opts['taxonFilterField'] = $args['taxon_filter_field'];
         // applies to autocompletes
         $species_ctrl_opts['taxonFilter'] = helper_base::explode_lines($args['taxon_filter']);
         // applies to autocompletes
     }
     // obtain table to query and hence fields to use
     $db = data_entry_helper::get_species_lookup_db_definition(false);
     // get local vars for the array
     extract($db);
     if ($ctrl !== 'species_autocomplete') {
         // The species autocomplete has built in support for the species name filter.
         // For other controls we need to apply the species name filter to the params used for population
         if (!empty($species_ctrl_opts['taxonFilter']) || $options['speciesNameFilterMode']) {
             $species_ctrl_opts['extraParams'] = array_merge($species_ctrl_opts['extraParams'], data_entry_helper::get_species_names_filter($species_ctrl_opts));
         }
         // for controls which don't know how to do the lookup, we need to tell them
         $species_ctrl_opts = array_merge(array('table' => $tblTaxon, 'captionField' => $colTaxon, 'valueField' => $colId), $species_ctrl_opts);
     }
     // if using something other than an autocomplete, then set the caption template to include the appropriate names. Autocompletes
     // use a JS function instead.
     if ($ctrl !== 'autocomplete' && isset($args['species_include_both_names']) && $args['species_include_both_names']) {
         if ($args['speciesNameFilterMode'] === 'all') {
             $indicia_templates['species_caption'] = "{{$colTaxon}}";
         } elseif ($args['speciesNameFilterMode'] === 'language') {
             $indicia_templates['species_caption'] = "{{$colTaxon}} - {{$colPreferred}}";
         } else {
             $indicia_templates['species_caption'] = "{{$colTaxon}} - {{$colCommon}}";
         }
         $species_ctrl_opts['captionTemplate'] = 'species_caption';
     }
     if ($ctrl == 'tree_browser') {
         // change the node template to include images
         $indicia_templates['tree_browser_node'] = '<div>' . '<img src="' . data_entry_helper::$base_url . '/upload/thumb-{image_path}" alt="Image of {caption}" width="80" /></div>' . '<span>{caption}</span>';
     }
     // Dynamically generate the species selection control required.
     $r .= call_user_func(array('data_entry_helper', $ctrl), $species_ctrl_opts);
     $ctrlOptions = array('extraParams' => $auth['read']);
     $attrSpecificOptions = array();
     $options = helper_base::explode_lines_key_value_pairs($args['attrOptions']);
     self::parseForAttrSpecificOptions($options, $ctrlOptions, $attrSpecificOptions);
     $r .= get_attribute_html($settings['tree_attributes'], $args, $ctrlOptions, '', $attrSpecificOptions);
     $r .= '</fieldset>';
     $r .= "</div>" . '<div class="right" style="width: ' . (isset($args['percent_width']) ? $args['percent_width'] : 50) . '%">';
     $olOptions = iform_map_get_ol_options($args);
     $options = iform_map_get_map_options($args, $auth['read']);
     $options['divId'] = 'trees-map';
     $options['toolbarDiv'] = 'top';
     $options['tabDiv'] = 'site-trees';
     $options['gridRefHint'] = true;
     $options['latLongFormat'] = 'DMS';
     // TODO drive from args or user.
     if (array_key_exists('standard_controls_trees', $args) && $args['standard_controls_trees']) {
         $standard_controls_trees = str_replace("\r\n", "\n", $args['standard_controls_trees']);
         $options['standardControls'] = explode("\n", $standard_controls_trees);
         // If drawing controls are enabled, then allow polygon recording.
         if (in_array('drawPolygon', $options['standardControls']) || in_array('drawLine', $options['standardControls'])) {
             $options['allowPolygonRecording'] = true;
         }
     }
     // also let the user click on a feature to select it. The highlighter just makes it easier to select one.
     // these controls are not present in read-only mode: all you can do is look at the map.
     $options['switchOffSrefRetrigger'] = true;
     $options['clickForSpatialRef'] = true;
     // override the opacity so the parent square does not appear filled in.
     $options['fillOpacity'] = 0;
     // override the map height and buffer size, which are specific to this map.
     $options['height'] = $args['tree_map_height'];
     $options['maxZoomBuffer'] = $args['tree_map_buffer'];
     $options['srefId'] = 'imp-sref-tree';
     $options['geomId'] = 'imp-geom-tree';
     $options['srefSystemId'] = 'imp-sref-system-tree';
     $help = '<p>' . lang::get('Add your trees using the appropriate tools in the top right of the map') . ':</p>' . '<ol><li>' . lang::get('Navigation Tool.') . '</li>' . '<li>' . lang::get('Query Tool. This tool allows you to click on a tree on the map to view its tree details.') . '</li>' . '<li>' . lang::get('Location Tool. This tool allows you to select the approximate location of a new tree on your site map. You can also reposition existing trees by first clicking on the tree and then clicking on its new location on the map.') . '</li></ol>';
     $r .= '<div class="ui-state-highlight page-notice ui-corner-all">' . $help . '</div>';
     $r .= map_helper::map_panel($options, $olOptions);
     $r .= data_entry_helper::file_box(array('table' => 'location_medium', 'readAuth' => $auth['read'], 'caption' => lang::get('Photos of Tree'), 'readAuth' => $auth['read']));
     $r .= "</div>";
     // right
     $r .= '<div class="follow_on_block" style="clear:both;">';
     $r .= get_attribute_html($settings['tree_attributes'], $args, $ctrlOptions, 'Lower Block', $attrSpecificOptions);
     data_entry_helper::$javascript .= "\n\$('#fieldset-optional-external-sc').prepend(\"" . lang::get('If you choose to record this tree for one of the citizen science projects below, please submit the tree ID used for that scheme.') . "\");\n";
     $r .= data_entry_helper::textarea(array('id' => 'location-comment', 'fieldname' => 'location:comment', 'label' => lang::get("Additional information"), 'labelClass' => 'autowidth')) . "<br />";
     $r .= '<input type="submit" value="' . lang::get('Save') . '" class="form-button right" id="submit-tree" />';
     $r .= '</div></form></div>';
     data_entry_helper::$onload_javascript .= "\$('#current-tree').change(selectTree);\n";
     return $r;
 }