/**
  * Outputs a map with an overlay of regions, showing a count for each. Default is to count records, but can
  * be configured to count taxa.
  *
  * @param array $auth Authorisation tokens.
  * @param array $args Form arguments (the settings on the form edit tab).
  * @param string $tabalias The alias of the tab this is being loaded onto.
  * @param array $options The options passed to this control using @option=value settings in the form structure.
  * Options supported are those which can be passed to the report_helper::report_map method. In addition
  * set @output=species to configure the report to show a species counts map.   
  * @param string $path The page reload path, in case it is required for the building of links.
  * @return string HTML to insert into the page for the location map. JavaScript is added to the variables in helper_base.
  *
  * @link http://www.biodiverseit.co.uk/indicia/dev/docs/classes/report_helper.html#method_report_map API docs for report_helper::report_map
  */
 public static function count_by_location_map($auth, $args, $tabalias, $options, $path)
 {
     iform_load_helpers(array('map_helper', 'report_helper'));
     require_once iform_client_helpers_path() . 'prebuilt_forms/includes/map.php';
     $mapOptions = iform_map_get_map_options($args, $auth['read']);
     $olOptions = iform_map_get_ol_options($args);
     $mapOptions['clickForSpatialRef'] = false;
     $r = map_helper::map_panel($mapOptions, $olOptions);
     if (!empty($options['output']) && $options['output'] === 'species') {
         $type = 'species';
     } else {
         $type = 'occurrence';
     }
     $reportOptions = array_merge(iform_report_get_report_options($args, $auth['read']), array('dataSource' => "library/locations/{$type}_counts_mappable_for_event", 'featureDoubleOutlineColour' => '#f7f7f7', 'rowId' => 'id'), $options);
     $r .= report_helper::report_map($reportOptions);
     return $r;
 }
 /**
  * Outputs a map with an overlay of regions, showing a count for each. Default is to count records, but can
  * be configured to count taxa.
  *
  * @param array $auth Authorisation tokens.
  * @param array $args Form arguments (the settings on the form edit tab).
  * @param string $tabalias The alias of the tab this is being loaded onto.
  * @param array $options The options passed to this control using @option=value settings in the form structure.
  * Options supported are those which can be passed to the report_helper::report_map method. In addition
  * set @output=species to configure the report to show a species counts map and set @title=... to 
  * include a heading in the output.   
  * @param string $path The page reload path, in case it is required for the building of links.
  * @return string HTML to insert into the page for the location map. JavaScript is added to the variables in helper_base.
  *
  * @link http://www.biodiverseit.co.uk/indicia/dev/docs/classes/report_helper.html#method_report_map API docs for report_helper::report_map
  */
 public static function count_by_location_map($auth, $args, $tabalias, $options, $path)
 {
     iform_load_helpers(array('map_helper', 'report_helper'));
     require_once iform_client_helpers_path() . 'prebuilt_forms/includes/map.php';
     $mapOptions = iform_map_get_map_options($args, $auth['read']);
     $olOptions = iform_map_get_ol_options($args);
     $mapOptions['clickForSpatialRef'] = false;
     if ($args['interface'] !== 'one_page') {
         $mapOptions['tabDiv'] = $tabalias;
     }
     $r = self::output_title($options);
     $r .= map_helper::map_panel($mapOptions, $olOptions);
     if (!empty($options['output']) && $options['output'] === 'species') {
         $type = 'species';
     } else {
         $type = 'occurrence';
     }
     $subtype = empty($options['linked']) || $options['linked'] === false ? '' : '_linked';
     $reportOptions = array_merge(iform_report_get_report_options($args, $auth['read']), array('dataSource' => "library/locations/filterable_{$type}_counts_mappable{$subtype}", 'featureDoubleOutlineColour' => '#f7f7f7', 'rowId' => 'id', 'caching' => true, 'cachePerUser' => false), $options);
     $r .= report_helper::report_map($reportOptions);
     return $r;
 }
 /**
  * Return the generated form output.
  * @return Form HTML.
  */
 public static function get_form($args)
 {
     iform_load_helpers(array('map_helper'));
     $readAuth = map_helper::get_read_auth($args['website_id'], $args['password']);
     // setup the map options
     $options = iform_map_get_map_options($args, $readAuth);
     $olOptions = iform_map_get_ol_options($args);
     for ($layer = 1; $layer <= 3; $layer++) {
         $argTitle = $args["layer_title_{$layer}"];
         if (isset($argTitle) && !empty($argTitle)) {
             //if there is no title then ignore the layer
             $meaningId = self::get_meaning_id($layer, $args, $readAuth);
             $taxon = self::get_taxon($meaningId, $readAuth);
             $layerTitle = str_replace('{species}', $taxon, $argTitle);
             $layerTitle = str_replace("'", "\\'", $layerTitle);
             $url = map_helper::$geoserver_url . 'wms';
             $argFeature = $args["wms_feature_type_{$layer}"];
             $layers = "layers: '{$argFeature}'";
             $argStyle = $args["wms_style_{$layer}"];
             $style = $argStyle ? ", styles: '{$argStyle}'" : '';
             $argWebsite = $args["website_id"];
             $filter = ", CQL_FILTER: 'website_id={$argWebsite} AND taxon_meaning_id={$meaningId}";
             $argCql = $args["cql_filter_{$layer}"];
             if ($argCql) {
                 $arg = str_replace("'", "\\'", $argCql);
                 $filter .= " AND({$argCql})'";
             } else {
                 $filter .= "'";
             }
             $script = "  var distLayer{$layer} = new OpenLayers.Layer.WMS(";
             $script .= "'{$layerTitle}', '{$url}',";
             $script .= "{" . "{$layers}, transparent: true {$filter} {$style}},";
             $script .= "{isBaseLayer: false, sphericalMercator: true, singleTile: true}";
             $script .= ");\n";
             map_helper::$onload_javascript .= $script;
             $options['layers'][] = "distLayer{$layer}";
         }
     }
     // This is not a map used for input
     $options['editLayer'] = false;
     // output a legend
     $r .= map_helper::layer_list(array('includeSwitchers' => true, 'includeHiddenLayers' => true));
     // output a map
     $r .= map_helper::map_panel($options, $olOptions);
     // Set up a page refresh for dynamic update of the map at set intervals
     if ($args['refresh_timer'] !== 0 && is_numeric($args['refresh_timer'])) {
         // is_int prevents injection
         if (isset($args['load_on_refresh']) && !empty($args['load_on_refresh'])) {
             map_helper::$javascript .= "setTimeout('window.location=\"" . $args['load_on_refresh'] . "\";', " . $args['refresh_timer'] . "*1000 );\n";
         } else {
             map_helper::$javascript .= "setTimeout('window.location.reload( false );', " . $args['refresh_timer'] . "*1000 );\n";
         }
     }
     return $r;
 }
 public static function get_sample_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.';
     }
     iform_load_helpers(array('map_helper'));
     $auth = data_entry_helper::get_read_write_auth($args['website_id'], $args['password']);
     $sampleId = isset($_GET['sample_id']) ? $_GET['sample_id'] : null;
     $locationId = null;
     if ($sampleId) {
         data_entry_helper::load_existing_record($auth['read'], 'sample', $sampleId, 'detail', false, true);
         $locationId = data_entry_helper::$entity_to_load['sample:location_id'];
     } else {
         // location ID also might be in the $_POST data after a validation save of a new record
         if (isset($_POST['sample:location_id'])) {
             $locationId = $_POST['sample:location_id'];
         }
     }
     $url = explode('?', $args['my_obs_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_obs_page'] = url($url[0], array('query' => $params, 'fragment' => $fragment, 'absolute' => TRUE));
     $r = '<form method="post" id="sample">';
     $r .= $auth['write'];
     $r .= '<input type="hidden" name="page" value="mainSample"/>';
     $r .= '<input type="hidden" name="website_id" value="' . $args['website_id'] . '"/>';
     if (isset(data_entry_helper::$entity_to_load['sample:id'])) {
         $r .= '<input type="hidden" name="sample:id" value="' . data_entry_helper::$entity_to_load['sample:id'] . '"/>';
     }
     $r .= '<input type="hidden" name="sample:survey_id" value="' . $args['survey_id'] . '"/>';
     $r .= '<div id="cols" class="ui-helper-clearfix"><div class="left" style="width: ' . (98 - (isset($args['percent_width']) ? $args['percent_width'] : 50)) . '%">';
     // Output only the locations for this website and location type.
     $availableSites = data_entry_helper::get_population_data(array('report' => 'library/locations/locations_list', 'extraParams' => $auth['read'] + array('website_id' => $args['website_id'], 'location_type_id' => $args['locationType'], 'locattrs' => 'CMS User ID', 'attr_location_cms_user_id' => $user->uid), 'nocache' => true));
     // convert the report data to an array for the lookup, plus one to pass to the JS so it can keep the map updated
     $sitesLookup = array();
     $sitesIds = array();
     $sitesJs = array();
     foreach ($availableSites as $site) {
         $sitesLookup[$site['location_id']] = $site['name'];
         $sitesIds[] = $site['location_id'];
     }
     $sites = data_entry_helper::get_population_data(array('table' => 'location', 'extraParams' => $auth['read'] + array('website_id' => $args['website_id'], 'id' => $sitesIds, 'view' => 'detail')));
     foreach ($sites as $site) {
         $sitesJs[$site['id']] = $site;
     }
     data_entry_helper::$javascript .= "indiciaData.sites = " . json_encode($sitesJs) . ";\n";
     if ($locationId) {
         $r .= '<input type="hidden" name="sample:location_id" id="sample_location_id" value="' . $locationId . '"/>';
         // for reload of existing, don't let the user switch the square as that could mess everything up.
         $r .= '<label>' . lang::get('1km square') . ':</label><span>' . $sitesJs[$locationId]['name'] . '</span><br/>' . lang::get('<p class="ui-state-highlight page-notice ui-corner-all">Please use the map to select a more precise location for your timed observation.</p>');
     } else {
         $options = array('label' => lang::get('Select 1km square'), 'validation' => array('required'), 'blankText' => lang::get('Please select'), 'lookupValues' => $sitesLookup, 'id' => "sample_location_id");
         // if ($locationId) $options['default'] = $locationId;
         $r .= data_entry_helper::location_select($options) . lang::get('<p class="ui-state-highlight page-notice ui-corner-all">After selecting the 1km square, use the map to select a more precise location for your timed observation.</p>');
     }
     // [spatial reference]
     $systems = array();
     foreach (explode(',', str_replace(' ', '', $args['spatial_systems'])) as $system) {
         $systems[$system] = lang::get("sref:{$system}");
     }
     $r .= data_entry_helper::sref_and_system(array('label' => lang::get('Grid Ref'), 'systems' => $systems));
     $r .= data_entry_helper::file_box(array('table' => 'sample_image', 'readAuth' => $auth['read'], 'caption' => lang::get('Upload photo(s) of timed search area')));
     $sampleMethods = helper_base::get_termlist_terms($auth, 'indicia:sample_methods', array('Field Observation'));
     $attributes = data_entry_helper::getAttributes(array('id' => $sampleId, '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']));
     $r .= get_user_profile_hidden_inputs($attributes, $args, '', $auth['read']);
     if (isset($_GET['date'])) {
         $r .= '<input type="hidden" name="sample:date" value="' . $_GET['date'] . '"/>';
         $r .= '<label>' . lang::get('Date') . ':</label> <span class="value-label">' . $_GET['date'] . '</span><br/>';
     } else {
         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'), 'fieldname' => 'sample:date'));
     }
     // are there any option overrides for the custom attributes?
     if (isset($args['custom_attribute_options']) && $args['custom_attribute_options']) {
         $blockOptions = get_attr_options_array_with_user_data($args['custom_attribute_options']);
     } else {
         $blockOptions = array();
     }
     $r .= get_attribute_html($attributes, $args, array('extraParams' => $auth['read']), null, $blockOptions);
     $r .= '<input type="hidden" name="sample:sample_method_id" value="' . $sampleMethods[0]['id'] . '" />';
     $r .= '<input type="submit" value="' . lang::get('Next') . '" />';
     $r .= '<a href="' . $args['my_obs_page'] . '" class="button">' . lang::get('Cancel') . '</a>';
     if (isset(data_entry_helper::$entity_to_load['sample:id'])) {
         $r .= '<button id="delete-button" type="button" class="ui-state-default ui-corner-all" />' . lang::get('Delete') . '</button>';
     }
     $r .= "</div>";
     // left
     $r .= '<div class="right" style="width: ' . (isset($args['percent_width']) ? $args['percent_width'] : 50) . '%">';
     // [place search]
     $georefOpts = iform_map_get_georef_options($args, $auth['read']);
     $georefOpts['label'] = lang::get('Search for Place on Map');
     // can't use place search without the driver API key
     if ($georefOpts['driver'] == 'geoplanet' && empty(helper_config::$geoplanet_api_key)) {
         $r .= '<span style="display: none;">The form structure includes a place search but needs a geoplanet api key.</span>';
     } else {
         $r .= data_entry_helper::georeference_lookup($georefOpts);
     }
     // [map]
     $options = iform_map_get_map_options($args, $auth['read']);
     if (!empty(data_entry_helper::$entity_to_load['sample:wkt'])) {
         $options['initialFeatureWkt'] = data_entry_helper::$entity_to_load['sample:wkt'];
     }
     $olOptions = iform_map_get_ol_options($args);
     if (!isset($options['standardControls'])) {
         $options['standardControls'] = array('layerSwitcher', 'panZoomBar');
     }
     $r .= map_helper::map_panel($options, $olOptions);
     data_entry_helper::$javascript .= "\nmapInitialisationHooks.push(function(mapdiv) {\n  var defaultStyle = new OpenLayers.Style({pointRadius: 6,fillOpacity: 0,strokeColor: \"Red\",strokeWidth: 1});\n  var SiteStyleMap = new OpenLayers.StyleMap({\"default\": defaultStyle});\n  indiciaData.SiteLayer = new OpenLayers.Layer.Vector('1km square',{styleMap: SiteStyleMap, displayInLayerSwitcher: true});\n  mapdiv.map.addLayer(indiciaData.SiteLayer);\n  if(jQuery('#sample_location_id').length > 0) {\n    if(jQuery('#sample_location_id').val() != ''){\n      var parser = new OpenLayers.Format.WKT();\n      var feature = parser.read(indiciaData.sites[jQuery('#sample_location_id').val()].geom);\n      indiciaData.SiteLayer.addFeatures([feature]);\n      // for existing data we zoom on the site, not this parent location\n    } \n    jQuery('#sample_location_id').change(function(){\n      indiciaData.SiteLayer.destroyFeatures();\n      if(jQuery('#sample_location_id').val() != ''){\n        var parser = new OpenLayers.Format.WKT();\n        var feature = parser.read(indiciaData.sites[jQuery('#sample_location_id').val()].geom);\n        indiciaData.SiteLayer.addFeatures([feature]);\n        var layerBounds = indiciaData.SiteLayer.getDataExtent().clone(); // use a clone\n        indiciaData.SiteLayer.map.zoomToExtent(layerBounds);\n      }\n    });\n  }\n});\n";
     $r .= "</div>";
     // right
     $r .= '</form>';
     // Recorder Name - assume Easy Login uid
     if (function_exists('module_exists') && module_exists('easy_login')) {
         $userId = hostsite_get_user_field('indicia_user_id');
         // For non easy login test only     $userId = 1;
         foreach ($attributes as $attrID => $attr) {
             if (strcasecmp('Recorder Name', $attr["untranslatedCaption"]) == 0 && !empty($userId)) {
                 // determining which you have used is difficult from a services based autocomplete, esp when the created_by_id is not available on the data.
                 data_entry_helper::add_resource('autocomplete');
                 data_entry_helper::$javascript .= "bindRecorderNameAutocomplete(" . $attrID . ", '" . $userId . "', '" . data_entry_helper::$base_url . "', '" . $args['survey_id'] . "', '" . $auth['read']['auth_token'] . "', '" . $auth['read']['nonce'] . "');\n";
             }
         }
     }
     if (isset(data_entry_helper::$entity_to_load['sample:id'])) {
         // allow deletes if sample id is present.
         data_entry_helper::$javascript .= "jQuery('#delete-button').click(function(){\n  if(confirm(\"" . lang::get('Are you sure you want to delete this walk?') . "\")){\n    jQuery('#delete-form').submit();\n  } // else do nothing.\n});\n";
         // note we only require bare minimum in order to flag a sample as deleted.
         $r .= '<form method="post" id="delete-form" style="display: none;">';
         $r .= $auth['write'];
         $r .= '<input type="hidden" name="page" value="delete"/>';
         $r .= '<input type="hidden" name="website_id" value="' . $args['website_id'] . '"/>';
         $r .= '<input type="hidden" name="sample:id" value="' . data_entry_helper::$entity_to_load['sample:id'] . '"/>';
         $r .= '<input type="hidden" name="sample:deleted" value="t"/>';
         $r .= '</form>';
     }
     data_entry_helper::enable_validation('sample');
     return $r;
 }
 /**
  * Return the generated form output.
  * @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 object $node The Drupal node object.
  * @param array $response When this form is reloading after saving a submission, contains the response from the service call.
  * Note this does not apply when redirecting (in this case the details of the saved object are in the $_GET data).
  * @return Form HTML.
  * @todo: Implement this method 
  */
 public static function get_form($args, $node, $response = null)
 {
     if (empty($_GET['group_id'])) {
         return 'This page needs a group_id URL parameter.';
     }
     require_once 'includes/map.php';
     require_once 'includes/groups.php';
     global $indicia_templates;
     iform_load_helpers(array('report_helper', 'map_helper'));
     $conn = iform_get_connection_details($node);
     $readAuth = report_helper::get_read_auth($conn['website_id'], $conn['password']);
     report_helper::$javascript .= "indiciaData.website_id={$conn['website_id']};\n";
     report_helper::$javascript .= "indiciaData.nodeId={$node->nid};\n";
     group_authorise_form($args, $readAuth);
     $group = data_entry_helper::get_population_data(array('table' => 'group', 'extraParams' => $readAuth + array('id' => $_GET['group_id'], 'view' => 'detail')));
     $group = $group[0];
     hostsite_set_page_title("{$group['title']}: {$node->title}");
     $actions = array();
     if (!empty($args['edit_location_path'])) {
         $actions[] = array('caption' => 'edit', 'url' => '{rootFolder}' . $args['edit_location_path'], 'urlParams' => array('group_id' => $_GET['group_id'], 'location_id' => '{location_id}'));
     }
     $actions[] = array('caption' => 'remove', 'javascript' => "remove_location_from_group({groups_location_id});");
     $leftcol = report_helper::report_grid(array('readAuth' => $readAuth, 'dataSource' => 'library/locations/locations_for_groups', 'sendOutputToMap' => true, 'extraParams' => array('group_id' => $_GET['group_id']), 'rowId' => 'location_id', 'columns' => array(array('display' => 'Actions', 'actions' => $actions, 'caption' => 'edit', 'url' => '{rootFolder}'))));
     $leftcol .= '<fieldset><legend>' . lang::Get('Add sites to the group') . '</legend>';
     $leftcol .= '<p>' . lang::get('LANG_Add_Sites_Instruct') . '</p>';
     if (!empty($args['edit_location_path'])) {
         $leftcol .= lang::get('Either') . ' <a class="button" href="' . hostsite_get_url($args['edit_location_path'], array('group_id' => $_GET['group_id'])) . '">' . lang::get('enter details of a new site') . '</a><br/>';
     }
     $leftcol .= data_entry_helper::select(array('label' => lang::get('Or, add an existing site'), 'fieldname' => 'add_existing_location_id', 'report' => 'library/locations/locations_available_for_group', 'caching' => false, 'blankText' => lang::get('<please select>'), 'valueField' => 'location_id', 'captionField' => 'name', 'extraParams' => $readAuth + array('group_id' => $_GET['group_id'], 'user_id' => hostsite_get_user_field('indicia_user_id', 0)), 'afterControl' => '<button id="add-existing">Add</button>'));
     $leftcol .= '</fieldset>';
     // @todo Link existing My Site to group. Need a new report to list sites I created, with sites already in the group
     // removed. Show in a drop down with an add button. Adding must create the groups_locations record, plus refresh
     // the grid and refresh the drop down.
     // @todo set destination after saving added site
     $map = map_helper::map_panel(iform_map_get_map_options($args, $readAuth), iform_map_get_ol_options($args));
     $r = str_replace(array('{col-1}', '{col-2}'), array($leftcol, $map), $indicia_templates['two-col-50']);
     data_entry_helper::$javascript .= "indiciaData.group_id={$_GET['group_id']};\n";
     return $r;
 }
 private static function get_template_with_map($args, $readAuth, $extraParams, $paramDefaults)
 {
     $r = '<div id="outer-with-map" class="ui-helper-clearfix">';
     $r .= '<div id="grid" class="left" style="width:65%">{paramsForm}{grid}';
     // Insert a button to verify all visible, only available if viewing the clean records.
     if (isset($_POST['verification-rule']) && $_POST['verification-rule'] === 'none' && empty($_POST['verification-id'])) {
         $r .= '<button type="button" id="btn-verify-all">' . lang::get('Verify all visible') . '</button>';
     }
     $r .= '</div>';
     $r .= '<div id="map-and-record" class="right" style="width: 34%"><div id="summary-map">';
     $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;
     $options['featureIdField'] = 'occurrence_id';
     $r .= map_helper::map_panel($options, $olOptions);
     $reportMapOpts = array('dataSource' => !empty($args['mapping_report_name']) ? $args['mapping_report_name'] : $args['report_name'], 'mode' => 'report', 'readAuth' => $readAuth, 'autoParamsForm' => false, 'extraParams' => $extraParams, 'paramDefaults' => $paramDefaults, 'reportGroup' => 'verification', 'clickableLayersOutputMode' => 'report', 'rowId' => 'occurrence_id', 'sharing' => 'verification', 'ajax' => TRUE);
     if (!empty($args['mapping_report_name_lores'])) {
         $reportMapOpts['dataSourceLoRes'] = $args['mapping_report_name_lores'];
     }
     $r .= report_helper::report_map($reportMapOpts);
     $r .= '</div>';
     global $user;
     if (function_exists('hostsite_get_user_field') && ($locationId = hostsite_get_user_field('location_expertise', false))) {
         iform_map_zoom_to_location($locationId, $readAuth);
     }
     $r .= '<div id="record-details-wrap" class="ui-widget ui-widget-content">';
     $r .= self::instructions('grid on the left');
     $r .= '<div id="record-details-content" style="display: none">';
     $r .= '<div id="record-details-toolbar">';
     $r .= '<label>Set status:</label>';
     $r .= '<button type="button" id="btn-verify">' . lang::get('Verify') . '</button>';
     $r .= '<button type="button" id="btn-reject">' . lang::get('Reject') . '</button>';
     $r .= '<button type="button" id="btn-query">' . lang::get('Query') . '</button>';
     $r .= '<button type="button" id="btn-multiple" title="' . lang::get('Select this tool to tick off a list of records and action all of the ticked records in one go') . '">' . lang::get('Select records') . '</button>';
     $r .= '<br/><label>Contact:</label>';
     $r .= '<button type="button" id="btn-email-expert" class="default-button">' . lang::get('Another expert') . '</button>';
     $r .= '<button type="button" id="btn-email-recorder" class="default-button">' . lang::get('Recorder') . '</button>';
     $r .= '</div>';
     $r .= '<div id="record-details-tabs">';
     // note - there is a dependency in the JS that comments is the last tab and images the 2nd to last.
     $r .= data_entry_helper::tab_header(array('tabs' => array('#details-tab' => lang::get('Details'), '#experience-tab' => lang::get('Experience'), '#phenology-tab' => lang::get('Phenology'), '#images-tab' => lang::get('Images'), '#comments-tab' => lang::get('Comments'))));
     data_entry_helper::$javascript .= "indiciaData.detailsTabs = ['details','experience','phenology','images','comments'];\n";
     data_entry_helper::enable_tabs(array('divId' => 'record-details-tabs'));
     $r .= '<div id="details-tab"></div>';
     $r .= self::other_tab_html();
     $r .= '</div></div></div></div></div>';
     return $r;
 }
Exemple #7
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 form output.
  * @return Form HTML.
  */
 public static function get_form($args)
 {
     require_once drupal_get_path('module', 'iform') . '/client_helpers/map_helper.php';
     $hidden = str_replace("\r\n", "\n", $args['hide_fields']);
     $hidden = explode("\n", $hidden);
     if (empty($_GET['occurrence_id'])) {
         return 'This form requires an occurrence_id parameter in the URL.';
     }
     // Get authorisation tokens to update and read from the Warehouse.
     $auth = data_entry_helper::get_read_auth($args['website_id'], $args['password']);
     data_entry_helper::load_existing_record($auth, 'occurrence', $_GET['occurrence_id']);
     data_entry_helper::load_existing_record($auth, 'sample', data_entry_helper::$entity_to_load['occurrence:sample_id']);
     $r .= "<div id=\"controls\">\n";
     $r .= "<table>\n";
     if (!in_array('Species', $hidden)) {
         $r .= "<tr><td><strong>" . lang::get('Species') . "</strong></td><td>" . data_entry_helper::$entity_to_load['occurrence:taxon'] . "</td></tr>\n";
     }
     if (!in_array('Date', $hidden)) {
         $r .= "<tr><td><strong>Date</strong></td><td>" . data_entry_helper::$entity_to_load['sample:date'] . "</td></tr>\n";
     }
     if (!in_array('Grid Reference', $hidden)) {
         $r .= "<tr><td><strong>Grid Reference</strong></td><td>" . data_entry_helper::$entity_to_load['sample:entered_sref'] . "</td></tr>\n";
     }
     $siteLabels = array();
     if (!empty(data_entry_helper::$entity_to_load['sample:location'])) {
         $siteLabels[] = data_entry_helper::$entity_to_load['sample:location'];
     }
     if (!empty(data_entry_helper::$entity_to_load['sample:location_name'])) {
         $siteLabels[] = data_entry_helper::$entity_to_load['sample:location_name'];
     }
     if (!in_array('Site', $hidden) && !empty($siteLabels)) {
         $r .= "<tr><td><strong>Site</strong></td><td>" . implode(' | ', $siteLabels) . "</td></tr>\n";
     }
     $smpAttrs = data_entry_helper::getAttributes(array('id' => data_entry_helper::$entity_to_load['sample:id'], 'valuetable' => 'sample_attribute_value', 'attrtable' => 'sample_attribute', 'key' => 'sample_id', 'extraParams' => $auth, 'survey_id' => data_entry_helper::$entity_to_load['occurrence:survey_id']));
     $occAttrs = data_entry_helper::getAttributes(array('id' => $_GET['occurrence_id'], 'valuetable' => 'occurrence_attribute_value', 'attrtable' => 'occurrence_attribute', 'key' => 'occurrence_id', 'extraParams' => $auth, 'survey_id' => data_entry_helper::$entity_to_load['occurrence:survey_id']));
     $attributes = array_merge($smpAttrs, $occAttrs);
     foreach ($attributes as $attr) {
         if (!in_array($attr['caption'], $hidden)) {
             $r .= "<tr><td><strong>" . lang::get($attr['caption']) . "</strong></td><td>" . $attr['displayValue'] . "</td></tr>\n";
         }
     }
     $r .= "</table>\n";
     $r .= "</div>\n";
     $options = iform_map_get_map_options($args, $readAuth);
     $olOptions = iform_map_get_ol_options($args);
     $options['initialFeatureWkt'] = data_entry_helper::$entity_to_load['occurrence:wkt'];
     $r .= map_helper::map_panel($options, $olOptions);
     return $r;
 }
 private static function get_template_with_map($args, $readAuth, $extraParams, $paramDefaults)
 {
     $r = '<div id="outer-with-map" class="ui-helper-clearfix">';
     $r .= '<div id="grid" class="left" style="width:65%">{paramsForm}{grid}</div>';
     $r .= '<div id="map-and-record" class="right" style="width: 34%"><div id="summary-map">';
     $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;
     $options['featureIdField'] = 'sample_id';
     $r .= map_helper::map_panel($options, $olOptions);
     $reportMapOpts = array('dataSource' => !empty($args['mapping_report_name']) ? $args['mapping_report_name'] : $args['report_name'], 'mode' => 'report', 'readAuth' => $readAuth, 'autoParamsForm' => false, 'extraParams' => $extraParams, 'paramDefaults' => $paramDefaults, 'reportGroup' => 'verification', 'clickableLayersOutputMode' => 'report', 'rowId' => 'sample_id', 'sharing' => 'verification', 'ajax' => TRUE);
     $r .= report_helper::report_map($reportMapOpts);
     $r .= '</div>';
     if (function_exists('hostsite_get_user_field') && ($locationId = hostsite_get_user_field('location_expertise', false))) {
         iform_map_zoom_to_location($locationId, $readAuth);
     }
     $r .= '<div id="record-details-wrap" class="ui-widget ui-widget-content">';
     $r .= self::instructions('grid on the left');
     $r .= '<div id="record-details-content" style="display: none">';
     $r .= '<div id="record-details-toolbar">';
     $r .= '<div id="action-buttons">';
     $r .= '<div id="action-buttons-status" class="action-buttons-row">';
     $r .= '<div class="col-1"><label>' . lang::get('Set status:') . '</label></div>';
     $imgPath = empty(data_entry_helper::$images_path) ? data_entry_helper::relative_client_helper_path() . "../media/images/" : data_entry_helper::$images_path;
     $r .= self::status_buttons($imgPath);
     $r .= '</div>';
     $r .= '<div id="action-buttons-other" class="action-buttons-row"><div class="col-1"><label>Other actions:</label></div>';
     $r .= self::other_action_buttons($imgPath);
     $r .= '</div></div>';
     $r .= '<div id="record-details-tabs">';
     // note - there is a dependency in the JS that comments is the last tab and media the 2nd to last.
     $r .= data_entry_helper::tab_header(array('tabs' => array('#details-tab' => lang::get('Details'), '#media-tab' => lang::get('Media'), '#comments-tab' => lang::get('Comments'))));
     data_entry_helper::$javascript .= "indiciaData.detailsTabs = ['details','media','comments'];\n";
     data_entry_helper::enable_tabs(array('divId' => 'record-details-tabs'));
     $r .= '<div id="details-tab"></div>';
     $r .= self::other_tab_html();
     $r .= '</div></div></div></div></div>';
     return $r;
 }
 /**
  * Draw Map section of the page.
  * @return string The output map panel.
  * 
  * @package    Client
  * @subpackage PrebuiltForms
  */
 protected static function get_control_map($auth, $args, $tabalias, $options)
 {
     iform_load_helpers(array('map_helper', 'data_entry_helper'));
     global $user;
     // setup the map options
     $options = iform_map_get_map_options($args, $auth['read']);
     if ($args['interface'] !== 'one_page') {
         $options['tabDiv'] = $tabalias;
     }
     $olOptions = iform_map_get_ol_options($args);
     $url = map_helper::$geoserver_url . 'wms';
     // Get the style if there is one selected
     $style = $args["wms_style"] ? ", styles: '" . $args["wms_style"] . "'" : '';
     map_helper::$onload_javascript .= "\n    var filter='website_id=" . $args['website_id'] . "';";
     $layerTitle = str_replace('{species}', self::get_best_name(), $args['layer_title']);
     map_helper::$onload_javascript .= "\n    filter += ' AND taxon_meaning_id=" . self::$taxon_meaning_id . "';\n";
     if ($args['cql_filter']) {
         map_helper::$onload_javascript .= "\n    filter += ' AND(" . str_replace("'", "\\'", $args['cql_filter']) . ")';\n";
     }
     $layerTitle = str_replace("'", "\\'", $layerTitle);
     map_helper::$onload_javascript .= "\n    var distLayer = new OpenLayers.Layer.WMS(\n      '" . $layerTitle . "',\n      '{$url}',\n      {layers: '" . $args["wms_feature_type"] . "', transparent: true, CQL_FILTER: filter {$style}},\n      {isBaseLayer: false, sphericalMercator: true, singleTile: true}\n    );\n";
     $options['layers'][] = 'distLayer';
     // This is not a map used for input
     $options['editLayer'] = false;
     // if in Drupal, and IForm proxy is installed, then use this path as OpenLayers proxy
     if (defined('DRUPAL_BOOTSTRAP_CONFIGURATION') && module_exists('iform_proxy')) {
         global $base_url;
         $options['proxy'] = $base_url . '?q=' . variable_get('iform_proxy_path', 'proxy') . '&url=';
     }
     // output a legend
     if (isset($args['include_layer_list_types'])) {
         $layerTypes = explode(',', $args['include_layer_list_types']);
     } else {
         $layerTypes = array('base', 'overlay');
     }
     $r = '<div class="detail-panel" id="detail-panel-map"><h3>' . lang::get('Map') . '</h3>';
     //Legend options set by the user
     if (!isset($args['include_layer_list']) || $args['include_layer_list']) {
         $r .= map_helper::layer_list(array('includeSwitchers' => isset($args['include_layer_list_switchers']) ? $args['include_layer_list_switchers'] : true, 'includeHiddenLayers' => true, 'layerTypes' => $layerTypes));
     }
     $r .= map_helper::map_panel($options, $olOptions);
     $r .= '</div>';
     // Set up a page refresh for dynamic update of the map at set intervals
     if ($args['refresh_timer'] !== 0 && is_numeric($args['refresh_timer'])) {
         // is_int prevents injection
         if (isset($args['load_on_refresh']) && !empty($args['load_on_refresh'])) {
             map_helper::$javascript .= "setTimeout('window.location=\"" . $args['load_on_refresh'] . "\";', " . $args['refresh_timer'] . "*1000 );\n";
         } else {
             map_helper::$javascript .= "setTimeout('window.location.reload( false );', " . $args['refresh_timer'] . "*1000 );\n";
         }
     }
     return $r;
 }
 /**
  * Return the generated form output.
  * @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 object $node The Drupal node object.
  * @param array $response When this form is reloading after saving a submission, contains the response from the service call.
  * Note this does not apply when redirecting (in this case the details of the saved object are in the $_GET data).
  * @return Form HTML.
  * @todo: Implement this method 
  */
 public static function get_form($args, $node, $response = null)
 {
     iform_load_helpers(array('report_helper', 'map_helper'));
     $conn = iform_get_connection_details($node);
     $readAuth = report_helper::get_read_auth($conn['website_id'], $conn['password']);
     $r = '<div id="leftcol">';
     $reportOptions = iform_report_get_report_options($args, $readAuth);
     iform_report_apply_explore_user_own_preferences($reportOptions);
     $reportOptions = array_merge(array('rowId' => 'external_key', 'columns' => array(), 'callback' => 'grid_load', 'rememberParamsReportGroup' => 'explore', 'paramsFormButtonCaption' => lang::get('Filter')), $reportOptions);
     $reportOptions['rowId'] = 'external_key';
     $imgPath = empty(report_helper::$images_path) ? report_helper::relative_client_helper_path() . "../media/images/" : report_helper::$images_path;
     $reportOptions['columns'][] = array('actions' => array(array('img' => "{$imgPath}/add.png", 'caption' => 'Click to add this species to the map')));
     $r .= report_helper::report_grid($reportOptions);
     $r .= '</div>';
     $args['indicia_species_layer_slds'] = report_helper::explode_lines($args['indicia_species_layer_slds']);
     $r .= '<div id="rightcol">';
     $r .= '<div id="layerbox">';
     $r .= '<p id="instruct">' . lang::get('Click on the + buttons in the grid to add species layers to the map. You can add up to {1} layers at a time.', count($args['indicia_species_layer_slds']));
     $r .= '<p id="instruct2" style="display: none">' . lang::get('Use the - buttons to permanently remove layers, or untick the box in the legend to temporarily hide them.');
     $mapOptions = iform_map_get_map_options($args, $readAuth);
     $mapOptions['clickForSpatialRef'] = false;
     $olOptions = iform_map_get_ol_options($args, $readAuth);
     $r .= map_helper::layer_list(array('layerTypes' => array('overlay'), 'includeSwitchers' => true, 'includeHiddenLayers' => true));
     $r .= '</div>';
     $r .= map_helper::map_panel($mapOptions, $olOptions);
     $r .= '</div>';
     $websiteIds = iform_get_allowed_website_ids($readAuth);
     if (!empty($args['indicia_species_layer_feature_type']) && !empty(report_helper::$geoserver_url)) {
         $training = function_exists('hostsite_get_user_field') && hostsite_get_user_field('training') ? 't' : 'f';
         $cql = 'website_id IN (' . implode(',', $websiteIds) . ') AND ' . $args['indicia_species_layer_filter_field'] . "='{filterValue}' AND record_status NOT IN ('R', 'I', 'T') AND training='{$training}'";
         if (isset($_POST[$reportOptions['reportGroup'] . '-quality'])) {
             $quality = $_POST[$reportOptions['reportGroup'] . '-quality'];
         } else {
             $quality = $reportOptions['extraParams']['quality'];
         }
         // logic here must match the quality_check function logic on the database.
         switch ($quality) {
             case 'V':
                 $cql .= " AND record_status='V'";
                 break;
             case 'C':
                 $cql .= " AND (record_status='V' OR certainty='C')";
                 break;
             case 'L':
                 $cql .= " AND (record_status='V' OR ((certainty <> 'U' OR certainty IS NULL) AND record_status <> 'D'))";
                 break;
             case '!D':
                 $cql .= " AND record_status<>'D'";
                 break;
             case '!R':
                 // nothing to add - rejects are always excluded
         }
         report_helper::$javascript .= "indiciaData.indiciaSpeciesLayer = {\n" . '  "title":"' . lang::get('{1}') . "\",\n" . '  "myRecords":"' . lang::get('my records') . "\",\n" . '  "userId":"' . hostsite_get_user_field('indicia_user_id') . "\",\n" . '  "featureType":"' . $args['indicia_species_layer_feature_type'] . "\",\n" . '  "wmsUrl":"' . data_entry_helper::$geoserver_url . "wms\",\n" . "  \"cqlFilter\":\"{$cql}\",\n" . "  \"filterField\":\"taxon_meaning_id\",\n" . '  "slds":' . json_encode($args['indicia_species_layer_slds']) . "\n" . "};\n";
     }
     return $r;
 }
    }
    switch ($attr['data_type']) {
        case 'D':
        case 'V':
            echo data_entry_helper::date_picker(array('label' => $attr['caption'], 'fieldname' => $name, 'default' => $attr['value']));
            break;
        case 'L':
            echo data_entry_helper::select(array('label' => $attr['caption'], 'fieldname' => $name, 'default' => $attr['raw_value'], 'lookupValues' => $values['terms_' . $attr['termlist_id']], 'blankText' => '<Please select>'));
            break;
        case 'B':
            echo data_entry_helper::checkbox(array('label' => $attr['caption'], 'fieldname' => $name, 'default' => $attr['value']));
            break;
        case 'G':
            echo '<input type="hidden" name="' . $name . '" value="' . $attr['value'] . '" id="imp-geom"/>';
            echo '<label>' . $attr['caption'] . ':</label>';
            echo map_helper::map_panel(array('presetLayers' => array('osm'), 'editLayer' => true, 'clickForSpatialRef' => false, 'layers' => array(), 'initial_lat' => 55, 'initial_long' => -2, 'initial_zoom' => 4, 'width' => 870, 'height' => 400, 'standardControls' => array('panZoomBar', 'layerSwitcher', 'hoverFeatureHighlight', 'drawPolygon', 'modifyFeature', 'clearEditLayer')));
            break;
        default:
            echo data_entry_helper::text_input(array('label' => $attr['caption'], 'fieldname' => $name, 'default' => $attr['value']));
    }
}
?>
 </ol>
 </fieldset>
<?php 
// some script to handle drawn polygons. Only allow 1 polygon on the layer
data_entry_helper::$javascript .= "mapInitialisationHooks.push(function(div) {\n  function featureChangeEvent(evt) {\n    var featuresToRemove=[];\n    \$.each(evt.feature.layer.features, function(idx, feature) {\n      if (feature.id !== evt.feature.id) {\n        featuresToRemove.push(feature);\n      }\n    });\n    evt.feature.layer.removeFeatures(featuresToRemove);\n    \$('#imp-geom').val(evt.feature.geometry.toString());\n  }\n  div.map.editLayer.events.on({'featureadded': featureChangeEvent, 'afterfeaturemodified': featureChangeEvent}); \n});\n";
echo html::form_buttons(html::initial_value($values, 'taxa_taxon_list:id') != null);
data_entry_helper::$dumped_resources[] = 'jquery';
data_entry_helper::$dumped_resources[] = 'jquery_ui';
data_entry_helper::$dumped_resources[] = 'fancybox';
 /**
  * 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)
 {
     $r = "";
     data_entry_helper::add_resource('jquery_ui');
     if (isset($args['advancedUI']) && $args['advancedUI']) {
         // TODO Sort out
         //    	data_entry_helper::$resource_list['jquery_ui_slider'] =
         //    		array('deps' => array('jquery_ui'), 'javascript' => array('/misc/ui/jquery.ui.slider.js'));
         //    	data_entry_helper::add_resource('jquery_ui_slider');
         //      drupal_add_js(drupal_get_path('module', 'jquery_update') .'/replace/ui/ui/jquery.ui.slider.js');
         //      drupal_add_js('/misc/ui/jquery.ui.slider.min.js');
         drupal_add_js('/misc/ui/jquery.ui.slider.js');
         //      drupal_add_js('/misc/ui/jquery.ui.button.min.js');
     }
     $readAuth = data_entry_helper::get_read_auth($args['website_id'], $args['password']);
     $now = new DateTime('now');
     $year = isset($_REQUEST['year']) ? $_REQUEST['year'] : ($year = $now->format('Y'));
     iform_load_helpers(array('report_helper', 'map_helper'));
     $options = iform_report_get_report_options($args, $readAuth);
     $currentParamValues = array();
     if (isset($options['extraParams'])) {
         foreach ($options['extraParams'] as $key => $value) {
             // trim data to ensure blank lines are not handled.
             $key = trim($key);
             $value = trim($value);
             // We have found a parameter, so put it in the request to the report service
             if (!empty($key)) {
                 $currentParamValues[$key] = $value;
             }
         }
     }
     $extras = '&wantColumns=1&wantParameters=1&' . report_helper::array_to_query_string($currentParamValues, true);
     $canIDuser = false;
     // Report record should have location_id, sample_id, occurrence_id, sample_date, species ttl_id, attributes, geometry. created_by_id is optional
     // Event definition: Name|attribute_id|attribute_values
     // Loop through event definitions
     /*    $events = array(array('type'=>'arrayVal', 'name'=>'Budburst', 'attr'=>'289', 'values'=>array(3904,3961,3905,3906,3962,3907)),
           array('type'=>'arrayVal', 'name'=>'Leaf', 'attr'=>'289', 'values'=>array(3906,3962,3907)),
           array('type'=>'arrayVal', 'name'=>'Flowering', 'attr'=>'291', 'values'=>array(3912,3913,3914,3916,3917,3918)),
           array('type'=>'presence', 'name'=>'Presence')); */
     $events = str_replace("\r\n", "\n", $args['triggerEvents']);
     $events = str_replace("\r", "\n", $events);
     $events = explode("\n", trim($events));
     foreach ($events as $idx => $event) {
         $events[$idx] = explode(':', $event);
     }
     $triggerEvents = array();
     $SpeciesEventSelections = array();
     $Species = array();
     $r .= '<div id="errorMsg"></div>' . '<table class="ui-widget ui-widget-content ui-corner-all controls-table" id="controls-table">' . '<thead class="ui-widget-header">' . '<tr><th><label for="yearControl">' . lang::get("Year") . ' : </label><select id="yearControl" name="year">';
     for ($i = $now->format('Y'); $i >= $args['first_year']; $i--) {
         $r .= '<option value="' . $i . '">' . $i . '</option>';
     }
     $r .= '</select></th>' . '<th><label for="speciesControl">' . lang::get("Species") . ' : </label><select id="speciesControl"><option value="">' . lang::get("Please select species") . '</option></select></th>' . '<th><label for="eventControl">' . lang::get("Event") . ' : </label><select id="eventControl"><option value="">' . lang::get("Please select event") . '</option>';
     foreach ($events as $index => $event) {
         $r .= '<option value="' . $index . '">' . $event[0] . '</option>';
         $triggerEvents[] = '{"name":"' . $event[0] . '","type":"' . $event[1] . '"' . (count($event) > 2 ? ',"attr":' . $event[2] . ',"values":[' . $event[3] . ']' : '') . '}';
     }
     $r .= "</select></th>\n";
     if (isset($args['twinMaps']) && $args['twinMaps']) {
         $r .= '<th><label for="rhsCtrl">' . lang::get("Compare") . ' : </label><select id="rhsCtrl" name="rhsCtrl"><option value="">' . lang::get("Please select.") . '</option><option value="Test">' . lang::get("Test.") . "</option></select></th>\n";
     }
     $r .= '</tr></thead></table>' . "\n";
     $args['map_width'] = "auto";
     $options = iform_map_get_map_options($args, $readAuth);
     $olOptions = iform_map_get_ol_options($args);
     $options['editLayer'] = false;
     $options['clickForSpatialRef'] = false;
     $options['scroll_wheel_zoom'] = false;
     $r .= '<div class="leftMap mapContainers leftMapOnly">' . map_helper::map_panel($options, $olOptions) . '</div>';
     $options['divId'] = 'map2';
     if (isset($args['twinMaps']) && $args['twinMaps']) {
         $r .= '<div class="rightMap mapContainers leftMapOnly">' . map_helper::map_panel($options, $olOptions) . '</div>';
     }
     $r .= '<div class="ui-helper-clearfix"></div><div id="timeControls">' . (isset($args['advancedUI']) && $args['advancedUI'] ? '<div id="timeSlider"></div>' : '') . '<div id="toolbar">' . '<span id="dotControlLabel">' . lang::get('Dot Size') . ' :</span>' . (isset($args['advancedUI']) && $args['advancedUI'] ? '<div id="dotSlider"></div>' : '<select id="dotSelect"><option>2</option><option>3</option><option>4</option><option>5</option></select>') . '<button id="beginning">go to beginning</button><button id="playMap">play</button><button id="end">go to end</button>' . '<span id="dateControlLabel">' . lang::get("Date Currently displayed") . ' : ' . (isset($args['advancedUI']) && $args['advancedUI'] ? '<span id="displayDate" ></span>' : '<select id="timeSelect"><option value="">' . lang::get("Please select date") . '</option></select>') . '</span>' . '</div>';
     $imgPath = empty(data_entry_helper::$images_path) ? data_entry_helper::relative_client_helper_path() . "../media/images/" : data_entry_helper::$images_path;
     data_entry_helper::$javascript .= "\ninitTreeMap2({\n  advanced_UI: " . (isset($args['advancedUI']) && $args['advancedUI'] ? "true" : "false") . ",\n  dotSize: " . $args['dotSize'] . ",\n  lat: " . $args['map_centroid_lat'] . ",\n  long: " . $args['map_centroid_long'] . ",\n  zoom: " . $args['map_zoom'] . ",\n  triggerEvents: [" . implode(',', $triggerEvents) . "],\n  base_url: '" . data_entry_helper::$base_url . "',\n  report_name: '" . $args['report_name'] . "',\n  auth_token: '" . $readAuth['auth_token'] . "',\n  nonce: '" . $readAuth['nonce'] . "',\n  reportExtraParams: '" . $extras . "',\n  indicia_user_id: " . (hostsite_get_user_field('indicia_user_id') ? hostsite_get_user_field('indicia_user_id') : 'false') . ",\n  timeControlSelector: '" . (isset($args['advancedUI']) && $args['advancedUI'] ? '#timeSlider' : '#timeSelect') . "',\n  dotControlSelector: '" . (isset($args['advancedUI']) && $args['advancedUI'] ? '#dotSlider' : '#dotSelect') . "',\n  timerDelay: " . (int) 1000 / $args['frameRate'] . ",\n  twinMaps: " . (isset($args['twinMaps']) && $args['twinMaps'] ? 'true' : 'false') . ",\n  imgPath: '" . $imgPath . "'\n});\n";
     $r .= '</div>';
     return $r;
 }
 private static function get_template_grid_left($args, $auth)
 {
     $r .= '<div id="outer" class="ui-helper-clearfix">';
     $r .= '<div id="grid" class="left">{grid}</div>';
     $r .= '<div id="record-details-wrap" class="right ui-widget ui-widget-content">';
     $r .= '<div id="click-record-notice">' . t('Click on a record to view the details') . '</div>';
     $r .= '<div id="record-details-content" style="display: none">';
     $r .= '<div id="record-details-toolbar">';
     $r .= '<button type="button" id="btn-verify">' . lang::get('Verify') . '</button>';
     $r .= '<button type="button" id="btn-reject">' . lang::get('Reject') . '</button>';
     $r .= '<button type="button" id="btn-email" class="default-button">' . lang::get('Email') . '</button>';
     $r .= '</div>';
     $r .= '<div id="record-details-tabs">';
     $r .= data_entry_helper::tab_header(array('tabs' => array('#details-tab' => 'Details', '#map-tab' => 'Map', '#images-tab' => 'Images', '#comments-tab' => 'Comments')));
     data_entry_helper::enable_tabs(array('divId' => 'record-details-tabs'));
     $r .= '<div id="details-tab"></div>';
     $r .= '<div id="map-tab">';
     $options = iform_map_get_map_options($args, $auth);
     $options['tabDiv'] = 'map-tab';
     $r .= map_helper::map_panel($options, iform_map_get_ol_options($args));
     $r .= '</div>';
     $r .= '<div id="images-tab"></div>';
     $r .= '<div id="comments-tab"></div>';
     $r .= '</div></div></div></div>';
     return $r;
 }
Exemple #15
0
 /**
  * Outputs a map panel.
  * The map panel can be augmented by adding any of the following controls which automatically link themselves
  * to the map:
  * <ul>
  * <li>{@link sref_textbox()}</li>
  * <li>{@link sref_system_select()}</li>
  * <li>{@link sref_and_system()}</li>
  * <li>{@link georeference_lookup()}</li>
  * <li>{@link location_select()}</li>
  * <li>{@link location_autocomplete()}</li>
  * <li>{@link postcode_textbox()}</li>
  * </ul>
  * To run JavaScript at the end of map initialisation, add a function to the global array
  * called mapInitialisationHooks. Code cannot access the map at any previous point because
  * maps may not be initialised when the page loads, e.g. if the map initialisation is
  * delayed until the tab it is on is shown.
  * To run JavaScript which updates any of the map settings, add a function to the
  * mapSettingsHooks global array. For example this is used to configure the map by report
  * parameters panels which need certain tools on the map.
  * @param array $options Associative array of options to pass to the jQuery.indiciaMapPanel plugin.
  * Has the following possible options:
  * <ul><li><b>indiciaSvc</b><br/>
  * </li>
  * <li><b>indiciaGeoSvc</b><br/>
  * </li>
  * <li><b>readAuth</b><br/>
  * </li>
  * <li><b>height</b><br/>
  * </li>
  * <li><b>width</b><br/>
  * </li>
  * <li><b>initial_lat</b><br/>
  * Latitude of the centre of the initially displayed map, using WGS84.
  * </li>
  * <li><b>initial_long</b><br/>
  * Longitude of the centre of the initially displayed map, using WGS84.
  * </li>
  * <li><b>initial_zoom</b><br/>
  * </li>
  * <li><b>scroll_wheel_zoom</b><br/>
  * </li>
  * <li><b>proxy</b><br/>
  * </li>
  * <li><b>displayFormat</b><br/>
  * </li>
  * <li><b>presetLayers</b><br/>
  * </li>
  * <li><b>tilecacheLayers</b><br/>
  * Array of layer definitions for tilecaches, which are pre-cached background tiles. They are less flexible but much faster
  * than typical WMS services. The array is associative, with the following keys:
  *   caption - The display name of the layer
  *   servers - array list of server URLs for the cache
  *   layerName - the name of the layer within the cache
  *   settings - any other settings that need to be passed to the tilecache, e.g. the server resolutions or file format.</li>
  * <li><b>indiciaWMSLayers</b><br/>
  * </li>
  * <li><b>indiciaWFSLayers</b><br/>
  * </li>
  * <li><b>layers</b><br/>
  * An array of JavaScript variables which point to additional OpenLayers layer objects to add to the map. The JavaScript for creating these layers 
  * can be added to data_entry_helper::$onload_javascript before calling the map_panel method.
  * </li>
  * <li><b>clickableLayers</b><br/>
  * If support for clicking on a layer to provide info on the clicked objects is required, set this to an array containing the JavaScript variable
  * names for the OpenLayers WMS layer objects you have created for the clickable layers. The JavaScript for creating these layers 
  * can be added to data_entry_helper::$onload_javascript before calling the map_panel method and they can be the same layers as those referred to in 
  * the layers parameter.
  * </li>
  * <li><b>clickableLayersOutputDiv</b><br/>
  * If this is set to the name of a div, then clicking on a clickable layer item outputs the details into this div rather than a popup.
  * </li>
  * <li><b>clickableLayersOutputColumns</b><br/>
  * An associated array of column field names with column titles as the values which defines the columns that are output when clicking on a data point. 
  * If ommitted, then all columns are output using their original field names.
  * </li>
  * <li><b>clickableLayersOutputFn</b><br/>
  * Allows overridding of the appearance of the output when clicking on the map for WMS or vector layers. Should be set to a JavaScript function name 
  * which takes a list of features and the map div as parameters, then returns the HTML to output.</li>
  * <li><b>locationLayerName</b><br/>
  * If using a location select or autocomplete control, then set this to the name of a feature type exposed on GeoServer which contains the id, name and boundary
  * geometry of each location that can be selected. Then when the user clicks on the map the system is able to automatically populate the locations control with the 
  * clicked on location. Ensure that the feature type is styled on GeoServer to appear as required, though it will be added to the map with semi-transparency. To use
  * this feature ensure that a proxy is set, e.g. by using the Indicia Proxy module in Drupal.
  * </li>
  * <li><b>controls</b><br/>
  * </li>
  * <li><b>toolbarDiv</b><br/>
  * If set to 'map' then any required toolbuttons are output directly onto the map canvas (in the top right corner). Alternatively can be set to 'top',
  * 'bottom' or the id of a div on the page to output them into.
  * </li>
  * <li><b>toolbarPrefix</b><br/>
  * Content to include at the beginning of the map toolbar. Not applicable when the toolbar is added directly to the map.
  * </li>
  * <li><b>toolbarSuffix</b><br/>
  * Content to include at the end of the map toolbar. Not applicable when the toolbar is added directly to the map.
  * </li>
  * <li><b>editLayer</b><br/>
  * </li>
  * <li><b>editLayerName</b><br/>
  * </li>
  * <li><b>standardControls</b>
  * An array of predefined controls that are added to the map. Select from:<br/>
  *    layerSwitcher - a button in the corner of the map which opens a panel allowing selection of the visible layers.<br/>
  *    drawPolygon - a tool for drawing polygons onto the map edit layer.<br/>
  *    drawLine - a tool for drawing lines onto the map edit layer.<br/>
  *    drawPoint - a tool for drawing points onto the map edit layer.<br/>
  *    zoomBox - allow zooming to a bounding box, drawn whilst holding the shift key down. This functionality is provided by the panZoom and panZoomBar controls as well
  *    so is only relevant when they are not selected. 
  *    panZoom - simple controls in the corner of the map for panning and zooming.
  *    panZoomBar - controls in the corner of the map for panning and zooming, including a slide bar for zooming.
  *    modifyFeature - a tool for selecting a feature on the map edit layer then editing the vertices of the feature.
  *    selectFeature - a tool for selecting a feature on the map edit layer.
  *    hoverFeatureHighlight - highlights the feature on the map edit layer which is under the mouse cursor position.
  * Default is layerSwitcher, panZoom and graticule.
  * </li>
  * <li><b>initialFeatureWkt</b><br/>
  * </li>
  * <li><b>defaultSystem</b><br/>
  * </li>
  * <li><b>latLongFormat</b><br/>
  * Override the format for display of lat long references. Select from D (decimal degrees, the default), DM (degrees and decimal minutes)
  * or DMS (degrees, minutes and decimal seconds).</li>
  * <li><b>srefId</b><br/>
  * Override the id of the control that has the grid reference value
  * </li>
  * <li><b>srefSystemId</b><br/>
  * Override the id of the control that has the spatial reference system value
  * </li>
  * <li><b>geomId</b><br/>
  * </li>
  * <li><b>clickedSrefPrecisionMin</b><br/>
  * Specify the minimum precision allowed when clicking on the map to get a grid square. If not set then the grid square selected will increase to its maximum
  * size as the map is zoomed out. E.g. specify 4 for a 1km British National Grid square.
  * </li>
  * <li><b>clickedSrefPrecisionMax</b><br/>
  * Specify the maximum precision allowed when clicking on the map to get a grid square. If not set then the grid square selected will decrease to its minimum
  * size as the map is zoomed in. E.g. specify 4 for a 1km British National Grid square.
  * </li>
  * <li><b>msgGeorefSelectPlace</b><br/>
  * </li>
  * <li><b>msgGeorefNothingFound</b><br/>
  * </li>
  * <li><b>msgSrefOutsideGrid</b><br/>
  * Message displayed when point outside of grid reference range is clicked.
  * </li>
  * <li><b>msgSrefNotRecognised</b><br/>
  * Message displayed when a grid reference is typed that is not recognised.
  * </li>
  * <li><b>maxZoom</b><br/>
  * Limit the maximum zoom used when clicking on the map to set a point spatial reference. Use this to prevent over zooming on
  * background maps.</li>
  * <li><b>tabDiv</b><br/>
  * If loading this control onto a set of tabs, specify the tab control's div ID here. This allows the control to
  * automatically generate code which only generates the map when the tab is shown.</li>
  * <li><b>setupJs</b><br/>
  * When there is JavaScript to run before the map is initialised, put the JavaScript into this option. This allows the map to run the 
  * setup JavaScript just in time, immediately before the map is created. This avoids problems where the setup JavaScript causes the OpenLayers library 
  * to be initialised too earlier if the map is on a div.</li>
  * <li><b>setupJs</b><br/>
  * When there is JavaScript to run before the map is initialised, put the JavaScript into this option. This allows the map to run the 
  * setup JavaScript just in time, immediately before the map is created. This avoids problems where the setup JavaScript causes the OpenLayers library 
  * to be initialised too earlier if the map is on a div.</li>
  * <li><b>graticuleProjection</b><br/>
  * EPSG code (including EPSG:) for the projection used for the graticule (grid overlay).</li>
  * <li><b>graticuleBounds</b><br/>
  * Array of the bounding box coordinates for the graticule(W,S,E,N).</li>
  * <li><b>rememberPos</b><br/>
  * Set to true to enable restoring the map position when the page is reloaded. Requires jquery.cookie plugin.</li>
  * </ul>
  * @param array $olOptions Optional array of settings for the OpenLayers map object. If overriding the projection or
  * displayProjection settings, just pass the EPSG number, e.g. 27700.
  */
 public static function map_panel($options, $olOptions = null)
 {
     if (!$options) {
         return '<div class="error">Form error. No options supplied to the map_panel method.</div>';
     } else {
         global $indicia_templates;
         $presetLayers = array();
         // If the caller has not specified the background layers, then default to the ones we have an API key for
         if (!array_key_exists('presetLayers', $options)) {
             if (parent::$multimap_api_key != '') {
                 $defaultLayers[] = 'multimap_landranger';
             }
             $presetLayers[] = 'google_satellite';
             $presetLayers[] = 'google_hybrid';
             $presetLayers[] = 'google_physical';
             // Fallback as we don't need a key for this.
             $presetLayers[] = 'virtual_earth';
         }
         $options = array_merge(array('indiciaSvc' => self::$base_url, 'indiciaGeoSvc' => self::$geoserver_url, 'divId' => 'map', 'class' => '', 'width' => 600, 'height' => 470, 'presetLayers' => $presetLayers, 'jsPath' => self::$js_path), $options);
         // When using tilecache layers, the open layers defaults cannot be used. The caller must take control of openlayers settings
         if (isset($options['tilecacheLayers'])) {
             $options['useOlDefaults'] = false;
         }
         //width and height may be numeric, which is interpreted as pixels, or a css string, e.g. '50%'
         //width in % is causing problems with panning in Firefox currently. 13/3/2010.
         if (is_numeric($options['height'])) {
             $options['height'] .= 'px';
         }
         if (is_numeric($options['width'])) {
             $options['width'] .= 'px';
         }
         if (array_key_exists('readAuth', $options)) {
             // Convert the readAuth into a query string so it can pass straight to the JS class.
             $options['readAuth'] = '&' . self::array_to_query_string($options['readAuth']);
             str_replace('&', '&amp;', $options['readAuth']);
         }
         // Autogenerate the links to the various mapping libraries as required
         if (array_key_exists('presetLayers', $options)) {
             foreach ($options['presetLayers'] as $layer) {
                 $a = explode('_', $layer);
                 $a = strtolower($a[0]);
                 switch ($a) {
                     case 'google':
                         self::add_resource('googlemaps');
                         break;
                     case 'multimap':
                         self::add_resource('multimap');
                         break;
                     case 'virtual':
                     case 'bing':
                         self::add_resource('virtualearth');
                         break;
                 }
             }
         }
         // This resource has a dependency on the googlemaps resource so has to be added afterwards.
         self::add_resource('indiciaMapPanel');
         if (array_key_exists('standardControls', $options)) {
             if (in_array('graticule', $options['standardControls'])) {
                 self::add_resource('graticule');
             }
             if (in_array('clearEditLayer', $options['standardControls'])) {
                 self::add_resource('clearLayer');
             }
         }
         // We need to fudge the JSON passed to the JavaScript class so it passes any actual layers, functions
         // and controls, not the string class names.
         $json_insert = '';
         $js_entities = array('controls', 'layers', 'clickableLayers');
         foreach ($js_entities as $entity) {
             if (array_key_exists($entity, $options)) {
                 $json_insert .= ',"' . $entity . '":[' . implode(',', $options[$entity]) . ']';
                 unset($options[$entity]);
             }
         }
         // Same for 'clickableLayersOutputFn'
         if (isset($options['clickableLayersOutputFn'])) {
             $json_insert .= ',"clickableLayersOutputFn":' . $options['clickableLayersOutputFn'];
             unset($options['clickableLayersOutputFn']);
         }
         // make a copy of the options to pass into JavaScript, with a few entries removed.
         $jsoptions = array_merge($options);
         unset($jsoptions['setupJs']);
         unset($jsoptions['tabDiv']);
         if (isset(self::$bing_api_key)) {
             $jsoptions['bing_api_key'] = self::$bing_api_key;
         }
         $json = substr(json_encode($jsoptions), 0, -1) . $json_insert . '}';
         if ($olOptions) {
             $json .= ',' . json_encode($olOptions);
         }
         $javascript = '';
         $mapSetupJs = '';
         if (isset($options['setupJs'])) {
             $mapSetupJs .= $options['setupJs'] . "\n";
         }
         $mapSetupJs .= "jQuery('#" . $options['divId'] . "').indiciaMapPanel({$json});\n";
         // If the map is displayed on a tab, so we must only generate it when the tab is displayed as creating the
         // map on a hidden div can cause problems. Also, the map must not be created until onload or later. So
         // we have to set use the mapTabLoaded and windowLoaded to track when these events are fired, and only
         // load the map when BOTH the events have fired.
         if (isset($options['tabDiv'])) {
             $javascript .= "var tabHandler = function(event, ui) { \n";
             $javascript .= "  if (ui.panel.id=='" . $options['tabDiv'] . "') {\n";
             $javascript .= "    indiciaData.mapTabLoaded=true;\n";
             $javascript .= "    if (indiciaData.windowLoaded) {\n      ";
             $javascript .= $mapSetupJs;
             $javascript .= "    }\n    \$(this).unbind(event);\n";
             $javascript .= "  }\n\n};\n";
             $javascript .= "jQuery(jQuery('#" . $options['tabDiv'] . "').parent()).bind('tabsshow', tabHandler);\n";
             // Insert this script at the beginning, because it must be done before the tabs are initialised or the
             // first tab cannot fire the event
             self::$javascript = $javascript . self::$javascript;
             self::$onload_javascript .= "if (typeof indiciaData.mapTabLoaded!==\"undefined\") {\n{$mapSetupJs}\n}\n";
         } else {
             self::$onload_javascript .= $mapSetupJs;
         }
         return self::apply_template('map_panel', $options);
     }
 }
 protected static function get_control_map($auth, $args, $tabalias, $options)
 {
     iform_load_helpers(array('map_helper', 'report_helper'));
     // $_GET data for standard params can override displayed location
     if (isset($_GET['filter-location_id']) || isset($_GET['filter-indexed_location_id'])) {
         $args['display_user_profile_location'] = false;
         if (!empty($_GET['filter-indexed_location_id'])) {
             $args['location_boundary_id'] = $_GET['filter-indexed_location_id'];
         } elseif (!empty($_GET['filter-location_id'])) {
             $args['location_boundary_id'] = $_GET['filter-location_id'];
         }
     }
     // allow us to call iform_report_get_report_options to get a default report setup, then override report_name
     $args['report_name'] = '';
     $sharing = empty($args['sharing']) ? 'reporting' : $args['sharing'];
     $reportOptions = array_merge(iform_report_get_report_options($args, $auth['read']), array('reportGroup' => 'dynamic', 'autoParamsForm' => false, 'sharing' => $sharing, 'readAuth' => $auth['read'], 'dataSource' => $options['dataSource'], 'reportGroup' => 'dynamic', 'rememberParamsReportGroup' => 'dynamic', 'clickableLayersOutputMode' => 'report', 'rowId' => 'occurrence_id', 'ajax' => TRUE), $options);
     if (self::$applyUserPrefs) {
         iform_report_apply_explore_user_own_preferences($reportOptions);
     }
     $r = report_helper::report_map($reportOptions);
     $options = array_merge(iform_map_get_map_options($args, $auth['read']), array('featureIdField' => 'occurrence_id', 'clickForSpatialRef' => false, 'reportGroup' => 'explore', 'toolbarDiv' => 'top'), $options);
     $olOptions = iform_map_get_ol_options($args);
     $r .= map_helper::map_panel($options, $olOptions);
     return $r;
 }
 /**
  * Outputs a map panel.
  * @param array $options Refer to map_helper::map_panel documentation.
  * @param array $olOptions Refer to map_helper::map_panel documentation.
  * @deprecated Use map_helper::map_panel instead.
  */
 public static function map_panel($options, $olOptions = null)
 {
     require_once 'map_helper.php';
     return map_helper::map_panel($options, $olOptions);
 }
 private static function _build_sites_report($args, $readAuth, $output, $type, $mySites)
 {
     $r = self::filter_toolbar(array('my_records', 'year', 'taxon_group_list'), $readAuth);
     $reportNameSuffix = $mySites ? '_my_sites' : '_indexed_sites';
     $extraParams = $mySites ? array('person_site_attr_id' => $args['my_sites_psn_attr_id']) : array('location_type_ids' => $args['main_location_layer_type_id']);
     if (!empty($args['min_rank_sort_order_for_species'])) {
         $extraParams['min_taxon_rank_sort_order'] = $args['min_rank_sort_order_for_species'];
     }
     $reportPerUser = $mySites || !empty($_GET['my_records']);
     $reportOptions = array('readAuth' => $readAuth, 'dataSource' => "library/locations/filterable_{$type}_counts_mappable{$reportNameSuffix}", 'extraParams' => $extraParams, 'caching' => true, 'cachePerUser' => $reportPerUser, 'cachetimeout' => $reportPerUser ? self::FAST_CACHE_REFRESH : self::SLOW_CACHE_REFRESH);
     self::check_filters($reportOptions);
     if ($output === 'map') {
         require_once iform_client_helpers_path() . 'prebuilt_forms/includes/map.php';
         $reportOptions += array('valueOutput' => array('fillColor' => array('from' => '#0000ff', 'to' => '#ff0000', 'valueField' => 'value', 'minValue' => '{minvalue}', 'maxValue' => '{maxvalue}'), 'fillOpacity' => array('from' => 0.25, 'to' => 0.6, 'valueField' => 'value', 'minValue' => '{minvalue}', 'maxValue' => '{maxvalue}')));
         // This looks better when the sites are not contiguous (unlike the full indexed sites layer)
         if ($mySites) {
             $reportOptions['featureDoubleOutlineColour'] = '#f7f7f7';
         }
         $mapOptions = iform_map_get_map_options($args, $readAuth);
         $olOptions = iform_map_get_ol_options($args);
         $mapOptions['clickForSpatialRef'] = false;
         $r .= map_helper::map_panel($mapOptions, $olOptions);
         $r .= report_helper::report_map($reportOptions);
     } else {
         $reportOptions += array('downloadLink' => true, 'columns' => array(array('fieldname' => 'site_label', 'visible' => false)));
         $r .= report_helper::report_grid($reportOptions);
     }
     return $r;
 }
 /**
  * Return the generated form output.
  * @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 object $node The Drupal node object.
  * @param array $response When this form is reloading after saving a submission, contains the response from the service call.
  * Note this does not apply when redirecting (in this case the details of the saved object are in the $_GET data).
  * @return Form HTML.
  */
 public static function get_form($args, $node, $response = null)
 {
     $form = '<form action="#" method="POST" id="entry_form">';
     if ($_POST) {
         $auth = data_entry_helper::get_read_write_auth($args['website_id'], $args['password']);
         self::subscribe($args, $auth);
     } else {
         // don't bother with write auth for initial form load, as read auth is cached and faster
         $auth = array('read' => data_entry_helper::get_read_auth($args['website_id'], $args['password']));
     }
     if (!empty($_GET['id'])) {
         data_entry_helper::load_existing_record($auth['read'], 'species_alert', $_GET['id']);
         // enforce permissions
         if (data_entry_helper::$entity_to_load['species_alert:user_id'] != hostsite_get_user_field('indicia_user_id')) {
             return lang::get('You cannot modify a species alert subscription created by someone else');
         }
         $form .= data_entry_helper::hidden_text(array('fieldname' => 'species_alert:id', 'default' => $_GET['id']));
     }
     // if not logged in, then ask for details to register against
     global $user;
     if (!hostsite_get_user_field('id') || !isset($user) || empty($user->mail) || !hostsite_get_user_field('last_name')) {
         $form .= "<fieldset><legend>" . lang::get('Your details') . ":</legend>\n";
         $default = empty($_POST['first_name']) ? hostsite_get_user_field('first_name', '') : $_POST['first_name'];
         $form .= data_entry_helper::text_input(array('label' => lang::get('First name'), 'fieldname' => 'first_name', 'validation' => array('required'), 'default' => $default, 'class' => 'control-width-4'));
         $default = empty($_POST['surname']) ? hostsite_get_user_field('last_name', '') : $_POST['surname'];
         $form .= data_entry_helper::text_input(array('label' => lang::get('Last name'), 'fieldname' => 'surname', 'validation' => array('required'), 'default' => $default, 'class' => 'control-width-4'));
         $default = empty($_POST['email']) ? empty($user->mail) ? '' : $user->mail : $_POST['email'];
         $form .= data_entry_helper::text_input(array('label' => lang::get('Email'), 'fieldname' => 'email', 'validation' => array('required', 'email'), 'default' => $default, 'class' => 'control-width-4'));
         $form .= "</fieldset>\n";
     } else {
         $form .= data_entry_helper::hidden_text(array('fieldname' => 'first_name', 'default' => hostsite_get_user_field('first_name')));
         $form .= data_entry_helper::hidden_text(array('fieldname' => 'surname', 'default' => hostsite_get_user_field('last_name')));
         $form .= data_entry_helper::hidden_text(array('fieldname' => 'email', 'default' => $user->mail));
         $form .= data_entry_helper::hidden_text(array('fieldname' => 'user_id', 'default' => hostsite_get_user_field('indicia_user_id')));
     }
     $form .= "<fieldset><legend>" . lang::get('Alert criteria') . ":</legend>\n";
     // Output the species selection control
     // Default after saving with a validation failure can be pulled direct from the post, but
     // when reloading we don't need a default taxa taxon list ID since we already know the meaning
     // ID or external key.
     $default = empty($_POST['taxa_taxon_list_id']) ? '' : $_POST['taxa_taxon_list_id'];
     if (empty($_POST['taxa_taxon_list_id:taxon'])) {
         $defaultCaption = empty(data_entry_helper::$entity_to_load['species_alert:preferred_taxon']) ? '' : data_entry_helper::$entity_to_load['species_alert:preferred_taxon'];
     } else {
         $defaultCaption = $_POST['taxa_taxon_list_id:taxon'];
     }
     $form .= data_entry_helper::species_autocomplete(array('label' => lang::get('Alert species'), 'helpText' => lang::get('Select the species you are interested in receiving alerts in ' . 'relation to if you want to receive alerts on a single species.'), 'fieldname' => 'taxa_taxon_list_id', 'cacheLookup' => true, 'extraParams' => $auth['read'] + array('taxon_list_id' => $args['list_id']), 'class' => 'control-width-4', 'default' => $default, 'defaultCaption' => $defaultCaption));
     if (empty($default)) {
         // Unless we've searched for the species name then posted (and failed), then the
         // default will be empty. We might therefore be reloading existing data which has
         // a meaning ID or external key.
         if (!empty(data_entry_helper::$entity_to_load['species_alert:external_key'])) {
             $form .= data_entry_helper::hidden_text(array('fieldname' => 'species_alert:external_key', 'default' => data_entry_helper::$entity_to_load['species_alert:external_key']));
         } elseif (!empty(data_entry_helper::$entity_to_load['species_alert:taxon_meaning_id'])) {
             $form .= data_entry_helper::hidden_text(array('fieldname' => 'species_alert:taxon_meaning_id', 'default' => data_entry_helper::$entity_to_load['species_alert:taxon_meaning_id']));
         }
     }
     if (!empty($args['full_lists'])) {
         $form .= data_entry_helper::select(array('label' => lang::get('Select full species lists'), 'helpText' => lang::get('If you want to restrict the alerts to records of any ' . 'species within a species list, then select the list here.'), 'fieldname' => 'species_alert:taxon_list_id', 'blankText' => lang::get('<Select a species list>'), 'table' => 'taxon_list', 'valueField' => 'id', 'captionField' => 'title', 'extraParams' => $auth['read'] + array('id' => $args['full_lists'], 'orderby' => 'title'), 'class' => 'control-width-4'));
     }
     $form .= data_entry_helper::location_select(array('label' => lang::get('Select location'), 'helpText' => lang::get('If you want to restrict the alerts to records within a certain boundary, select it here.'), 'fieldname' => 'species_alert:location_id', 'id' => 'imp-location', 'blankText' => lang::get('<Select boundary>'), 'extraParams' => $auth['read'] + array('location_type_id' => $args['location_type_id'], 'orderby' => 'name'), 'class' => 'control-width-4'));
     $form .= data_entry_helper::checkbox(array('label' => lang::get('Alert on initial entry'), 'helpText' => lang::get('Tick this box if you want to receive a notification when the record is first input into the system.'), 'fieldname' => 'species_alert:alert_on_entry'));
     $form .= data_entry_helper::checkbox(array('label' => lang::get('Alert on verification as correct'), 'helpText' => lang::get('Tick this box if you want to receive a notification when the record has been verified as correct.'), 'fieldname' => 'species_alert:alert_on_verify'));
     $form .= "</fieldset>\n";
     $form .= '<input type="Submit" value="Subscribe" />';
     $form .= '</form>';
     data_entry_helper::enable_validation('entry_form');
     iform_load_helpers(array('map_helper'));
     $mapOptions = iform_map_get_map_options($args, $auth['read']);
     $map = map_helper::map_panel($mapOptions);
     global $indicia_templates;
     return str_replace(array('{col-1}', '{col-2}'), array($form, $map), $indicia_templates['two-col-50']);
 }
 /**
  * Outputs a map panel.
  * The map panel can be augmented by adding any of the following controls which automatically link themselves
  * to the map:
  * <ul>
  * <li>{@link sref_textbox()}</li>
  * <li>{@link sref_system_select()}</li>
  * <li>{@link sref_and_system()}</li>
  * <li>{@link georeference_lookup()}</li>
  * <li>{@link location_select()}</li>
  * <li>{@link location_autocomplete()}</li>
  * <li>{@link postcode_textbox()}</li>
  * </ul>
  * To run JavaScript at the end of map initialisation, add a function to the global array
  * called mapInitialisationHooks. Code cannot access the map at any previous point because
  * maps may not be initialised when the page loads, e.g. if the map initialisation is
  * delayed until the tab it is on is shown.
  * To run JavaScript which updates any of the map settings, add a function to the
  * mapSettingsHooks global array. For example this is used to configure the map by report
  * parameters panels which need certain tools on the map.
  * @param array $options Associative array of options to pass to the jQuery.indiciaMapPanel plugin.
  * Has the following possible options:
  * <ul><li><b>indiciaSvc</b><br/>
  * </li>
  * <li><b>indiciaGeoSvc</b><br/>
  * </li>
  * <li><b>readAuth</b><br/>
  * Provides read authentication tokens for the warehouse. Only required when there is a location control linked to the warehouse associated with this map.
  * </li>
  * <li><b>height</b><br/>
  * Height of the map panel, in pixels.
  * </li>
  * <li><b>width</b><br/>
  * Width of the map panel, in pixels or as a percentage if followed by a % symbol.
  * </li>
  * <li><b>initial_lat</b><br/>
  * Latitude of the centre of the initially displayed map, using WGS84.
  * </li>
  * <li><b>initial_long</b><br/>
  * Longitude of the centre of the initially displayed map, using WGS84.
  * </li>
  * <li><b>initial_zoom</b><br/>
  * </li>
  * <li><b>scroll_wheel_zoom</b><br/>
  * Does the scroll wheel zoom the map in and out when over the map? Defaults to true. When using the scroll wheel to look up and down a data entry form
  * it can be easy to inadvertantly scroll the map, so it may be desirable to disable this feature in some cases.
  * </li>
  * <li><b>proxy</b><br/>
  * </li>
  * <li><b>displayFormat</b><br/>
  * </li>
  * <li><b>presetLayers</b><br/>
  * Array of preset layers to include. Options are 'google_physical', 'google_streets', 'google_hybrid',
  * 'google_satellite', 'openlayers_wms', 'nasa_mosaic', 'virtual_earth' (deprecated, use bing_aerial),
  * 'bing_aerial', 'bing_hybrid, 'bing_shaded', 'osm' (for OpenStreetMap), 'osm_th' (for OpenStreetMap Tiles@Home).
  * </li>
  * <li><b>tilecacheLayers</b><br/>
  * Array of layer definitions for tilecaches, which are pre-cached background tiles. They are less flexible but much faster
  * than typical WMS services. The array is associative, with the following keys:
  *   caption - The display name of the layer
  *   servers - array list of server URLs for the cache
  *   layerName - the name of the layer within the cache
  *   settings - any other settings that need to be passed to the tilecache, e.g. the server resolutions or file format.</li>
  * <li><b>indiciaWMSLayers</b><br/>
  * </li>
  * <li><b>indiciaWFSLayers</b><br/>
  * </li>
  * <li><b>layers</b><br/>
  * An array of JavaScript variables which point to additional OpenLayers layer objects to add to the map. The JavaScript for creating these layers 
  * can be added to data_entry_helper::$onload_javascript before calling the map_panel method.
  * </li>
  * <li><b>clickableLayers</b><br/>
  * If support for clicking on a layer to provide info on the clicked objects is required, set this to an array containing the JavaScript variable
  * names for the OpenLayers WMS layer objects you have created for the clickable layers. The JavaScript for creating these layers 
  * can be added to data_entry_helper::$onload_javascript before calling the map_panel method and they can be the same layers as those referred to in 
  * the layers parameter.
  * </li>
  * <li><b>clickableLayersOutputMode</b><br/>
  * Set to popup to display the information retrieved from a click operation on a popup window, set to div to
  * display the information in a specified HTML div, or to customFunction to call a JavaScript function
  * after the click operation allowing custom functionality such as navigation to another page. Default 
  * is popup.
  * </li>
  * <li><b>clickableLayersOutputDiv</b><br/>
  * ID of the HTML div to output information retrieved from a click operation into, if clickableLayersOutputMode
  * is set to div.
  * </li>
  * <li><b>allowBox</b><br/>
  * Default true. Set to false to disable drag boxes for selecting items on clickable layers. The advantage of this is that
  * the drag boxes don't hinder attempts to drag the map to navigate.
  * </li>
  * <li><b>customClickFn</b>
  * Set to the name of a global custom JavaScript function which will handle the event of clicking on the map if 
  * you want custom functionality. Provide this when clickableLayersOutputMode=customFunction. The function will 
  * receive a single parameter containing an array of features.
  * </li>
  * <li><b>clickableLayersOutputFn</b><br/>
  * Allows overridding of the appearance of the output when clicking on the map for WMS or vector layers. Should be set to a 
  * JavaScript function name which takes a list of features and the map div as parameters, then returns the HTML to output.</li>
  * <li><b>clickableLayersOutputColumns</b><br/>
  * An associated array of column field names with column titles as the values which defines the columns that are output when clicking on a data point. 
  * If ommitted, then all columns are output using their original field names.
  * </li>
  * <li><b>locationLayerName</b><br/>
  * If using a location select or autocomplete control, then set this to the name of a feature type exposed on GeoServer which contains the id, name and boundary
  * geometry of each location that can be selected. Then when the user clicks on the map the system is able to automatically populate the locations control with the 
  * clicked on location. Ensure that the feature type is styled on GeoServer to appear as required, though it will be added to the map with semi-transparency. To use
  * this feature ensure that a proxy is set, e.g. by using the Indicia Proxy module in Drupal.
  * </li>
  * <li><b>locationLayerFilter</b><br/>
  * If using a location layer, then set this to a cql filter in order to select e.g. locations for a website or locations of a type.
  * The filter can act on any fields in the feature type that locationLayerName refers to.
  * </li>
  * <li><b>controls</b><br/>
  * </li>
  * <li><b>toolbarDiv</b><br/>
  * If set to 'map' then any required toolbuttons are output directly onto the map canvas (in the top right corner). Alternatively can be set to 'top',
  * 'bottom' or the id of a div on the page to output them into.
  * </li>
  * <li><b>toolbarPrefix</b><br/>
  * Content to include at the beginning of the map toolbar. Not applicable when the toolbar is added directly to the map.
  * </li>
  * <li><b>toolbarSuffix</b><br/>
  * Content to include at the end of the map toolbar. Not applicable when the toolbar is added directly to the map.
  * </li>
  * <li><b>helpDiv</b><br/>
  * Set to 'bottom' to add a div containing help hints below the map. Set to the name of a div to output help hints into that
  * div. Otherwise no help hints are displayed.
  * </li>
  * <li><b>clickForSpatialRef</b><br/>
  * Does clicking on the map set the spatial reference of the sample input controls on the form the map appears on (if any)?
  * Defaults to true.
  * </li>
  * <li><b>allowPolygonRecording</b><br/>
  * If a drawPolygon or drawLine control is present, do these set the spatial reference of the sample input controls on the form the map appears on (if any)?
  * The spatial ref is set to the polygon centroid and the sample geometry is set to the polygon itself allowing polygons for records.
  * </li>
  * <li><b>editLayer</b><br/>
  * </li>
  * <li><b>editLayerName</b><br/>
  * </li>
  * <li><b>standardControls</b>
  * An array of predefined controls that are added to the map. Select from:<br/>
  *    layerSwitcher - a button in the corner of the map which opens a panel allowing selection of the visible layers.<br/>
  *    drawPolygon - a tool for drawing polygons onto the map edit layer.<br/>
  *    drawLine - a tool for drawing lines onto the map edit layer.<br/>
  *    drawPoint - a tool for drawing points onto the map edit layer.<br/>
  *    zoomBox - allow zooming to a bounding box, drawn whilst holding the shift key down. This functionality is provided by the panZoom and panZoomBar controls as well
  *    so is only relevant when they are not selected. 
  *    panZoom - simple controls in the corner of the map for panning and zooming.
  *    panZoomBar - controls in the corner of the map for panning and zooming, including a slide bar for zooming.
  *    modifyFeature - a tool for selecting a feature on the map edit layer then editing the vertices of the feature.
  *    selectFeature - a tool for selecting a feature on the map edit layer.
  *    hoverFeatureHighlight - highlights the feature on the map edit layer which is under the mouse cursor position.
  *    fullscreen - add a button allowing the map to be shown in full screen mode.
  * Default is layerSwitcher, panZoom and graticule.
  * </li>
  * <li><b>initialFeatureWkt</b><br/>
  * Well known text for a geometry to load onto the map at startup, normally corresponding to the geometry of the record
  * being edited.
  * </li>
  * <li><b>initialBoundaryWkt</b><br/>
  * Well known text for a geometry to load onto the map at startup, normally corresponding to the geometry of the boundary
  * being edited (e.g. a site boundary).
  * </li>
  * <li><b>defaultSystem</b><br/>
  * </li>
  * <li><b>latLongFormat</b><br/>
  * Override the format for display of lat long references. Select from D (decimal degrees, the default), DM (degrees and decimal minutes)
  * or DMS (degrees, minutes and decimal seconds).</li>
  * <li><b>srefId</b><br/>
  * Override the id of the control that has the grid reference value
  * </li>
  * <li><b>srefSystemId</b><br/>
  * Override the id of the control that has the spatial reference system value
  * </li>
  * <li><b>geomId</b><br/>
  * </li>
  * <li><b>clickedSrefPrecisionMin</b><br/>
  * Specify the minimum precision allowed when clicking on the map to get a grid square. If not set then the grid square selected will increase to its maximum
  * size as the map is zoomed out. E.g. specify 4 for a 1km British National Grid square.
  * </li>
  * <li><b>clickedSrefPrecisionMax</b><br/>
  * Specify the maximum precision allowed when clicking on the map to get a grid square. If not set then the grid square selected will decrease to its minimum
  * size as the map is zoomed in. E.g. specify 4 for a 1km British National Grid square.
  * </li>
  * <li><b>msgGeorefSelectPlace</b><br/>
  * </li>
  * <li><b>msgGeorefNothingFound</b><br/>
  * </li>
  * <li><b>msgSrefOutsideGrid</b><br/>
  * Message displayed when point outside of grid reference range is clicked.
  * </li>
  * <li><b>msgSrefNotRecognised</b><br/>
  * Message displayed when a grid reference is typed that is not recognised.
  * </li>
  * <li><b>maxZoom</b><br/>
  * Limit the maximum zoom used when clicking on the map to set a point spatial reference. Use this to prevent over zooming on
  * background maps.</li>
  * <li><b>tabDiv</b><br/>
  * If loading this control onto a set of tabs, specify the tab control's div ID here. This allows the control to
  * automatically generate code which only generates the map when the tab is shown.</li>
  * <li><b>setupJs</b><br/>
  * When there is JavaScript to run before the map is initialised, put the JavaScript into this option. This allows the map to run the 
  * setup JavaScript just in time, immediately before the map is created. This avoids problems where the setup JavaScript causes the OpenLayers library 
  * to be initialised too earlier if the map is on a div.</li>
  * <li><b>graticuleProjection</b><br/>
  * EPSG code (including EPSG:) for the projection used for the graticule (grid overlay).</li>
  * <li><b>graticuleBounds</b><br/>
  * Array of the bounding box coordinates for the graticule(W,S,E,N) in the coordinate system of the graticule.</li>
  * <li><b>graticuleIntervals</b><br/>
  * A list of possible graticule widths in the coordinate system of the graticule.</li>
  * <li><b>graticuleIntervalColours</b><br/>
  * A list of possible graticule CSS colours corresponding to each graticule width.</li>
  * <li><b>rememberPos</b><br/>
  * Set to true to enable restoring the map position when the page is reloaded. Requires jquery.cookie plugin. As this feature
  * requires cookies, you should notify your users in compliance with European cookie law if you use this option.</li>
  * </ul>
  * <li><b>helpDiv</b><br/>
  * Set to bottom to output a help div under the map, or set to the ID of a div to output into.</li>
  * <li><b>helpToPickPrecisionMin</b><br/>
  * Set to a precision in metres (e.g. 10, 100, 1000) to provide help guiding the recorder to pick a grid square of at least that precision. Ensure that helpDiv is 
  * set when using this option.</li>
  * <li><b>helpToPickPrecisionMax</b><br/>
  * Set to a precision in metres (e.g. 10, 100, 1000) that the help system will accept as not requiring further refinement when a grid square of this precision is picked.</li>  
  * <li><b>helpToPickPrecisionSwitchAt</b><br/>
  * Set to a precision in metres (e.g. 10, 100, 1000) that the map will switch to the satellite layer (if Google or Bing satellite layers active) when
  * the recorder picks a grid square of at least that precision.</li>
  * <li><b>gridRefHint</b><br/>
  * Set to true to put the currently hovered over grid ref in an element with id grid-ref-hint. Use the next setting to automate adding this to the page.</li>
  * <li><b>gridRefHintInFooter</b><br/>
  * Defaults to true. If there is a grid ref hint, should it go in the footer area of the map? If so, there is no need to add an element id grid-ref-hint to the page.</li>
  * </ul>
  * @param array $olOptions Optional array of settings for the OpenLayers map object. If overriding the projection or
  * displayProjection settings, just pass the EPSG number, e.g. 27700.
  */
 public static function map_panel($options, $olOptions = array())
 {
     if (!$options) {
         return '<div class="error">Form error. No options supplied to the map_panel method.</div>';
     } else {
         global $indicia_templates;
         $presetLayers = array();
         // If the caller has not specified the background layers, then default to the ones we have an API key for
         if (!array_key_exists('presetLayers', $options)) {
             $presetLayers[] = 'google_satellite';
             $presetLayers[] = 'google_hybrid';
             $presetLayers[] = 'google_physical';
             $presetLayers[] = 'virtual_earth';
             $presetLayers[] = 'osm';
         }
         if (!empty(parent::$warehouse_proxy)) {
             $warehouseUrl = parent::$warehouse_proxy;
         } else {
             $warehouseUrl = parent::$base_url;
         }
         $options = array_merge(array('indiciaSvc' => $warehouseUrl, 'indiciaGeoSvc' => self::$geoserver_url, 'divId' => 'map', 'class' => '', 'width' => 600, 'height' => 470, 'presetLayers' => $presetLayers, 'jsPath' => self::$js_path, 'clickForSpatialRef' => true, 'gridRefHintInFooter' => true, 'gridRefHint' => false), $options);
         // When using tilecache layers, the open layers defaults cannot be used. The caller must take control of openlayers settings
         if (isset($options['tilecacheLayers'])) {
             $options['useOlDefaults'] = false;
         }
         //width and height may be numeric, which is interpreted as pixels, or a css string, e.g. '50%'
         //width in % is causing problems with panning in Firefox currently. 13/3/2010.
         if (is_numeric($options['height'])) {
             $options['height'] .= 'px';
         }
         if (is_numeric($options['width'])) {
             $options['width'] .= 'px';
         }
         if (array_key_exists('readAuth', $options)) {
             // Convert the readAuth into a query string so it can pass straight to the JS class.
             $options['readAuth'] = '&' . self::array_to_query_string($options['readAuth']);
             str_replace('&', '&amp;', $options['readAuth']);
         }
         // convert textual true/false to boolean equivalents.
         foreach ($options as $key => $value) {
             if ($options[$key] === "false") {
                 $options[$key] = false;
             } else {
                 if ($options[$key] === "true") {
                     $options[$key] = true;
                 }
             }
         }
         // Autogenerate the links to the various mapping libraries as required
         if (array_key_exists('presetLayers', $options)) {
             foreach ($options['presetLayers'] as $layer) {
                 $a = explode('_', $layer);
                 $a = strtolower($a[0]);
                 switch ($a) {
                     case 'google':
                         self::add_resource('googlemaps');
                         break;
                     case 'virtual':
                         self::add_resource('virtualearth');
                         break;
                 }
                 if ($a == 'bing' && (!isset(self::$bing_api_key) || empty(self::$bing_api_key))) {
                     return '<p class="error">To use the Bing layers, please ensure that you declare a variable called $bing_api_key in the helper_config.php file set to an ' . 'empty string and specify a Bing API Key on the IForm settings page.</p>';
                 }
             }
         }
         // This resource has a dependency on the googlemaps resource so has to be added afterwards.
         self::add_resource('indiciaMapPanel');
         if (array_key_exists('standardControls', $options)) {
             if (in_array('graticule', $options['standardControls'])) {
                 self::add_resource('graticule');
             }
             if (in_array('clearEditLayer', $options['standardControls'])) {
                 self::add_resource('clearLayer');
             }
         }
         // We need to fudge the JSON passed to the JavaScript class so it passes any actual layers, functions
         // and controls, not the string class names.
         $json_insert = '';
         $js_entities = array('controls', 'layers', 'clickableLayers');
         foreach ($js_entities as $entity) {
             if (array_key_exists($entity, $options)) {
                 $json_insert .= ',"' . $entity . '":[' . implode(',', $options[$entity]) . ']';
                 unset($options[$entity]);
             }
         }
         // Same for 'clickableLayersOutputFn'
         if (isset($options['clickableLayersOutputFn'])) {
             $json_insert .= ',"clickableLayersOutputFn":' . $options['clickableLayersOutputFn'];
             unset($options['clickableLayersOutputFn']);
         }
         // Same for 'customClickFn'
         if (isset($options['customClickFn'])) {
             $json_insert .= ',"customClickFn":' . $options['customClickFn'];
             unset($options['customClickFn']);
         }
         // make a copy of the options to pass into JavaScript, with a few entries removed.
         $jsoptions = array_merge($options);
         unset($jsoptions['setupJs']);
         unset($jsoptions['tabDiv']);
         if (isset(self::$bing_api_key)) {
             $jsoptions['bing_api_key'] = self::$bing_api_key;
         }
         $json = substr(json_encode($jsoptions), 0, -1) . $json_insert . '}';
         $olOptions = array_merge(array('theme' => self::$js_path . 'theme/default/style.css'), $olOptions);
         $json .= ',' . json_encode($olOptions);
         $javascript = '';
         $mapSetupJs = '';
         if (isset($options['setupJs'])) {
             $mapSetupJs .= $options['setupJs'] . "\n";
         }
         $mapSetupJs .= "jQuery('#" . $options['divId'] . "').indiciaMapPanel({$json});\n";
         // trigger a change event on the sref if it's set in case locking in use. This will draw the polygon on the map.
         $srefId = empty($options['srefId']) ? '$.fn.indiciaMapPanel.defaults.srefId' : "'{$options['srefId']}'";
         if (!(isset($options['switchOffSrefRetrigger']) && $options['switchOffSrefRetrigger'] == true)) {
             $mapSetupJs .= "      var srefId = {$srefId};\n" . "      if (srefId && \$('#' + srefId).length && \$('#' + srefId).val()!=='' && indiciaData.mapdiv.settings.initialBoundaryWkt===null) {jQuery('#'+srefId).change();}\n";
         }
         // If the map is displayed on a tab, so we must only generate it when the tab is displayed as creating the
         // map on a hidden div can cause problems. Also, the map must not be created until onload or later. So
         // we have to set use the mapTabLoaded and windowLoaded to track when these events are fired, and only
         // load the map when BOTH the events have fired.
         if (isset($options['tabDiv'])) {
             $divId = preg_replace('/[^a-zA-Z0-9]/', '', $options['divId']);
             $javascript .= "var mapTabHandler = function(event, ui) { \n";
             $javascript .= "  panel = typeof ui.newPanel==='undefined' ? ui.panel : ui.newPanel[0];\n";
             $javascript .= "  if (typeof indiciaData.mapdiv !== 'undefined' && \$(indiciaData.mapdiv).parents('#'+panel.id).length) {\n";
             $javascript .= "    indiciaData.mapdiv.map.updateSize();\n";
             $javascript .= "  }\n\n};\n";
             $javascript .= "indiciaFns.bindTabsActivate(\$(\$('#" . $options['tabDiv'] . "').parent()), mapTabHandler);\n";
             // Insert this script at the beginning, because it must be done before the tabs are initialised or the
             // first tab cannot fire the event
             self::$javascript = $javascript . self::$javascript;
         }
         $options['suffixTemplate'] = 'blank';
         self::$onload_javascript .= $mapSetupJs;
         $r = str_replace('{content}', self::apply_template('map_panel', $options), $indicia_templates['jsWrap']);
         if ($options['gridRefHintInFooter'] && $options['gridRefHint']) {
             $div = '<div id="map-footer" class="grid-ref-hints ui-helper-clearfix" style="width: ' . $options['width'] . '" ' . 'title="When you hover the mouse over the map, the grid reference is displayed here. Hold the minus key or plus key when clicking on the map ' . 'to decrease or increase the grid square precision respectively.">';
             if ($options['clickForSpatialRef']) {
                 $r .= $div . '<h3>' . lang::get('Click to set map ref') . '</h3>' . '<div class="grid-ref-hint hint-minus">' . '<span class="label"></span><span class="data"></span> <span>(' . lang::get('hold -') . ')</span></div>' . '<div class="grid-ref-hint hint-normal"><span class="label"> </span><span class="data"></span></div>' . '<div class="grid-ref-hint hint-plus">' . '<span class="label"></span><span class="data"></span> <span>(' . lang::get('hold +') . ')</span></div>';
             } else {
                 $r .= $div . '<h3>' . lang::get('Map ref at pointer') . '</h3>' . '<div class="grid-ref-hint hint-normal"><span class="label"></span><span class="data"></span></div>';
             }
             $r .= '</div>';
         }
         return $r;
     }
 }
 private static function get_site_tab($auth, $args, $settings)
 {
     $r = '<div id="site-details" class="ui-helper-clearfix">';
     $r .= '<form method="post" id="input-form">';
     $r .= $auth['write'];
     $r .= '<div id="cols" class="ui-helper-clearfix"><div class="left" style="width: 54%">';
     $r .= '<fieldset><legend>' . lang::get('Site Details') . '</legend>';
     $r .= "<input type=\"hidden\" name=\"website_id\" value=\"" . $args['website_id'] . "\" />\n";
     $typeTerms = array();
     if (!empty($args['main_type_term_1'])) {
         $typeTerms[] = $args['main_type_term_1'];
     }
     if (!empty($args['main_type_term_2'])) {
         $typeTerms[] = $args['main_type_term_2'];
     }
     if (!empty($args['main_type_term_3'])) {
         $typeTerms[] = $args['main_type_term_3'];
     }
     $typeTermIDs = helper_base::get_termlist_terms($auth, 'indicia:location_types', $typeTerms);
     $lookUpValues = array('' => '<' . lang::get('please select') . '>');
     foreach ($typeTermIDs as $termDetails) {
         $lookUpValues[$termDetails['id']] = $termDetails['term'];
     }
     // if location is predefined, can not change unless a 'managerPermission'
     $canEditType = !$settings['locationId'] || isset($args['managerPermission']) && $args['managerPermission'] != '' && function_exists('user_access') && user_access($args['managerPermission']);
     if ($canEditType) {
         $r .= data_entry_helper::select(array('label' => lang::get('Site Type'), 'id' => 'location_type_id', 'fieldname' => 'location:location_type_id', 'lookupValues' => $lookUpValues));
         data_entry_helper::$javascript .= "\$('#location_type_id').change(function(){\r\n  switch(\$(this).val()){\n";
         for ($i = 1; $i < 4; $i++) {
             if (!empty($args['main_type_term_' . $i])) {
                 $type = helper_base::get_termlist_terms($auth, 'indicia:location_types', array($args['main_type_term_' . $i]));
                 data_entry_helper::$javascript .= "    case \"" . $type[0]['id'] . "\":\n";
                 if (!isset($args['can_change_section_number_' . $i]) || !$args['can_change_section_number_' . $i]) {
                     if ($settings['locationId']) {
                         // not saved yet, so no sections yet created, hence no need to worry about existing value. make number attribute readonly. set value. min value will be 1.
                         data_entry_helper::$javascript .= "      var minValue = \$('[name=" . str_replace(':', '\\\\:', $settings['numSectionsAttr']) . "]').attr('min');\r\n      if(minValue > " . $args['section_number_' . $i] . ") { // existing value is greater than one we want to set\r\n        alert('You are reducing the number of sections below that already existing. Please use the Remove Section button on the Your Route tab to reduce the number of sections to " . $args['section_number_' . $i] . " before changing the Site type');\r\n        return false;\r\n      }\r\n      \$('[name=" . str_replace(':', '\\\\:', $settings['numSectionsAttr']) . "]').val(" . $args['section_number_' . $i] . ").attr('readonly','readonly').css('color','graytext');\n";
                     } else {
                         // not saved yet, so no sections yet created, hence no need to worry about existing value. make number attribute readonly. set value. min value will be 1.
                         data_entry_helper::$javascript .= "      \$('[name=" . str_replace(':', '\\\\:', $settings['numSectionsAttr']) . "]').val(" . $args['section_number_' . $i] . ").attr('readonly','readonly').css('color','graytext');\n";
                     }
                 } else {
                     // user modifiable number of sections. value of attribute is left alone: don't have to worry att his point whether existing data.
                     data_entry_helper::$javascript .= "      \$('[name=" . str_replace(':', '\\\\:', $settings['numSectionsAttr']) . "]').removeAttr('readonly').css('color','');\n";
                 }
                 data_entry_helper::$javascript .= "      break;\n";
             }
         }
         data_entry_helper::$javascript .= "    default: break;\r\n  };\r\n  return true;\r\n});\n";
     }
     if ($settings['locationId']) {
         $r .= '<input type="hidden" name="location:id" id="location:id" value="' . $settings['locationId'] . "\" />\n";
     }
     $r .= data_entry_helper::text_input(array('fieldname' => 'location:name', 'label' => lang::get('Site Name'), 'class' => 'control-width-4 required', 'disabled' => $settings['canEditBody'] ? '' : ' disabled="disabled" '));
     if (!$settings['canEditBody']) {
         $r .= '<p>' . lang::get('This site cannot be edited because there are walks recorded on it. Please contact the site administrator if you think there are details which need changing.') . '</p>';
     } else {
         if (count($settings['walks']) > 0) {
             // can edit it
             $r .= '<p>' . lang::get('This site has walks recorded on it. Please do not change the site details without considering the impact on the existing data.') . '</p>';
         }
     }
     $list = explode(',', str_replace(' ', '', $args['spatial_systems']));
     foreach ($list as $system) {
         $systems[$system] = lang::get($system);
     }
     if (isset(data_entry_helper::$entity_to_load['location:centroid_sref_system']) && in_array(data_entry_helper::$entity_to_load['location:centroid_sref_system'], array('osgb', 'osie'))) {
         data_entry_helper::$entity_to_load['location:centroid_sref_system'] = strtoupper(data_entry_helper::$entity_to_load['location:centroid_sref_system']);
     }
     $r .= data_entry_helper::sref_and_system(array('fieldname' => 'location:centroid_sref', 'geomFieldname' => 'location:centroid_geom', 'label' => 'Grid Ref.', 'systems' => $systems, 'class' => 'required', 'helpText' => lang::get('Click on the map to set the central grid reference.'), 'disabled' => $settings['canEditBody'] ? '' : ' disabled="disabled" '));
     if ($settings['locationId'] && data_entry_helper::$entity_to_load['location:code'] != '' && data_entry_helper::$entity_to_load['location:code'] != null) {
         $r .= data_entry_helper::text_input(array('fieldname' => 'location:code', 'label' => lang::get('Site Code'), 'class' => 'control-width-4', 'disabled' => ' readonly="readonly" '));
     } else {
         $r .= "<p>" . lang::get('The Site Code will be allocated by the Administrator.') . "</p>";
     }
     // setup the map options
     $options = iform_map_get_map_options($args, $auth['read']);
     // find the form blocks that need to go below the map.
     $bottom = '';
     $bottomBlocks = explode("\n", isset($args['bottom_blocks']) ? $args['bottom_blocks'] : '');
     foreach ($bottomBlocks as $block) {
         $bottom .= get_attribute_html($settings['attributes'], $args, array('extraParams' => $auth['read'], 'disabled' => $settings['canEditBody'] ? '' : ' disabled="disabled" '), $block);
     }
     // other blocks to go at the top, next to the map
     if (isset($args['site_help']) && $args['site_help'] != '') {
         $r .= '<p class="ui-state-highlight page-notice ui-corner-all">' . t($args['site_help']) . '</p>';
     }
     $r .= get_attribute_html($settings['attributes'], $args, array('extraParams' => $auth['read']));
     $r .= '</fieldset>';
     $r .= "</div>";
     // left
     $r .= '<div class="right" style="width: 44%">';
     if (!$settings['locationId']) {
         $help = t('Use the search box to find a nearby town or village, then drag the map to pan and click on the map to set the centre grid reference of the transect. ' . 'Alternatively if you know the grid reference you can enter it in the Grid Ref box on the left.');
         $r .= '<p class="ui-state-highlight page-notice ui-corner-all">' . $help . '</p>';
         $r .= data_entry_helper::georeference_lookup(array('label' => lang::get('Search for place'), 'driver' => $args['georefDriver'], 'georefPreferredArea' => $args['georefPreferredArea'], 'georefCountry' => $args['georefCountry'], 'georefLang' => $args['language'], 'readAuth' => $auth['read']));
     }
     if (isset($args['maxPrecision']) && $args['maxPrecision'] != '') {
         $options['clickedSrefPrecisionMax'] = $args['maxPrecision'];
     }
     if (isset($args['minPrecision']) && $args['minPrecision'] != '') {
         $options['clickedSrefPrecisionMin'] = $args['minPrecision'];
     }
     $olOptions = iform_map_get_ol_options($args);
     $options['clickForSpatialRef'] = $settings['canEditBody'];
     $r .= map_helper::map_panel($options, $olOptions);
     $r .= '</div></div>';
     // right
     if (!empty($bottom)) {
         $r .= $bottom;
     }
     if ($args['branch_assignment_permission'] != '') {
         if ($settings['canAllocBranch'] || $settings['locationId']) {
             $r .= self::get_branch_assignment_control($auth['read'], $settings['branchCmsUserAttr'], $args, $settings);
         }
     }
     if ($args['allow_user_assignment']) {
         if ($settings['canAllocUser']) {
             $r .= self::get_user_assignment_control($auth['read'], $settings['cmsUserAttr'], $args);
         } else {
             if (!$settings['locationId']) {
                 // for a new record, we need to link the current user to the location if they are not admin.
                 global $user;
                 $r .= '<input type="hidden" name="locAttr:' . self::$cmsUserAttrId . '" value="' . $user->uid . '">';
             }
         }
     }
     if ($settings['canEditBody']) {
         $r .= '<button type="submit" class="indicia-button right">' . lang::get('Save') . '</button>';
     }
     if ($settings['canEditBody'] && $settings['locationId']) {
         $r .= '<button type="button" class="indicia-button right" id="delete-transect">' . lang::get('Delete') . '</button>';
     }
     $r .= '</form>';
     $r .= '</div>';
     // site-details
     // This must go after the map panel, so it has created its toolbar
     data_entry_helper::$onload_javascript .= "\$('#current-section').change(selectSection);\n";
     if ($settings['canEditBody'] && $settings['locationId']) {
         $walkIDs = array();
         foreach ($settings['walks'] as $walk) {
             $walkIDs[] = $walk['id'];
         }
         $sectionIDs = array();
         foreach ($settings['sections'] as $code => $section) {
             $sectionIDs[] = $section['id'];
         }
         data_entry_helper::$javascript .= "\r\ndeleteSurvey = function(){\r\n  if(confirm(\"" . (count($settings['walks']) > 0 ? count($settings['walks']) . ' ' . lang::get('walks will also be deleted when you delete this location.') . ' ' : '') . lang::get('Are you sure you wish to delete this location?') . "\")){\r\n    deleteWalks([" . implode(',', $walkIDs) . "]);\r\n    deleteSections([" . implode(',', $sectionIDs) . "]);\r\n    \$('#delete-transect').html('Deleting Site');\r\n    deleteLocation(" . $settings['locationId'] . ");\r\n    \$('#delete-transect').html('Done');\r\n    window.location='" . url($args['sites_list_path']) . "';\r\n  };\r\n};\r\n\$('#delete-transect').click(deleteSurvey);\r\n";
     }
     return $r;
 }
 public static function get_sample_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.';
     }
     iform_load_helpers(array('map_helper'));
     $auth = data_entry_helper::get_read_write_auth($args['website_id'], $args['password']);
     $sampleId = isset($_GET['sample_id']) ? $_GET['sample_id'] : null;
     if ($sampleId) {
         data_entry_helper::load_existing_record($auth['read'], 'sample', $sampleId);
         $locationId = data_entry_helper::$entity_to_load['sample:location_id'];
     } else {
         $locationId = isset($_GET['site']) ? $_GET['site'] : null;
         // location ID also might be in the $_POST data after a validation save of a new record
         if (!$locationId && isset($_POST['sample:location_id'])) {
             $locationId = $_POST['sample:location_id'];
         }
     }
     $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));
     $r = '<form method="post" id="sample">';
     $r .= $auth['write'];
     // we pass through the read auth. This makes it possible for the get_submission method to authorise against the warehouse
     // without an additional (expensive) warehouse call, so it can get location details.
     $r .= '<input type="hidden" name="page" value="mainSample"/>';
     $r .= '<input type="hidden" name="read_nonce" value="' . $auth['read']['nonce'] . '"/>';
     $r .= '<input type="hidden" name="read_auth_token" value="' . $auth['read']['auth_token'] . '"/>';
     $r .= '<input type="hidden" name="website_id" value="' . $args['website_id'] . '"/>';
     if (isset(data_entry_helper::$entity_to_load['sample:id'])) {
         $r .= '<input type="hidden" name="sample:id" value="' . data_entry_helper::$entity_to_load['sample:id'] . '"/>';
     }
     $r .= '<input type="hidden" name="sample:survey_id" value="' . $args['survey_id'] . '"/>';
     if (isset($args['include_map_samples_form']) && $args['include_map_samples_form']) {
         $r .= '<div id="cols" class="ui-helper-clearfix"><div class="left" style="width: ' . (98 - (isset($args['percent_width']) ? $args['percent_width'] : 50)) . '%">';
     }
     if ($locationId) {
         $site = data_entry_helper::get_population_data(array('table' => 'location', 'extraParams' => $auth['read'] + array('view' => 'detail', 'id' => $locationId, 'deleted' => 'f')));
         $site = $site[0];
         $r .= '<input type="hidden" name="sample:location_id" value="' . $locationId . '"/>';
         $r .= '<input type="hidden" name="sample:entered_sref" value="' . $site['centroid_sref'] . '"/>';
         $r .= '<input type="hidden" name="sample:entered_sref_system" value="' . $site['centroid_sref_system'] . '"/>';
     }
     if ($locationId && (isset(data_entry_helper::$entity_to_load['sample:id']) || isset($_GET['site']))) {
         // for reload of existing or the the site is specified in the URL, don't let the user switch the transect as that would mess everything up.
         $r .= '<label>' . lang::get('Transect') . ':</label> <span class="value-label">' . $site['name'] . '</span><br/>';
     } else {
         // Output only the locations for this website and transect type. Note we load both transects and sections, just so that
         // we always use the same warehouse call and therefore it uses the cache.
         $typeTerms = array(empty($args['transect_type_term']) ? 'Transect' : $args['transect_type_term'], empty($args['section_type_term']) ? 'Section' : $args['section_type_term']);
         $locationTypes = helper_base::get_termlist_terms($auth, 'indicia:location_types', $typeTerms);
         $siteParams = $auth['read'] + array('website_id' => $args['website_id'], 'location_type_id' => $locationTypes[0]['id']);
         if ((!isset($args['user_locations_filter']) || $args['user_locations_filter']) && (!isset($args['managerPermission']) || !user_access($args['managerPermission']))) {
             $siteParams += array('locattrs' => 'CMS User ID', 'attr_location_cms_user_id' => $user->uid);
         } else {
             $siteParams += array('locattrs' => '');
         }
         $availableSites = data_entry_helper::get_population_data(array('report' => 'library/locations/locations_list', 'extraParams' => $siteParams, 'nocache' => true));
         // convert the report data to an array for the lookup, plus one to pass to the JS so it can keep the hidden sref fields updated
         $sitesLookup = array();
         $sitesJs = array();
         foreach ($availableSites as $site) {
             $sitesLookup[$site['location_id']] = $site['name'];
             $sitesJs[$site['location_id']] = $site;
         }
         // bolt in branch locations. Don't assume that branch list is superset of normal sites list.
         // Only need to do if not a manager - they have already fetched the full list anyway.
         if (isset($args['branch_assignment_permission']) && user_access($args['branch_assignment_permission']) && $siteParams['locattrs'] != '') {
             $siteParams['locattrs'] = 'Branch CMS User ID';
             $siteParams['attr_location_branch_cms_user_id'] = $user->uid;
             unset($siteParams['attr_location_cms_user_id']);
             $availableSites = data_entry_helper::get_population_data(array('report' => 'library/locations/locations_list', 'extraParams' => $siteParams, 'nocache' => true));
             foreach ($availableSites as $site) {
                 $sitesLookup[$site['location_id']] = $site['name'];
                 $sitesJs[$site['location_id']] = $site;
             }
             natcasesort($sitesLookup);
             // merge into original list in alphabetic order.
         }
         data_entry_helper::$javascript .= "indiciaData.sites = " . json_encode($sitesJs) . ";\n";
         $options = array('label' => lang::get('Select Transect'), 'validation' => array('required'), 'blankText' => lang::get('please select'), 'lookupValues' => $sitesLookup);
         if ($locationId) {
             $options['default'] = $locationId;
         }
         $r .= data_entry_helper::location_select($options);
     }
     if (!$locationId) {
         $r .= '<input type="hidden" name="sample:entered_sref" value="" id="entered_sref"/>';
         $r .= '<input type="hidden" name="sample:entered_sref_system" value="" id="entered_sref_system"/>';
         // sref values for the sample will be populated automatically when the submission is built.
     }
     $sampleMethods = helper_base::get_termlist_terms($auth, 'indicia:sample_methods', array('Transect'));
     $attributes = data_entry_helper::getAttributes(array('id' => $sampleId, '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']));
     $r .= get_user_profile_hidden_inputs($attributes, $args, '', $auth['read']);
     if (isset($_GET['date'])) {
         $r .= '<input type="hidden" name="sample:date" value="' . $_GET['date'] . '"/>';
         $r .= '<label>' . lang::get('Date') . ':</label> <span class="value-label">' . $_GET['date'] . '</span><br/>';
     } else {
         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'), 'fieldname' => 'sample:date'));
     }
     // are there any option overrides for the custom attributes?
     if (isset($args['custom_attribute_options']) && $args['custom_attribute_options']) {
         $blockOptions = get_attr_options_array_with_user_data($args['custom_attribute_options']);
     } else {
         $blockOptions = array();
     }
     $r .= get_attribute_html($attributes, $args, array('extraParams' => $auth['read']), null, $blockOptions);
     $r .= '<input type="hidden" name="sample:sample_method_id" value="' . $sampleMethods[0]['id'] . '" />';
     $r .= '<input type="submit" value="' . lang::get('Next') . '" />';
     $r .= '<a href="' . $args['my_walks_page'] . '" class="button">' . lang::get('Cancel') . '</a>';
     if (isset(data_entry_helper::$entity_to_load['sample:id'])) {
         $r .= '<button id="delete-button" type="button" class="ui-state-default ui-corner-all" />' . lang::get('Delete') . '</button>';
     }
     if (isset($args['include_map_samples_form']) && $args['include_map_samples_form']) {
         $r .= "</div>" . '<div class="right" style="width: ' . (isset($args['percent_width']) ? $args['percent_width'] : 50) . '%">';
         // no place search: [map]
         $options = iform_map_get_map_options($args, $auth['read']);
         if (!empty(data_entry_helper::$entity_to_load['sample:wkt'])) {
             $options['initialFeatureWkt'] = data_entry_helper::$entity_to_load['sample:wkt'];
         }
         $olOptions = iform_map_get_ol_options($args);
         if (!isset($options['standardControls'])) {
             $options['standardControls'] = array('layerSwitcher', 'panZoomBar');
         }
         $r .= map_helper::map_panel($options, $olOptions);
         $r .= "</div>";
         // right
     }
     $r .= '</form>';
     // Recorder Name - assume Easy Login uid
     if (function_exists('module_exists') && module_exists('easy_login')) {
         $userId = hostsite_get_user_field('indicia_user_id');
         // For non easy login test only     $userId = 1;
         foreach ($attributes as $attrID => $attr) {
             if (strcasecmp('Recorder Name', $attr["untranslatedCaption"]) == 0 && !empty($userId)) {
                 // determining which you have used is difficult from a services based autocomplete, esp when the created_by_id is not available on the data.
                 data_entry_helper::add_resource('autocomplete');
                 data_entry_helper::$javascript .= "bindRecorderNameAutocomplete(" . $attrID . ", '" . $userId . "', '" . data_entry_helper::$base_url . "', '" . $args['survey_id'] . "', '" . $auth['read']['auth_token'] . "', '" . $auth['read']['nonce'] . "');\n";
             }
         }
     }
     if (isset(data_entry_helper::$entity_to_load['sample:id'])) {
         // allow deletes if sample id is present.
         data_entry_helper::$javascript .= "jQuery('#delete-button').click(function(){\n  if(confirm(\"" . lang::get('Are you sure you want to delete this walk?') . "\")){\n    jQuery('#delete-form').submit();\n  } // else do nothing.\n});\n";
         // note we only require bare minimum in order to flag a sample as deleted.
         $r .= '<form method="post" id="delete-form" style="display: none;">';
         $r .= $auth['write'];
         $r .= '<input type="hidden" name="page" value="delete"/>';
         $r .= '<input type="hidden" name="website_id" value="' . $args['website_id'] . '"/>';
         $r .= '<input type="hidden" name="sample:id" value="' . data_entry_helper::$entity_to_load['sample:id'] . '"/>';
         $r .= '<input type="hidden" name="sample:deleted" value="t"/>';
         $r .= '</form>';
     }
     data_entry_helper::enable_validation('sample');
     return $r;
 }
 protected static function get_your_route_tab($auth, $args, $settings)
 {
     $r = '<div id="your-route" class="ui-helper-clearfix">';
     $olOptions = iform_map_get_ol_options($args);
     $options = iform_map_get_map_options($args, $auth['read']);
     $options['divId'] = 'route-map';
     $options['toolbarDiv'] = 'top';
     $options['tabDiv'] = 'your-route';
     $options['gridRefHint'] = true;
     if ($settings['canEditBody']) {
         $options['toolbarPrefix'] = self::section_selector($settings, 'section-select-route');
         if ($settings['canEditSections'] && count($settings['sections']) > 1 && $settings['numSectionsAttr'] != "") {
             // do not allow deletion of last section, or if the is no section number attribute
             $options['toolbarSuffix'] = '<input type="button" value="' . lang::get('Remove Section') . '" class="remove-section form-button right" title="' . lang::get('Completely remove the highlighted section. The total number of sections will be reduced by one. The form will be reloaded after the section is deleted.') . '">';
         } else {
             $options['toolbarSuffix'] = '';
         }
         $options['toolbarSuffix'] .= '<input type="button" value="' . lang::get('Erase Route') . '" class="erase-route form-button right" title="' . lang::get('If the Draw Line control is active, this will erase each drawn point one at a time. If not active, then this will erase the whole highlighted route. This keeps the Section, allowing you to redraw the route for it.') . '">';
         if ($settings['canEditSections'] && count($settings['sections']) < $args['maxSectionCount'] && $settings['numSectionsAttr'] != "") {
             // do not allow insertion of section if it exceeds max number, or if the is no section number attribute
             $options['toolbarSuffix'] .= '<input type="button" value="' . lang::get('Insert Section') . '" class="insert-section form-button right" title="' . lang::get('This inserts an extra section after the currently selected section. All subsequent sections are renumbered, increasing by one. All associated occurrences are kept with the moved sections. This can be used to facilitate the splitting of this section.') . '">';
         }
         // 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['standardControls'][] = 'selectFeature';
         $options['standardControls'][] = 'hoverFeatureHighlight';
         $options['standardControls'][] = 'drawLine';
         $options['standardControls'][] = 'modifyFeature';
         $options['switchOffSrefRetrigger'] = true;
         $help = lang::get('Select a section from the list then click on the map to draw the route and double click to finish. ' . 'You can also select a section using the query tool to click on the section lines. If you make a mistake in the middle ' . 'of drawing a route, then you can use the Erase Route button to remove the last point drawn. After a route has been ' . 'completed use the Modify a feature tool to correct the line shape (either by dragging one of the circles along the ' . 'line to form the correct shape, or by placing the mouse over a circle and pressing the Delete button on your keyboard ' . 'to remove that point). Alternatively you could just redraw the line - this new line will then replace the old one ' . 'completely. If you are not in the middle of drawing a line, the Erase Route button will erase the whole route for the ' . 'currently selected section.') . ($settings['numSectionsAttr'] != "" ? '<br />' . (count($settings['sections']) > 1 ? lang::get('The Remove Section button will remove the section completely, reducing the number of sections by one.') . ' ' : '') . lang::get('To increase the number of sections, return to the Site Details tab, and increase the value in the No. of sections field there.') : '');
         $r .= '<p class="ui-state-highlight page-notice ui-corner-all">' . $help . '</p>';
     }
     $options['clickForSpatialRef'] = false;
     // 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['route_map_height'];
     $options['maxZoomBuffer'] = $args['route_map_buffer'];
     $r .= map_helper::map_panel($options, $olOptions);
     if (count($settings['section_attributes']) == 0) {
         $r .= '<button class="indicia-button right" type="button" title="' . lang::get('Returns to My Sites page. Any changes to sections carried out on this page (including creating new ones) are saved to the database as they are done, but changes to the Site Details must be saved using the Save button on that tab.') . '" onclick="window.location.href=\'' . url($args['redirect_on_success']) . '\'">' . lang::get('Return to My Sites') . '</button>';
     }
     $r .= '</div>';
     return $r;
 }
Exemple #24
0
 /**
  * Return the generated form output.
  * @return Form HTML.
  * @todo: Implement this method
  */
 public static function get_form($args)
 {
     global $user;
     $lang = isset($user) ? iform_lang_iso_639_2($user->lang) : 'eng';
     require_once dirname(dirname(__FILE__)) . '/map_helper.php';
     $readAuth = data_entry_helper::get_read_auth($args['website_id'], $args['password']);
     $r = '';
     // setup the map options
     $options = iform_map_get_map_options($args, $readAuth);
     $olOptions = iform_map_get_ol_options($args);
     if (array_key_exists('table', $_GET) && $_GET['table'] == 'sample') {
         // Use a cUrl request to get the data from Indicia which contains the value we need to filter against
         // Read the record that was just posted.
         $fetchOpts = array('dataSource' => 'reports_for_prebuilt_forms/my_dot_map/occurrences_list', 'mode' => 'report', 'readAuth' => $readAuth, 'extraParams' => array('sample_id' => $_GET['id'], 'language' => $lang));
         // @todo Error handling on the response
         $occurrence = data_entry_helper::get_report_data($fetchOpts);
         self::prepare_layer_titles($args, $occurrence);
         // Add the 3 distribution layers if present. Reverse the order so 1st layer is topmost
         $layerName = self::build_distribution_layer(3, $args, $occurrence);
         if ($layerName) {
             $options['layers'][] = $layerName;
         }
         $layerName = self::build_distribution_layer(2, $args, $occurrence);
         if ($layerName) {
             $options['layers'][] = $layerName;
         }
         $layerName = self::build_distribution_layer(1, $args, $occurrence);
         if ($layerName) {
             $options['layers'][] = $layerName;
         }
         if ($layerName) {
             $options['layers'][] = $layerName;
         }
         // This is not a map used for input
         $options['editLayer'] = false;
         if ($args['hide_grid'] == false) {
             // Now output a grid of the occurrences that were just saved.
             $r .= "<table class=\"submission\"><thead><tr><th>" . lang::get('Species') . "</th><th>" . lang::get('Latin Name') . "</th><th>" . lang::get('Date') . "</th><th>" . lang::get('Spatial Ref') . "</th></tr></thead>\n";
             $r .= "<tbody>\n";
             foreach ($occurrence as $record) {
                 $r .= '<tr class="biota"><td>' . $record['lt4_taxon'] . '</td><td class="binomial"><em>' . $record['lt7_taxon'] . '</em></td><td>' . $record['lt0_date_start'] . '</td><td>' . $record['lt0_entered_sref'] . "</td></tr>\n";
             }
             $r .= "</tbody></table>\n";
         }
     }
     $r .= '<div id="mapandlegend">';
     $r .= map_helper::layer_list(array('id' => 'legend', 'includeSwitchers' => false, 'includeHiddenLayers' => false, 'includeIcons' => true, 'layerTypes' => array('overlay')));
     $r .= map_helper::map_panel($options, $olOptions);
     $r .= '</div>';
     return $r;
 }
 /**
  * Return the generated form output.
  * @return Form HTML.
  * @todo: Implement this method
  */
 public static function get_form($args)
 {
     $lang = iform_lang_iso_639_2(hostsite_get_user_field('language', 'en'));
     if (function_exists('iform_load_helpers')) {
         iform_load_helpers(array('map_helper'));
     } else {
         require_once dirname(dirname(__FILE__)) . '/map_helper.php';
     }
     $readAuth = data_entry_helper::get_read_auth($args['website_id'], $args['password']);
     $r = '';
     // setup the map options
     $options = iform_map_get_map_options($args, $readAuth);
     $olOptions = iform_map_get_ol_options($args);
     if (array_key_exists('table', $_GET) && $_GET['table'] == 'sample') {
         // Use a cUrl request to get the data from Indicia which contains the value we need to filter against
         // Read the record that was just posted.
         $fetchOpts = array('dataSource' => 'reports_for_prebuilt_forms/my_dot_map/occurrences_list_2', 'mode' => 'report', 'readAuth' => $readAuth, 'extraParams' => array('sample_id' => $_GET['id'], 'language' => $lang));
         // @todo Error handling on the response
         $occurrence = data_entry_helper::get_report_data($fetchOpts);
         self::prepare_layer_titles($args, $occurrence);
         // Add the 3 distribution layers if present. Reverse the order so 1st layer is topmost
         $layerName = self::build_distribution_layer(3, $args, $occurrence);
         if ($layerName) {
             $options['layers'][] = $layerName;
         }
         $layerName = self::build_distribution_layer(2, $args, $occurrence);
         if ($layerName) {
             $options['layers'][] = $layerName;
         }
         $layerName = self::build_distribution_layer(1, $args, $occurrence);
         if ($layerName) {
             $options['layers'][] = $layerName;
         }
         if ($layerName) {
             $options['layers'][] = $layerName;
         }
         // This is not a map used for input
         $options['editLayer'] = false;
         if ($args['hide_grid'] == false) {
             // Now output a grid of the occurrences that were just saved.
             $r .= "<table class=\"submission\"><thead><tr><th>" . lang::get('Species') . "</th><th>" . lang::get('Latin Name') . "</th><th>" . lang::get('Abundance') . "</th><th>" . lang::get('Date') . "</th><th>" . lang::get('Spatial Ref') . "</th>" . "</th><th>" . lang::get('Comment') . "</th></tr></thead>\n";
             $r .= "<tbody>\n";
             foreach ($occurrence as $record) {
                 $r .= '<tr class="biota"><td>' . $record['taxon'] . '</td><td class="binomial"><em>' . $record['preferred_taxon'] . '</em></td><td>' . $record['abundance'] . '</td><td>' . $record['date'] . '</td><td>' . $record['entered_sref'] . '</td>' . $record['comment'] . "</td><td></tr>\n";
             }
             $r .= "</tbody></table>\n";
         }
     }
     if (!empty($args['add_another_link'])) {
         $path = $args['add_another_link'];
         if (count($occurrence) === 1) {
             $path = str_replace(array('#taxon_meaning_id#', '#external_key#'), array($occurrence[0]['taxon_meaning_id'], $occurrence[0]['external_key']), $path);
             $parts = explode('?', $path, 2);
             $parts[0] = url($parts[0]);
             $path = implode('?', $parts);
         }
         $r .= '<a class="indicia-button" href="' . $path . '">' . lang::get('Add another record') . '</a><br/>';
     }
     $r .= '<div id="mapandlegend">';
     $r .= map_helper::layer_list(array('id' => 'legend', 'includeSwitchers' => false, 'includeHiddenLayers' => false, 'includeIcons' => true, 'layerTypes' => array('overlay')));
     $r .= map_helper::map_panel($options, $olOptions);
     $r .= '</div>';
     return $r;
 }
 /**
  * Hierarchy map control, which can be added to user interface form configurations using [site_hierarchy_navigator.map].
  *
  * Display a map with polygons loaded onto it of a particular location type. When the user clicks on one, reloads the map layer
  * to show the intersecting polygons from the next location type. Continues down the locations hierarchy in a supplied sequence of 
  * location types (e.g. you might set the location type sequence to Country, County, Parish, Site). 
  *
  * Supply an option @layerLocationTypes with a comma separated array of the location types ID to load in top down order.
  */
 public function map($auth, $args, $tabalias, $options, $path)
 {
     global $base_root;
     //Setup the path to the cudi information sheets.
     //Include the parameter on the end of the path, but leave off the parameter values
     //as these will change for each path used.
     iform_load_helpers(array('map_helper', 'report_helper'));
     $informationSheetLinkParts = explode('|', $options['informationSheetLink']);
     $path = $base_root . base_path() . (variable_get('clean_url', 0) ? '' : '?q=') . $informationSheetLinkParts[0] . (variable_get('clean_url', 0) ? '?' : '&') . $informationSheetLinkParts[1] . '=';
     map_helper::$javascript .= "indiciaData.informationSheetLink='" . $path . "';\n";
     if (empty($options['layerLocationTypes'])) {
         return '<p>Please provide a @layerLocationTypes option for the [site_hierarchy_navigator.map] map control on the edit tab</p>';
     }
     $msg = self::check_format($options, 'layerLocationTypes', 'location_type_id (from the termlists term table)', '/^([0-9]*,\\s*)*[0-9]*\\s*$/');
     if ($msg !== true) {
         return $msg;
     }
     //This option is optional, so don't need to check if it isn't present
     $msg = self::check_format($options, 'showCountUnitsForLayers', 'location_type_id (from the termlists term table)', '/^([0-9]*,\\s*)*[0-9]*\\s*$/');
     if ($msg !== true) {
         return $msg;
     }
     drupal_add_js(iform_client_helpers_path() . 'prebuilt_forms/extensions/site_hierarchy_navigator.js');
     //The location types are supplied by the user in a comma seperated list.
     //The first number is used as the initial location type to display.
     //The second number is used after the user clicks the first time on a feature and so on
     $layerLocationTypes = explode(',', $options['layerLocationTypes']);
     //Comma seperated list of location types which signify which layers should also display the Count Unit location type.
     //This should be a subset of $layerLocationTypes.
     $showCountUnitsForLayers = explode(',', $options['showCountUnitsForLayers']);
     $locationTypesWithSymbols = explode(',', $options['locationTypesWithSymbols']);
     //Annotation location types as defined on edit tab
     $annotationTypeIds = explode(',', $options['annotationTypeIds']);
     $mapOptions = iform_map_get_map_options($args, $auth);
     $olOptions = iform_map_get_ol_options($args);
     $mapOptions['readAuth'] = $mapOptions['readAuth']['read'];
     $mapOptions['clickForSpatialRef'] = false;
     //When user clicks on map, run specified Javascript function
     $mapOptions['clickableLayersOutputMode'] = 'customFunction';
     $mapOptions['customClickFn'] = 'move_to_new_layer';
     $mapOptions['clickableLayersOutputDiv'] = '';
     //Tell the system which layers we to be clickable.
     $mapOptions['clickableLayers'] = array('indiciaData.reportlayer');
     $r .= map_helper::map_panel($mapOptions, $olOptions);
     map_helper::$javascript .= "indiciaData.layerLocationTypes=" . json_encode($layerLocationTypes) . ";\n";
     $reportOptions = array('dataSource' => 'reports_for_prebuilt_forms/CUDI/get_layer_list_names', 'readAuth' => $auth['read'], 'mode' => 'report', 'extraParams' => array('layer_ids' => $options['layerLocationTypes']));
     //Return a list of location type names for the location type id layers list
     //provided by the user in the form structure.
     $locationTypeNamesDirty = data_entry_helper::get_report_data($reportOptions);
     //The data returned by the database is not a simple array of names, so convert the data and put into correct order
     foreach ($layerLocationTypes as $originalLayerIndex => $layerLocationTypeFromOriginalList) {
         foreach ($locationTypeNamesDirty as $locationTypeNamesData) {
             if ($locationTypeNamesData['id'] === $layerLocationTypeFromOriginalList) {
                 $locationTypeNamesClean[$originalLayerIndex] = $locationTypeNamesData['name'];
             }
         }
     }
     //Send the array of names to javascript
     map_helper::$javascript .= "indiciaData.layerLocationTypesNames=" . json_encode($locationTypeNamesClean) . ";\n";
     //Send the user supplied options for layers to display count units to Javascript
     map_helper::$javascript .= "indiciaData.showCountUnitsForLayers=" . json_encode($showCountUnitsForLayers) . ";\n";
     map_helper::$javascript .= "indiciaData.countUnitBoundaryTypeId=" . $options['countUnitBoundaryTypeId'] . ";\n";
     map_helper::$javascript .= "indiciaData.annotationTypeIds=" . json_encode($annotationTypeIds) . ";\n";
     map_helper::$javascript .= "indiciaData.deactivateSiteAttributeId=" . $options['deactivateSiteAttributeId'] . ";\n";
     //Get translatable label for top-level breadcrub item.
     map_helper::$javascript .= "indiciaData.allSitesLabel='" . lang::get('All Sites') . "';\n";
     $reportOptions = array('linkOnly' => 'true', 'dataSource' => 'reports_for_prebuilt_forms/cudi/get_boundaries_and_locations_for_cudi_map', 'readAuth' => $auth['read']);
     //Get the report options such as the Preset Parameters on the Edit Tab
     $reportOptions = array_merge(iform_report_get_report_options($args, $readAuth), $reportOptions);
     //Run the report that shows the locations (features) to the user when the map loads the first time.
     map_helper::$javascript .= "indiciaData.layerReportRequest='" . report_helper::get_report_data($reportOptions) . "';\n";
     //Options for the report that is used to draw the map breadcrumb
     $reportOptions = array('linkOnly' => 'true', 'dataSource' => 'reports_for_prebuilt_forms/CUDI/get_map_hierarchy_for_current_position', 'readAuth' => $auth['read']);
     //Get the report options such as the Preset Parameters on the Edit Tab
     $reportOptions = array_merge(iform_report_get_report_options($args, $readAuth), $reportOptions);
     //Run the report that builds the map breadcrumb.
     map_helper::$javascript .= "indiciaData.breadcrumbReportRequest='" . report_helper::get_report_data($reportOptions) . "';\n";
     return $r;
 }
 private static function get_template_with_map($args, $readAuth, $extraParams, $paramDefaults)
 {
     $r = '<div id="outer-with-map" class="ui-helper-clearfix">';
     $r .= '<div id="grid" class="left" style="width:65%">{paramsForm}{grid}</div>';
     $r .= '<div id="map-and-record" class="right" style="width: 34%"><div id="summary-map">';
     $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;
     $options['featureIdField'] = 'occurrence_id';
     $r .= map_helper::map_panel($options, $olOptions);
     $reportMapOpts = array('dataSource' => !empty($args['mapping_report_name']) ? $args['mapping_report_name'] : $args['report_name'], 'mode' => 'report', 'readAuth' => $readAuth, 'autoParamsForm' => false, 'extraParams' => $extraParams, 'paramDefaults' => $paramDefaults, 'reportGroup' => 'verification', 'clickableLayersOutputMode' => 'report', 'rowId' => 'occurrence_id', 'sharing' => 'verification', 'ajax' => TRUE);
     if (!empty($args['mapping_report_name_lores'])) {
         $reportMapOpts['dataSourceLoRes'] = $args['mapping_report_name_lores'];
     }
     $r .= report_helper::report_map($reportMapOpts);
     $r .= '</div>';
     global $user;
     if (function_exists('hostsite_get_user_field') && ($locationId = hostsite_get_user_field('location_expertise', false))) {
         iform_map_zoom_to_location($locationId, $readAuth);
     }
     $r .= '<div id="record-details-wrap" class="ui-widget ui-widget-content">';
     $r .= self::instructions('grid on the left');
     $r .= '<div id="record-details-content" style="display: none">';
     $r .= '<div id="record-details-toolbar">';
     $r .= '<div id="verify-buttons">';
     $r .= '<div id="verify-buttons-inner">';
     $r .= '<label>' . lang::get('Actions:') . '</label>';
     $imgPath = empty(data_entry_helper::$images_path) ? data_entry_helper::relative_client_helper_path() . "../media/images/" : data_entry_helper::$images_path;
     $r .= '<button type="button" id="btn-verify" title="' . lang::get('Verify') . '"><img width="18" height="18" src="' . $imgPath . 'nuvola/ok-16px.png"/></button>';
     $r .= '<button type="button" id="btn-edit-verify" title="' . lang::get('Edit determination then verify') . '"><img width="18" height="18" src="' . $imgPath . 'nuvola/package_editors-16px.png"/>' . '<img width="18" height="18" src="' . $imgPath . 'nuvola/ok-16px.png"/></button>';
     $r .= '<button type="button" id="btn-reject" title="' . lang::get('Reject') . '"><img width="18" height="18" src="' . $imgPath . 'nuvola/cancel-16px.png"/></button>';
     $r .= '<button type="button" id="btn-query" title="' . lang::get('Query') . '"><img width="18" height="18" src="' . $imgPath . 'nuvola/dubious-16px.png"/></button>';
     $r .= '<div id="redet-dropdown-ctnr" style="display: none"><div id="redet-dropdown">';
     $r .= data_entry_helper::species_autocomplete(array('fieldname' => 'redet', 'label' => lang::get('New determination'), 'labelClass' => 'auto', 'helpText' => lang::get('Enter a new determination for this record before verifying it. The previous determination will be stored with the record.'), 'cacheLookup' => true, 'extraParams' => $readAuth + array('taxon_list_id' => 1), 'speciesIncludeBothNames' => true, 'speciesIncludeTaxonGroup' => true));
     $r .= '</div></div>';
     $r .= '</div></div>';
     $r .= '<label>Contact:</label>';
     $r .= '<button type="button" id="btn-email-expert" class="default-button">' . lang::get('Another expert') . '</button>';
     $r .= '<button type="button" id="btn-email-recorder" class="default-button">' . lang::get('Recorder') . '</button>';
     $r .= '</div>';
     $r .= '<div id="record-details-tabs">';
     // note - there is a dependency in the JS that comments is the last tab and media the 2nd to last.
     $r .= data_entry_helper::tab_header(array('tabs' => array('#details-tab' => lang::get('Details'), '#experience-tab' => lang::get('Experience'), '#phenology-tab' => lang::get('Phenology'), '#media-tab' => lang::get('Media'), '#comments-tab' => lang::get('Comments'))));
     data_entry_helper::$javascript .= "indiciaData.detailsTabs = ['details','experience','phenology','media','comments'];\n";
     data_entry_helper::enable_tabs(array('divId' => 'record-details-tabs'));
     $r .= '<div id="details-tab"></div>';
     $r .= self::other_tab_html();
     $r .= '</div></div></div></div></div>';
     return $r;
 }
 /**
  * Return the generated output.
  * @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 object $node The Drupal node object.
  * @param array $response When this form is reloading after saving a submission, contains the response from the service call.
  * Note this does not apply when redirecting (in this case the details of the saved object are in the $_GET data).
  * @return Form HTML.
  */
 public static function get_form($args, $node, $response = null)
 {
     iform_load_helpers(array('report_helper', 'map_helper'));
     $readAuth = report_helper::get_read_auth($args['website_id'], $args['password']);
     $sharing = 'reporting';
     $reportOptions = array_merge(iform_report_get_report_options($args, $readAuth), array('reportGroup' => 'explore', 'rememberParamsReportGroup' => 'explore', 'paramsOnly' => true, 'paramsInMapToolbar' => true, 'sharing' => $sharing, 'paramsFormButtonCaption' => lang::get('Filter'), 'rowId' => 'occurrence_id'));
     iform_report_apply_explore_user_own_preferences($reportOptions);
     $reportOptions['extraParams']['limit'] = 3000;
     $r = report_helper::report_grid($reportOptions);
     $r .= report_helper::report_map(array('readAuth' => $readAuth, 'dataSource' => $args['report_name'], 'extraParams' => $reportOptions['extraParams'], 'paramDefaults' => $reportOptions['paramDefaults'], 'autoParamsForm' => false, 'reportGroup' => 'explore', 'rememberParamsReportGroup' => 'explore', 'clickableLayersOutputMode' => 'report', 'sharing' => $sharing, 'rowId' => 'occurrence_id', 'ajax' => TRUE));
     $options = array_merge(iform_map_get_map_options($args, $readAuth), array('featureIdField' => 'occurrence_id', 'clickForSpatialRef' => false, 'reportGroup' => 'explore', 'toolbarDiv' => 'top'));
     $olOptions = iform_map_get_ol_options($args);
     $r .= map_helper::map_panel($options, $olOptions);
     $allowDownload = !isset($args['downloadOwnDataOnly']) || !$args['downloadOwnDataOnly'] || isset($reportOptions['extraParams']['ownData']) && $reportOptions['extraParams']['ownData'] === 1 || isset($_POST['explore-ownData']) && $_POST['explore-ownData'] === '1' || !(isset($_POST['explore-ownData']) || $_POST['explore-ownData'] === '0') && isset($reportOptions['paramDefaults']['ownData']) && $reportOptions['paramDefaults']['ownData'] === 1;
     $reportOptions = array_merge($reportOptions, array('id' => 'explore-records', 'paramsOnly' => false, 'autoParamsForm' => false, 'downloadLink' => $allowDownload, 'rowClass' => 'certainty{certainty}'));
     if (isset($args['includeEditLink']) && $args['includeEditLink'] && !empty($args['includeEditLinkPath'])) {
         $reportOptions['columns'][] = array('display' => 'Actions', 'actions' => array(array('caption' => 'edit', 'url' => url($args['includeEditLinkPath']), 'urlParams' => array('occurrence_id' => '{occurrence_id}'), 'visibility_field' => 'belongs_to_user')));
     }
     $r .= report_helper::report_grid($reportOptions);
     return $r;
 }
 /**
  * Return the generated output for the main sample 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_sample_tab($args, $nid, $auth, $attributes, &$packageAttr)
 {
     global $user;
     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');
     }
     // are there any option overrides for the custom attributes?
     if (isset($args['custom_attribute_options']) && $args['custom_attribute_options']) {
         $blockOptions = get_attr_options_array_with_user_data($args['custom_attribute_options']);
     } else {
         $blockOptions = array();
     }
     $systems = array();
     $list = explode(',', str_replace(' ', '', $args['spatial_systems']));
     foreach ($list as $system) {
         $systems[$system] = lang::get("sref:{$system}");
     }
     $options = iform_map_get_map_options($args, $auth['read']);
     $olOptions = iform_map_get_ol_options($args);
     if (!empty(data_entry_helper::$entity_to_load['sample:wkt'])) {
         $options['initialFeatureWkt'] = data_entry_helper::$entity_to_load['sample:wkt'];
     }
     if (!isset($options['standardControls'])) {
         $options['standardControls'] = array('layerSwitcher', 'panZoomBar');
     }
     $options['tabDiv'] = 'sample';
     // we pass through the read auth. This makes it possible for the get_submission method to authorise against the warehouse
     // without an additional (expensive) warehouse call, so it can get subsample details.
     $r = '<div id="sample">' . '<input type="hidden" name="website_id" value="' . $args['website_id'] . '"/>' . get_user_profile_hidden_inputs($attributes, $args, isset(data_entry_helper::$entity_to_load['sample:id']), $auth['read']) . data_entry_helper::text_input(array('label' => lang::get('Location Name'), 'fieldname' => 'sample:location_name', 'class' => 'control-width-5', 'validation' => array('required'))) . data_entry_helper::date_picker(array('label' => lang::get('Date'), 'fieldname' => 'sample:date')) . self::_build_package_control($args, $packageAttr) . get_attribute_html($attributes, $args, array('extraParams' => $auth['read']), null, $blockOptions) . data_entry_helper::textarea(array('fieldname' => 'sample:comment', 'label' => lang::get('Overall comment'))) . data_entry_helper::sref_and_system(array('label' => lang::get('Grid Reference'), 'systems' => $systems)) . '<p class="ui-state-highlight page-notice ui-corner-all">' . t('Use the search box to find a nearby town or village, then drag the map to pan and click on the map to set the centre grid reference of the transect. ' . 'Alternatively if you know the grid reference you can enter it in the Grid Ref box above: this will then be drawn automatically on the map.') . '</p>' . (isset(data_entry_helper::$entity_to_load['sample:id']) ? '' : data_entry_helper::georeference_lookup(array('label' => lang::get('Search for place'), 'driver' => $args['georefDriver'], 'georefPreferredArea' => $args['georefPreferredArea'], 'georefCountry' => $args['georefCountry'], 'georefLang' => $args['language'], 'readAuth' => $auth['read']))) . map_helper::map_panel($options, $olOptions) . (self::$readOnly ? '' : '<br/><input type="submit" value="' . lang::get('Save') . '" title="' . lang::get('Saves any data entered across all the tabs.') . '" />') . '</div>';
     return $r;
 }
 /**
  * Return the generated form output.
  * @return Form HTML.
  */
 public static function get_form($args)
 {
     iform_load_helpers(array('map_helper', 'data_entry_helper'));
     global $user;
     $readAuth = map_helper::get_read_auth($args['website_id'], $args['password']);
     // setup the map options
     $options = iform_map_get_map_options($args, $readAuth);
     $olOptions = iform_map_get_ol_options($args);
     if (!$args['show_all_species']) {
         if (isset($args['taxon_identifier']) && !empty($args['taxon_identifier'])) {
             // This page is for a predefined species map
             $taxonIdentifier = $args['taxon_identifier'];
         } else {
             if (isset($_GET['taxon'])) {
                 $taxonIdentifier = $_GET['taxon'];
             } else {
                 return lang::get("The distribution map cannot be displayed without a taxon identifier");
             }
         }
         if ($args['external_key'] == true) {
             if (empty($args['taxon_list_id'])) {
                 return lang::get('This form is configured with the Distribution Layer - External Key option ticked, but no species list has been configured to ' . 'lookup the external keys against.');
             }
             // the taxon identifier is an external key, so we need to translate to a meaning ID.
             $fetchOpts = array('table' => 'taxa_taxon_list', 'extraParams' => $readAuth + array('view' => 'detail', 'external_key' => $taxonIdentifier, 'taxon_list_id' => $args['taxon_list_id'], 'preferred' => true));
             $prefRecords = data_entry_helper::get_population_data($fetchOpts);
             // We might have multiple records back, e.g. if there are several photos, but we should have a unique meaning id.
             $meaningId = 0;
             foreach ($prefRecords as $prefRecord) {
                 if ($meaningId != 0 && $meaningId != $prefRecord['taxon_meaning_id']) {
                     // bomb out, as we  don't know which taxon to display
                     return lang::get("The taxon identifier cannot be used to identify a unique taxon.");
                 }
                 $meaningId = $prefRecord['taxon_meaning_id'];
             }
             if ($meaningId == 0) {
                 return lang::get("The taxon identified by the taxon identifier cannot be found.");
             }
             $meaningId = $prefRecords[0]['taxon_meaning_id'];
         } else {
             // the taxon identifier is the meaning ID.
             $meaningId = $taxonIdentifier;
         }
         // We still need to fetch the species record, to get its common name
         $fetchOpts = array('table' => 'taxa_taxon_list', 'extraParams' => $readAuth + array('view' => 'detail', 'language_iso' => iform_lang_iso_639_2(hostsite_get_user_field('language')), 'taxon_meaning_id' => $meaningId));
         $taxonRecords = data_entry_helper::get_population_data($fetchOpts);
     }
     $url = map_helper::$geoserver_url . 'wms';
     // Get the style if there is one selected
     $style = $args["wms_style"] ? ", styles: '" . $args["wms_style"] . "'" : '';
     map_helper::$onload_javascript .= "\n    var filter='website_id=" . $args['website_id'] . "';";
     if ($args['show_all_species']) {
         $layerTitle = lang::get('All species occurrences');
     } else {
         $layerTitle = str_replace('{species}', $taxonRecords[0]['taxon'], $args['layer_title']);
         map_helper::$onload_javascript .= "\n    filter += ' AND taxon_meaning_id={$meaningId}';\n";
     }
     if (!empty($args['cql_filter'])) {
         map_helper::$onload_javascript .= "\n    filter += ' AND(" . str_replace("'", "\\'", $args['cql_filter']) . ")';\n";
     }
     $layerTitle = str_replace("'", "\\'", $layerTitle);
     map_helper::$onload_javascript .= "\n    var distLayer = new OpenLayers.Layer.WMS(\r\n          '" . $layerTitle . "',\r\n          '{$url}',\r\n          {layers: '" . $args["wms_feature_type"] . "', transparent: true, CQL_FILTER: filter {$style}},\r\n          {isBaseLayer: false, sphericalMercator: true, singleTile: true}\r\n    );\n";
     $options['layers'][] = 'distLayer';
     if (isset($args['click_on_occurrences_mode']) && $args['click_on_occurrences_mode'] != 'none') {
         $options['clickableLayersOutputMode'] = $args['click_on_occurrences_mode'];
         $options['clickableLayersOutputDiv'] = 'getinfo-output';
         $options['clickableLayers'][] = 'distLayer';
         if (!empty($args['click_columns'])) {
             // convert the input column list argument to a structured array to pass to the map
             $inputarr = explode("\r\n", $args['click_columns']);
             $outputarr = array();
             foreach ($inputarr as $coldef) {
                 $coldef = explode('=', $coldef);
                 $outputarr[$coldef[0]] = $coldef[1];
             }
             $options['clickableLayersOutputColumns'] = $outputarr;
         }
     }
     // This is not a map used for input
     $options['editLayer'] = false;
     // if in Drupal, and IForm proxy is installed, then use this path as OpenLayers proxy
     if (defined('DRUPAL_BOOTSTRAP_CONFIGURATION') && module_exists('iform_proxy')) {
         global $base_url;
         $options['proxy'] = $base_url . '?q=' . variable_get('iform_proxy_path', 'proxy') . '&url=';
     }
     // output a legend
     if (isset($args['include_layer_list_types'])) {
         $layerTypes = explode(',', $args['include_layer_list_types']);
     } else {
         $layerTypes = array('base', 'overlay');
     }
     $r = '';
     if (!isset($args['include_layer_list']) || $args['include_layer_list']) {
         $r .= map_helper::layer_list(array('includeSwitchers' => isset($args['include_layer_list_switchers']) ? $args['include_layer_list_switchers'] : true, 'includeHiddenLayers' => true, 'layerTypes' => $layerTypes));
     }
     // output a map
     $r .= map_helper::map_panel($options, $olOptions);
     // add an empty div for the output of getinfo requests
     if (isset($args['click_on_occurrences_mode']) && $args['click_on_occurrences_mode'] == 'div') {
         $r .= '<div id="getinfo-output"></div>';
     }
     // Set up a page refresh for dynamic update of the map at set intervals
     if (!empty($args['refresh_timer']) && $args['refresh_timer'] !== 0 && is_numeric($args['refresh_timer'])) {
         // is_int prevents injection
         if (isset($args['load_on_refresh']) && !empty($args['load_on_refresh'])) {
             map_helper::$javascript .= "setTimeout('window.location=\"" . $args['load_on_refresh'] . "\";', " . $args['refresh_timer'] . "*1000 );\n";
         } else {
             map_helper::$javascript .= "setTimeout('window.location.reload( false );', " . $args['refresh_timer'] . "*1000 );\n";
         }
     }
     return $r;
 }