/**
  * 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, $node)
   {
       define("MODE_GRID", 0);
       define("MODE_NEW_SAMPLE", 1);
       define("MODE_EXISTING", 2);
       self::parse_defaults($args);
       self::getArgDefaults($args);
       self::$node = $node;
       // if we use locks, we want them to be distinct for each drupal user
       if (function_exists('profile_load_profile')) {
           // check we are in drupal
           global $user;
           data_entry_helper::$javascript .= "if (indicia && indicia.locks && indicia.locks.setUser) {\n        indicia.locks.setUser ('" . $user->uid . "');\n      }\n";
       }
       // hard-wire some 'dynamic' options to simplify the form. Todo: take out the dynamic code for these
       $args['subjectAccordion'] = false;
       $args['emailShow'] = false;
       $args['nameShow'] = false;
       $args['copyFromProfile'] = false;
       $args['multiple_subject_observation_mode'] = 'single';
       $args['extra_list_id'] = '';
       $args['occurrence_comment'] = false;
       $args['col_widths'] = '';
       $args['includeLocTools'] = false;
       $args['loctoolsLocTypeID'] = 0;
       $args['subject_observation_confidential'] = false;
       $args['observation_images'] = false;
       // Get authorisation tokens to update and read from the Warehouse.
       $auth = data_entry_helper::get_read_write_auth($args['website_id'], $args['password']);
       $svcUrl = self::warehouseUrl() . 'index.php/services';
       self::$auth = $auth;
       drupal_add_js(iform_media_folder_path() . 'js/jquery.form.js', 'module');
       $mode = isset($args['no_grid']) && $args['no_grid'] ? MODE_NEW_SAMPLE : MODE_GRID;
       // default mode when no grid set to false - display grid of existing data
       // mode MODE_EXISTING: display existing sample
       $loadedSampleId = null;
       $loadedSubjectObservationId = null;
       if ($_POST) {
           if (!array_key_exists('website_id', $_POST)) {
               // non Indicia POST, in this case must be the location allocations. add check to ensure we don't corrept the data by accident
               if (function_exists('iform_loctools_checkaccess') && iform_loctools_checkaccess($node, 'admin') && array_key_exists('mnhnld1', $_POST)) {
                   iform_loctools_deletelocations($node);
                   foreach ($_POST as $key => $value) {
                       $parts = explode(':', $key);
                       iform_loctools_insertlocation($node, $parts[2], $parts[1]);
                   }
               }
           } else {
               if (!is_null(data_entry_helper::$entity_to_load)) {
                   $mode = MODE_EXISTING;
                   // errors with new sample, entity populated with post, so display this data.
               }
           }
           // else valid save, so go back to gridview: default mode 0
       }
       if (array_key_exists('sample_id', $_GET) && $_GET['sample_id'] != '{sample_id}') {
           $mode = MODE_EXISTING;
           $loadedSampleId = $_GET['sample_id'];
       }
       if (array_key_exists('subject_observation_id', $_GET) && $_GET['subject_observation_id'] != '{subject_observation_id}') {
           $mode = MODE_EXISTING;
           // single subject_observation case
           $loadedSubjectObservationId = $_GET['subject_observation_id'];
           self::$subjectObservationIds = array($loadedSubjectObservationId);
       }
       if ($mode != MODE_EXISTING && array_key_exists('newSample', $_GET)) {
           $mode = MODE_NEW_SAMPLE;
           data_entry_helper::$entity_to_load = array();
       }
       // else default to mode MODE_GRID or MODE_NEW_SAMPLE depending on no_grid parameter
       self::$mode = $mode;
       // default mode  MODE_GRID : display grid of the samples to add a new one
       // or edit an existing one.
       if ($mode == MODE_GRID) {
           $r = '';
           // debug section
           if (!empty($args['debug_info']) && $args['debug_info']) {
               $r .= '<input type="button" value="Debug info" onclick="$(\'#debug-info-div\').slideToggle();" /><br />' . '<div id="debug-info-div" style="display: none;">';
               $r .= '<p>$_GET is:<br /><pre>' . print_r($_GET, true) . '</pre></p>';
               $r .= '<p>$_POST is:<br /><pre>' . print_r($_POST, true) . '</pre></p>';
               $r .= '<p>Entity to load is:<br /><pre>' . print_r(data_entry_helper::$entity_to_load, true) . '</pre></p>';
               $r .= '<p>Submission was:<br /><pre>' . print_r(self::$submission, true) . '</pre></p>';
               $r .= '<input type="button" value="Hide debug info" onclick="$(\'#debug-info-div\').slideToggle();" />';
               $r .= '</div>';
           }
           if (method_exists(get_called_class(), 'getHeaderHTML')) {
               $r .= call_user_func(array(get_called_class(), 'getHeaderHTML'), true, $args);
           }
           $attributes = data_entry_helper::getAttributes(array('valuetable' => 'sample_attribute_value', 'attrtable' => 'sample_attribute', 'key' => 'sample_id', 'fieldprefix' => 'smpAttr', 'extraParams' => $auth['read'], 'survey_id' => $args['survey_id']), false);
           $tabs = array('#sampleList' => lang::get('LANG_Main_Samples_Tab'));
           if ($args['includeLocTools'] && function_exists('iform_loctools_checkaccess') && iform_loctools_checkaccess($node, 'admin')) {
               $tabs['#setLocations'] = lang::get('LANG_Allocate_Locations');
           }
           if (method_exists(get_called_class(), 'getExtraGridModeTabs')) {
               $extraTabs = call_user_func(array(get_called_class(), 'getExtraGridModeTabs'), false, $auth['read'], $args, $attributes);
               if (is_array($extraTabs)) {
                   $tabs = $tabs + $extraTabs;
               }
           }
           if (count($tabs) > 1) {
               $r .= "<div id=\"controls\">" . data_entry_helper::enable_tabs(array('divId' => 'controls', 'active' => '#sampleList')) . "<div id=\"temp\"></div>";
               $r .= data_entry_helper::tab_header(array('tabs' => $tabs));
           }
           $r .= "<div id=\"sampleList\">" . call_user_func(array(get_called_class(), 'getSampleListGrid'), $args, $node, $auth, $attributes) . "</div>";
           if ($args['includeLocTools'] && function_exists('iform_loctools_checkaccess') && iform_loctools_checkaccess($node, 'admin')) {
               $r .= '
 <div id="setLocations">
   <form method="post">
     <input type="hidden" id="mnhnld1" name="mnhnld1" value="mnhnld1" /><table border="1"><tr><td></td>';
               $url = $svcUrl . '/data/location?mode=json&view=detail&auth_token=' . $auth['read']['auth_token'] . "&nonce=" . $auth['read']["nonce"] . "&parent_id=NULL&orderby=name" . (isset($args['loctoolsLocTypeID']) && $args['loctoolsLocTypeID'] != '' ? '&location_type_id=' . $args['loctoolsLocTypeID'] : '');
               $session = curl_init($url);
               curl_setopt($session, CURLOPT_RETURNTRANSFER, true);
               $entities = json_decode(curl_exec($session), true);
               $userlist = iform_loctools_listusers($node);
               foreach ($userlist as $uid => $a_user) {
                   $r .= '<td>' . $a_user->name . '</td>';
               }
               $r .= "</tr>";
               if (!empty($entities)) {
                   foreach ($entities as $entity) {
                       if (!$entity["parent_id"]) {
                           // only assign parent locations.
                           $r .= "<tr><td>" . $entity["name"] . "</td>";
                           $defaultuserids = iform_loctools_getusers($node, $entity["id"]);
                           foreach ($userlist as $uid => $a_user) {
                               $r .= '<td><input type="checkbox" name="location:' . $entity["id"] . ':' . $uid . (in_array($uid, $defaultuserids) ? '" checked="checked"' : '"') . '></td>';
                           }
                           $r .= "</tr>";
                       }
                   }
               }
               $r .= "</table>\n      <input type=\"submit\" class=\"ui-state-default ui-corner-all\" value=\"" . lang::get('LANG_Save_Location_Allocations') . "\" />\n    </form>\n  </div>";
           }
           if (method_exists(get_called_class(), 'getExtraGridModeTabs')) {
               $r .= call_user_func(array(get_called_class(), 'getExtraGridModeTabs'), true, $auth['read'], $args, $attributes);
           }
           if (count($tabs) > 1) {
               // close tabs div if present
               $r .= "</div>";
           }
           if (method_exists(get_called_class(), 'getTrailerHTML')) {
               $r .= call_user_func(array(get_called_class(), 'getTrailerHTML'), true, $args);
           }
           return $r;
       }
       // from this point on, we are MODE_EXISTING or MODE_NEW_SAMPLE
       if ($mode == MODE_EXISTING && is_null(data_entry_helper::$entity_to_load)) {
           // only load if not in error situation
           // Displaying an existing sample. If we know the subject_observation ID, and don't know the sample ID
           // then we must get the sample id from the subject_observation data.
           if ($loadedSubjectObservationId && !$loadedSampleId) {
               data_entry_helper::load_existing_record($auth['read'], 'subject_observation', $loadedSubjectObservationId);
               $loadedSampleId = data_entry_helper::$entity_to_load['subject_observation:sample_id'];
           }
           data_entry_helper::$entity_to_load = self::reload_form_data($loadedSampleId, $args, $auth);
       }
       // get the sample attributes
       $attrOpts = array('id' => data_entry_helper::$entity_to_load['sample:id'], 'valuetable' => 'sample_attribute_value', 'attrtable' => 'sample_attribute', 'key' => 'sample_id', 'fieldprefix' => 'smpAttr', 'extraParams' => $auth['read'], 'survey_id' => $args['survey_id']);
       // select only the custom attributes that are for this sample method or all sample methods, if this
       // form is for a specific sample method.
       if (!empty($args['sample_method_id'])) {
           $attrOpts['sample_method_id'] = $args['sample_method_id'];
       }
       $attributes = data_entry_helper::getAttributes($attrOpts, false);
       // Check if Recorder details is included as a control.
       // If so, remove the recorder attributes from the $attributes array so not output anywhere else.
       $arr = helper_base::explode_lines($args['structure']);
       if (in_array('[recorder details]', $arr)) {
           $attrCount = count($attributes);
           for ($i = 0; $i < $attrCount; $i++) {
               if (strcasecmp($attributes[$i]['caption'], 'first name') === 0 || strcasecmp($attributes[$i]['caption'], 'last name') === 0 || strcasecmp($attributes[$i]['caption'], 'email') === 0) {
                   unset($attributes[$i]);
               }
           }
       }
       //// Make sure the form action points back to this page
       $reload = data_entry_helper::get_reload_link_parts();
       unset($reload['params']['sample_id']);
       unset($reload['params']['subject_observation_id']);
       unset($reload['params']['newSample']);
       $reloadPath = $reload['path'];
       // don't url-encode the drupal path id using dirty url
       $pathParam = function_exists('variable_get') && variable_get('clean_url', 0) == '0' ? 'q' : '';
       if (count($reload['params'])) {
           if ($pathParam === 'q' && array_key_exists('q', $reload['params'])) {
               $reloadPath .= '?q=' . $reload['params']['q'];
               unset($reload['params']['q']);
               if (count($reload['params'])) {
                   $reloadPath .= '&' . http_build_query($reload['params']);
               }
           } else {
               $reloadPath .= '?' . http_build_query($reload['params']);
           }
       }
       $r = "<form method=\"post\" id=\"entry_form\" action=\"{$reloadPath}\">\n";
       // debug section
       if (!empty($args['debug_info']) && $args['debug_info']) {
           $r .= '<input type="button" value="Debug info" onclick="$(\'#debug-info-div\').slideToggle();" /><br />' . '<div id="debug-info-div" style="display: none;">';
           $r .= '<p>$_GET is:<br /><pre>' . print_r($_GET, true) . '</pre></p>';
           $r .= '<p>$_POST is:<br /><pre>' . print_r($_POST, true) . '</pre></p>';
           $r .= '<p>Entity to load is:<br /><pre>' . print_r(data_entry_helper::$entity_to_load, true) . '</pre></p>';
           $r .= '<p>Submission was:<br /><pre>' . print_r(self::$submission, true) . '</pre></p>';
           $r .= '<input type="button" value="Hide debug info" onclick="$(\'#debug-info-div\').slideToggle();" />';
           $r .= '</div>';
       }
       // reset button
       $r .= '<input type="button" class="ui-state-default ui-corner-all" value="' . lang::get('Abandon Form and Reload') . '" ' . 'onclick="window.location.href=\'' . url('node/' . $node->nid, array('query' => 'newSample')) . '\'">';
       // clear all padlocks button
       $r .= ' <input type="button" class="ui-state-default ui-corner-all" value="' . lang::get('Clear All Padlocks') . '" ' . 'onclick="if (indicia && indicia.locks) indicia.locks.unlockRegion(\'body\');">';
       // Get authorisation tokens to update the Warehouse, plus any other hidden data.
       $hiddens = $auth['write'] . "<input type=\"hidden\" id=\"read_auth_token\" name=\"read_auth_token\" value=\"" . $auth['read']['auth_token'] . "\" />\n" . "<input type=\"hidden\" id=\"read_nonce\" name=\"read_nonce\" value=\"" . $auth['read']['nonce'] . "\" />\n" . "<input type=\"hidden\" id=\"website_id\" name=\"website_id\" value=\"" . $args['website_id'] . "\" />\n" . "<input type=\"hidden\" id=\"survey_id\" name=\"survey_id\" value=\"" . $args['survey_id'] . "\" />\n";
       if (!empty($args['sample_method_id'])) {
           $hiddens .= '<input type="hidden" name="sample:sample_method_id" value="' . $args['sample_method_id'] . '"/>';
       }
       if (isset(data_entry_helper::$entity_to_load['sample:id'])) {
           $hiddens .= "<input type=\"hidden\" id=\"sample:id\" name=\"sample:id\" value=\"" . data_entry_helper::$entity_to_load['sample:id'] . "\" />\n";
       }
       // request automatic JS validation
       if (!isset($args['clientSideValidation']) || $args['clientSideValidation']) {
           data_entry_helper::enable_validation('entry_form');
           // override the default invalidHandler to activate the first accordion panels which has an error
           global $indicia_templates;
           $indicia_templates['invalid_handler_javascript'] = "function(form, validator) {\n          var tabselected=false;\n          var accordion\$=jQuery('.ui-accordion');\n          jQuery.each(validator.errorMap, function(ctrlId, error) {\n            // select the tab containing the first error control\n            var ctrl = jQuery('[name=' + ctrlId.replace(/:/g, '\\\\:').replace(/\\[/g, '\\\\[').replace(/]/g, '\\\\]') + ']');\n            if (!tabselected && typeof(tabs)!=='undefined') {\n              tabs.tabs('select',ctrl.filter('input,select').parents('.ui-tabs-panel')[0].id);\n              tabselected = true;\n            }\n            ctrl.parents('fieldset').removeClass('collapsed');\n            ctrl.parents('.fieldset-wrapper').show();\n            // for each accordion, activate the first panel which has an error\n            ctrl.parents('.ui-accordion-content').each(function (n) {\n              var acc\$ = \$(this).closest('.ui-accordion');\n              var accId = acc\$[0].id.replace(/:/g, '\\\\:').replace(/\\[/g, '\\\\[').replace(/]/g, '\\\\]');\n              if (accordion\$.is('#'+accId)) {\n                var header\$ = \$(this).prev('h3');\n                var accHeaderId = header\$.attr('id').replace(/:/g, '\\\\:').replace(/\\[/g, '\\\\[').replace(/]/g, '\\\\]');\n                acc\$.accordion('activate', '#'+accHeaderId);\n                accordion\$ = accordion\$.not('#'+accId);\n              }\n            });\n          });\n        }";
           // By default, validate doesn't validate any ':hidden' fields,
           // but we need to validate hidden with display: none; fields in accordions
           data_entry_helper::$javascript .= "jQuery.validator.setDefaults({ \n        ignore: \"input[type='hidden']\"\n      });\n";
       }
       if (method_exists(get_called_class(), 'getHeaderHTML')) {
           $r .= call_user_func(array(get_called_class(), 'getHeaderHTML'), true, $args);
       }
       if ($mode == MODE_EXISTING && ($loadedSampleId || $loadedSubjectObservationId)) {
           $existing = true;
       } else {
           $existing = false;
       }
       $hiddens .= get_user_profile_hidden_inputs($attributes, $args, $existing, $auth['read']);
       $customAttributeTabs = get_attribute_tabs($attributes);
       // remove added comment controls unless editing an existing sample
       if ($mode !== MODE_EXISTING || helper_base::$form_mode === 'ERRORS') {
           $controls = helper_base::explode_lines($args['structure']);
           $new_controls = array();
           foreach ($controls as $control) {
               if ($control !== '[show added sample comments]' && $control !== '[add sample comment]') {
                   $new_controls[] = $control;
               }
           }
           $args['structure'] = implode("\r\n", $new_controls);
       }
       $tabs = self::get_all_tabs($args['structure'], $customAttributeTabs);
       $r .= "<div id=\"controls\">\n";
       // Build a list of the tabs that actually have content
       $tabHtml = self::get_tab_html($tabs, $auth, $args, $attributes, $hiddens);
       // Output the dynamic tab headers
       if ($args['interface'] != 'one_page') {
           $headerOptions = array('tabs' => array());
           foreach ($tabHtml as $tab => $tabContent) {
               $alias = preg_replace('/[^a-zA-Z0-9]/', '', strtolower($tab));
               $tabtitle = lang::get("LANG_Tab_{$alias}");
               if ($tabtitle == "LANG_Tab_{$alias}") {
                   // if no translation provided, we'll just use the standard heading
                   $tabtitle = $tab;
               }
               $headerOptions['tabs']['#' . $alias] = $tabtitle;
           }
           $r .= data_entry_helper::tab_header($headerOptions);
           data_entry_helper::enable_tabs(array('divId' => 'controls', 'style' => $args['interface'], 'progressBar' => isset($args['tabProgress']) && $args['tabProgress'] == true));
       }
       // Output the dynamic tab content
       $pageIdx = 0;
       foreach ($tabHtml as $tab => $tabContent) {
           // get a machine readable alias for the heading
           $tabalias = preg_replace('/[^a-zA-Z0-9]/', '', strtolower($tab));
           $r .= '<div id="' . $tabalias . '">' . "\n";
           // For wizard include the tab title as a header.
           if ($args['interface'] == 'wizard') {
               $r .= '<h1>' . $headerOptions['tabs']['#' . $tabalias] . '</h1>';
           }
           $r .= $tabContent;
           // Add any buttons required at the bottom of the tab
           if ($args['interface'] == 'wizard') {
               $r .= data_entry_helper::wizard_buttons(array('divId' => 'controls', 'page' => $pageIdx === 0 ? 'first' : ($pageIdx == count($tabHtml) - 1 ? 'last' : 'middle')));
           } elseif ($pageIdx == count($tabHtml) - 1 && !($args['interface'] == 'tabs' && $args['save_button_below_all_pages'])) {
               // last part of a non wizard interface must insert a save button, unless it is tabbed interface with save button beneath all pages
               $r .= "<input type=\"submit\" class=\"ui-state-default ui-corner-all\" id=\"save-button\" value=\"" . lang::get('LANG_Save') . "\" />\n";
           }
           $pageIdx++;
           $r .= "</div>\n";
       }
       $r .= "</div>\n";
       if ($args['interface'] == 'tabs' && $args['save_button_below_all_pages']) {
           $r .= "<input type=\"submit\" class=\"ui-state-default ui-corner-all\" id=\"save-button\" value=\"" . lang::get('LANG_Save') . "\" />\n";
       }
       if (!empty(data_entry_helper::$validation_errors)) {
           $r .= data_entry_helper::dump_remaining_errors();
       }
       $r .= "</form>";
       if (method_exists(get_called_class(), 'getTrailerHTML')) {
           $r .= call_user_func(array(get_called_class(), 'getTrailerHTML'), true, $args);
       }
       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;
 }
 /**
  * Retrieve the additional HTML to appear at the top of the first
  * tab or form section. This is a set of hidden inputs containing the website ID and
  * survey ID as well as an existing location's ID.
  * @param type $args 
  */
 protected static function getFirstTabAdditionalContent($args, $auth, &$attributes)
 {
     // Get authorisation tokens to update the Warehouse, plus any other hidden data.
     $r = $auth['write'] . "<input type=\"hidden\" id=\"website_id\" name=\"website_id\" value=\"" . $args['website_id'] . "\" />\n" . "<input type=\"hidden\" id=\"survey_id\" name=\"survey_id\" value=\"" . $args['survey_id'] . "\" />\n";
     if (isset(data_entry_helper::$entity_to_load['location:id'])) {
         $r .= '<input type="hidden" id="location:id" name="location:id" value="' . data_entry_helper::$entity_to_load['location:id'] . '" />' . PHP_EOL;
     }
     $r .= get_user_profile_hidden_inputs($attributes, $args, isset(data_entry_helper::$entity_to_load['location:id']), $auth['read']);
     // pass through the group_id if set in URL parameters, so we can save the location against the group
     if (!empty($_GET['group_id'])) {
         $r .= "<input type=\"hidden\" id=\"group_id\" name=\"group_id\" value=\"" . $_GET['group_id'] . "\" />\n";
     }
     return $r;
 }
 protected static function getFirstTabAdditionalContent($args, $auth, &$attributes)
 {
     // Get authorisation tokens to update the Warehouse, plus any other hidden data.
     $r = $auth['write'] . "<input type=\"hidden\" id=\"website_id\" name=\"website_id\" value=\"" . $args['website_id'] . "\" />\n" . "<input type=\"hidden\" id=\"survey_id\" name=\"survey_id\" value=\"" . $args['survey_id'] . "\" />\n";
     if (!empty($args['sample_method_id'])) {
         $r .= '<input type="hidden" name="sample:sample_method_id" value="' . $args['sample_method_id'] . '"/>' . PHP_EOL;
     }
     if (isset(data_entry_helper::$entity_to_load['sample:id'])) {
         $r .= '<input type="hidden" id="sample:id" name="sample:id" value="' . data_entry_helper::$entity_to_load['sample:id'] . '" />' . PHP_EOL;
     }
     if (isset(data_entry_helper::$entity_to_load['occurrence:id'])) {
         $r .= '<input type="hidden" id="occurrence:id" name="occurrence:id" value="' . data_entry_helper::$entity_to_load['occurrence:id'] . '" />' . PHP_EOL;
     }
     // Check if Record Status is included as a control. If not, then add it as a hidden.
     $arr = helper_base::explode_lines($args['structure']);
     if (!in_array('[record status]', $arr)) {
         $value = isset($args['defaults']['occurrence:record_status']) ? $args['defaults']['occurrence:record_status'] : 'C';
         $r .= '<input type="hidden" id="occurrence:record_status" name="occurrence:record_status" value="' . $value . '" />' . PHP_EOL;
     }
     $r .= get_user_profile_hidden_inputs($attributes, $args, isset(data_entry_helper::$entity_to_load['sample:id']), $auth['read']);
     return $r;
 }
示例#6
0
 /**
  * Overridable function to retrieve the additional HTML to appear at the top of the first
  * tab or form section. This is normally a set of hidden inputs, containing things like the
  * website ID to post with a form submission.
  * @param type $args 
  */
 protected static function getFirstTabAdditionalContent($args, $auth, &$attributes)
 {
     // Get authorisation tokens to update the Warehouse, plus any other hidden data.
     $r = $auth['write'] . "<input type=\"hidden\" id=\"website_id\" name=\"website_id\" value=\"" . $args['website_id'] . "\" />\n" . "<input type=\"hidden\" id=\"survey_id\" name=\"survey_id\" value=\"" . $args['survey_id'] . "\" />\n";
     $r .= get_user_profile_hidden_inputs($attributes, $args, isset(data_entry_helper::$entity_to_load['sample:id']), $auth['read']);
     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'];
         }
     }
     $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="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'] . '"/>';
     // pass a param that sets the next page to display
     $r .= '<input type="hidden" name="page" value="grid"/>';
     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>' . $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.
         $locationTypes = helper_base::get_termlist_terms($auth, 'indicia:location_types', array('Transect', 'Transect Section'));
         $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' => $locationTypes[0]['id'], '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 hidden sref fields updated
         $sitesLookup = array();
         $sitesJs = array();
         foreach ($availableSites as $site) {
             $sitesLookup[$site['location_id']] = $site['name'];
             $sitesJs[$site['location_id']] = array('centroid_sref' => $site['centroid_sref'], 'centroid_sref_system' => $site['centroid_sref_system']);
         }
         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="date-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?
     $blockOptions = array();
     if (isset($args['custom_attribute_options']) && $args['custom_attribute_options']) {
         $blockOptionList = explode("\n", $args['custom_attribute_options']);
         foreach ($blockOptionList as $opt) {
             $tokens = explode('|', $opt);
             $optvalue = explode('=', $tokens[1]);
             $blockOptions[$tokens[0]][$optvalue[0]] = $optvalue[1];
         }
     }
     $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') . '" class="ui-state-default ui-corner-all" />';
     $r .= '</form>';
     data_entry_helper::enable_validation('sample');
     return $r;
 }
 public static function get_sample_form($args, $node, $response)
 {
     global $user;
     iform_load_helpers(array('map_helper'));
     $auth = data_entry_helper::get_read_write_auth($args['website_id'], $args['password']);
     // either looking at existing, creating a new one, or an error occurred: no successful posts...
     // first check some conditions are met
     $sampleMethods = helper_base::get_termlist_terms($auth, 'indicia:sample_methods', array('Timed Count'));
     if (count($sampleMethods) == 0) {
         return 'The sample method "Timed Count" must be defined in the termlist in order to use this form.';
     }
     $sampleId = isset($_GET['sample_id']) ? $_GET['sample_id'] : null;
     if ($sampleId && !isset(data_entry_helper::$validation_errors)) {
         data_entry_helper::load_existing_record($auth['read'], 'sample', $sampleId);
     }
     $isAdmin = isset($args['manager_permission']) && user_access($args['manager_permission']);
     // The following is butchered from mnhnl.
     data_entry_helper::$javascript .= "\r\n// the default edit layer is used for this sample\r\nvar editLayer = null;\r\n\r\nconvertGeom = function(geom, projection){\r\n  if (projection.projcode!='EPSG:900913' && projection.projcode!='EPSG:3857') {\r\n    var cloned = geom.clone();\r\n    return cloned.transform(new OpenLayers.Projection('EPSG:900913'), projection);\r\n  }\r\n  return geom;\r\n}\r\nreverseConvertGeom = function(geom, projection){\r\n  if (projection.projcode!='EPSG:900913' && projection.projcode!='EPSG:3857') {\r\n    var cloned = geom.clone();\r\n    return cloned.transform(projection, new OpenLayers.Projection('EPSG:900913'));\r\n  }\r\n  return geom;\r\n}\r\n\r\ngetwkt = function(geometry, incFront, incBrackets){\r\n  var retVal;\r\n  \t  retVal = '';\r\n  \t  switch(geometry.CLASS_NAME){\r\n  \t  case \"OpenLayers.Geometry.Point\":\r\n  \t  return((incFront!=false ? 'POINT' : '')+(incBrackets!=false ? '(' : '')+geometry.x+' '+geometry.y+(incBrackets!=false ? ')' : ''));\r\n  \t  break;\r\n  \t  case \"OpenLayers.Geometry.MultiPoint\":\r\n      retVal = 'MULTIPOINT(';\r\n      for(var i=0; i< geometry.components.length; i++)\r\n        retVal += (i!=0 ? ',':'')+getwkt(geometry.components[i], false, true);\r\n      retVal += ')';\r\n      break;\r\n    case \"OpenLayers.Geometry.LineString\":\r\n      retVal = (incFront!=false ? 'LINESTRING' : '')+'(';\r\n      for(var i=0; i< geometry.components.length; i++)\r\n        retVal += (i!=0 ? ',':'')+getwkt(geometry.components[i], false, false);\r\n      retVal += ')';\r\n      break;\r\n    case \"OpenLayers.Geometry.MultiLineString\":\r\n      retVal = 'MULTILINESTRING(';\r\n      for(var i=0; i< geometry.components.length; i++)\r\n        retVal += (i!=0 ? ',':'')+getwkt(geometry.components[i], false, true);\r\n      retVal += ')';\r\n      break;\r\n    case \"OpenLayers.Geometry.Polygon\": // only do outer ring\r\n      retVal = (incFront!=false ? 'POLYGON' : '')+'((';\r\n      for(var i=0; i< geometry.components[0].components.length; i++)\r\n        retVal += (i!=0 ? ',':'')+getwkt(geometry.components[0].components[i], false, false);\r\n      retVal += '))';\r\n      break;\r\n    case \"OpenLayers.Geometry.MultiPolygon\":\r\n      retVal = 'MULTIPOLYGON(';\r\n      for(var i=0; i< geometry.components.length; i++)\r\n        retVal += (i!=0 ? ',':'')+getwkt(geometry.components[i], false, true);\r\n      retVal += ')';\r\n      break;\r\n    case \"OpenLayers.Geometry.Collection\":\r\n      retVal = 'GEOMETRYCOLLECTION(';\r\n      for(var i=0; i< geometry.components.length; i++)\r\n        retVal += (i!=0 ? ',':'')+getwkt(geometry.components[i], true, true);\r\n      retVal += ')';\r\n      break;\r\n  }\r\n  return retVal;\r\n}\r\nsetSref = function(geometry){\r\n  var centre = getCentroid(geometry);\r\n  centre = reverseConvertGeom(centre, editLayer.map.projection); // convert to indicia internal projection\r\n  var system = \$('#imp-sref-system').val();\t\t\t\t\r\n  jQuery.getJSON('" . data_entry_helper::$base_url . "/index.php/services/spatial/wkt_to_sref?wkt=POINT(' + centre.x + '  ' + centre.y + ')&system=' + system + '&precision=" . (isset($args['precision']) && $args['precision'] != '' ? $args['precision'] : '8') . "&callback=?',\r\n      function(data){\r\n        if(typeof data.error != 'undefined')\r\n          alert(data.error);\r\n        else\r\n          \$('#imp-sref').val(data.sref);\r\n       });\r\n};\r\nhook_setGeomFields = [];\r\nsetGeomFields = function(){\r\n  var geomstack = [];\r\n  var completeGeom;\r\n  for(var i=0; i<editLayer.features.length; i++)\r\n    if(editLayer.features[i].attributes.highlighted == true)\r\n      geomstack.push(editLayer.features[i].geometry.clone()); // needs to be a clone as we don't want to transform the original geoms.\r\n  if(geomstack.length == 0){\r\n    jQuery('#imp-geom').val('');\r\n    jQuery('#imp-sref').val('');\r\n    return;\r\n  } else if (geomstack.length == 1)\r\n    completeGeom = geomstack[0];\r\n  else\r\n    completeGeom = new OpenLayers.Geometry.Collection(geomstack);\r\n  // the geometry is in the map projection: if this doesn't match indicia's internal one, then must convert.\r\n  if (editLayer.map.projection.projcode!='EPSG:900913' && editLayer.map.projection.projcode!='EPSG:3857') \r\n    completeGeom.transform(editLayer.map.projection,  new OpenLayers.Projection('EPSG:900913'));\r\n  jQuery('#imp-geom').val(getwkt(completeGeom, true, true));\r\n  setSref(getCentroid(completeGeom));\r\n  if(hook_setGeomFields.length > 0)\r\n    for(i=0; i< hook_setGeomFields.length; i++)\r\n  \t  (hook_setGeomFields[i])(completeGeom);\r\n}\r\nremoveDrawnGeom = function(){\r\n  var highlighted=gethighlight();\r\n  if(highlighted.length > 0) {\r\n    unhighlightAll();\r\n  }\r\n  for(var i=editLayer.features.length-1; i>=0; i--)\r\n    editLayer.destroyFeatures([editLayer.features[i]]);\r\n}\r\nreplaceGeom = function(feature, layer, modControl, geom, highlight, setFields){\r\n  if(modControl.feature)\r\n    modControl.unselectFeature(modControl.feature);\r\n  var newfeature = new OpenLayers.Feature.Vector(geom, {});\r\n  newfeature.attributes = feature.attributes;\r\n  layer.destroyFeatures([feature]);\r\n  layer.addFeatures([newfeature]);\r\n  modControl.selectFeature(newfeature);\r\n  selectFeature.highlight(newfeature);\r\n  newfeature.attributes.highlighted=true;\r\n  if(setFields) setGeomFields();\r\n}\r\naddAndSelectNewGeom = function(layer, modControl, geom, highlight){\r\n  var feature = new OpenLayers.Feature.Vector(geom, {highlighted: false, ours: true});\r\n  layer.addFeatures([feature]);\r\n  modControl.selectFeature(feature);\r\n  feature.attributes.highlighted=true;\r\n  selectFeature.highlight(feature);\r\n  setGeomFields();\r\n  return feature;\r\n}\r\naddToExistingFeatureSet = function(existingFeatures, layer, modControl, geom, highlight){\r\n  var feature = new OpenLayers.Feature.Vector(geom, {});\r\n  feature.attributes = existingFeatures[0].attributes;\r\n  layer.addFeatures([feature]);\r\n  modControl.selectFeature(feature);\r\n  selectFeature.highlight(feature);\r\n  feature.attributes.highlighted=true;\r\n  setGeomFields();\r\n}\r\nunhighlightAll = function(){\r\n  if(modAreaFeature.feature) modAreaFeature.unselectFeature(modAreaFeature.feature);\r\n  var highlighted = gethighlight();\r\n  for(var i=0; i<highlighted.length; i++) {\r\n    highlighted[i].attributes.highlighted = false;\r\n    selectFeature.unhighlight(highlighted[i]);\r\n  }\r\n}\r\ngethighlight = function(){\r\n  var features=[];\r\n  for(var i=0; i<editLayer.features.length; i++){\r\n    if(editLayer.features[i].attributes.highlighted==true){\r\n      features.push(editLayer.features[i]);\r\n    }}\r\n  return features;\r\n}\r\n\r\naddDrawnPolygonToSelection = function(geometry) {\r\n  var points = geometry.components[0].getVertices();\r\n  if(points.length < 3){\r\n    alert(\"" . lang::get('LANG_TooFewPoints') . "\");\r\n    return false;\r\n  }\r\n  var highlightedFeatures = gethighlight();\r\n  if(highlightedFeatures.length == 0){\r\n    // No currently selected feature. Create a new one.\r\n    feature = addAndSelectNewGeom(editLayer, modAreaFeature, geometry, true);\r\n  \treturn true;\r\n  }\r\n  var selectedFeature = false;\r\n  for(var i=0; i<highlightedFeatures.length; i++){\r\n    if(highlightedFeatures[i].geometry.CLASS_NAME == \"OpenLayers.Geometry.Polygon\" ||\r\n        highlightedFeatures[i].geometry.CLASS_NAME == \"OpenLayers.Geometry.MultiPolygon\") {\r\n      selectedFeature = highlightedFeatures[i];\r\n  \t        \t\tbreak;\r\n    }}\r\n  // a site is already selected so the Drawn/Specified state stays unaltered\r\n  if(!selectedFeature) {\r\n      addToExistingFeatureSet(highlightedFeatures, editLayer, modAreaFeature, geometry, true);\r\n      return true;\r\n  }\r\n  if(selectedFeature.geometry.CLASS_NAME == \"OpenLayers.Geometry.MultiPolygon\") {\r\n    if(modAreaFeature.feature)\r\n\t    modAreaFeature.unselectFeature(selectedFeature);\r\n    selectedFeature.geometry.addComponents([geometry]);\r\n    modAreaFeature.selectFeature(selectedFeature);\r\n    selectFeature.highlight(selectedFeature);\r\n    selectedFeature.attributes.highlighted = true;\r\n    setGeomFields();\r\n  } else { // is OpenLayers.Geometry.Polygon\r\n    var CompoundGeom = new OpenLayers.Geometry.MultiPolygon([selectedFeature.geometry, geometry]);\r\n    replaceGeom(selectedFeature, editLayer, modAreaFeature, CompoundGeom, true, true);\r\n  }\r\n  return true;\r\n}\r\nonFeatureModified = function(evt) {\r\n  var feature = evt.feature;\r\n  switch(feature.geometry.CLASS_NAME){\r\n    case \"OpenLayers.Geometry.Polygon\": // only do outer ring\r\n      points = feature.geometry.components[0].getVertices();\r\n      if(points.length < 3){\r\n        alert(\"" . lang::get('There are now too few vertices to make a polygon: it will now be completely removed.') . "\");\r\n        modAreaFeature.unselectFeature(feature);\r\n        editLayer.destroyFeatures([feature]);\r\n      }\r\n      break;\r\n    case \"OpenLayers.Geometry.MultiPolygon\":\r\n  \t  for(i=feature.geometry.components.length-1; i>=0; i--) {\r\n        points = feature.geometry.components[i].components[0].getVertices();\r\n        if(points.length < 3){\r\n          alert(\"" . lang::get('There are now too few vertices to make a polygon: it will now be completely removed.') . "\");\r\n  \t      var selectedFeature = modAreaFeature.feature;\r\n          modAreaFeature.unselectFeature(selectedFeature);\r\n          selectFeature.unhighlight(selectedFeature);\r\n          editLayer.removeFeatures([selectedFeature]);\r\n          selectedFeature.geometry.removeComponents([feature.geometry.components[i]]);\r\n  \t      editLayer.addFeatures([selectedFeature]);\r\n          modAreaFeature.selectFeature(selectedFeature);\r\n          selectFeature.highlight(selectedFeature);\r\n          selectedFeature.attributes.highlighted = true;\r\n        }\r\n      }\r\n      if(feature.geometry.components.length == 0){\r\n        modAreaFeature.unselectFeature(feature);\r\n        editLayer.destroyFeatures([feature]);\r\n      }\r\n      break;\r\n  }\r\n  setGeomFields();\r\n}\r\n/********************************/\r\n/* Define Map Control callbacks */\r\n/********************************/\r\nUndoSketchPoint = function(layer){\r\n  for(var i = editControl.controls.length-1; i>=0; i--)\r\n    if(editControl.controls[i].CLASS_NAME == \"OpenLayers.Control.DrawFeature\" && editControl.controls[i].active)\r\n      editControl.controls[i].undo();\r\n};\r\nRemoveNewSite = function(){\r\n  highlighted = gethighlight();\r\n  removeDrawnGeom(highlighted[0].attributes.SiteNum);\r\n  setGeomFields();\r\n};\r\nZoomToFeature = function(feature){\r\n  var div = jQuery('#map')[0];\r\n  var bounds=feature.geometry.bounds.clone();\r\n  // extend the boundary to include a buffer, so the map does not zoom too tight.\r\n  var dy = (bounds.top-bounds.bottom) * div.settings.maxZoomBuffer;\r\n  var dx = (bounds.right-bounds.left) * div.settings.maxZoomBuffer;\r\n  bounds.top = bounds.top + dy;\r\n  bounds.bottom = bounds.bottom - dy;\r\n  bounds.right = bounds.right + dx;\r\n  bounds.left = bounds.left - dx;\r\n  if (div.map.getZoomForExtent(bounds) > div.settings.maxZoom) {\r\n    // if showing something small, don't zoom in too far\r\n    div.map.setCenter(bounds.getCenterLonLat(), div.settings.maxZoom);\r\n  } else {\r\n    // Set the default view to show something triple the size of the grid square\r\n    // Assume this is within the map extent\r\n    div.map.zoomToExtent(bounds);\r\n  }\r\n};\r\n/***********************************/\r\n/* Define Controls for use on Map. */\r\n/***********************************/\r\npolygonDrawActivate = function(){\r\n  selectFeature.deactivate();\r\n  modAreaFeature.activate();\r\n  highlighted = gethighlight();\r\n  if(highlighted.length == 0)\r\n    return true;\r\n  for(var i=0; i<editLayer.features.length; i++)\r\n      if(editLayer.features[i].attributes.highlighted == true)\r\n        modAreaFeature.selectFeature(editLayer.features[i]);\r\n  return true;\r\n};\r\n\t\t         \t\t \t\t\r\nmodAreaFeature = null;\r\nselectFeature = null;\r\npolygonDraw = null;\r\neditControl = null;\r\n\r\nmapInitialisationHooks.push(function(mapdiv) {\r\n\t\$('#imp-sref').unbind('change');\r\n\teditLayer=mapdiv.map.editLayer;\r\n    var nav=new OpenLayers.Control.Navigation({displayClass: \"olControlNavigation\", \"title\":mapdiv.settings.hintNavigation+((!mapdiv.settings.scroll_wheel_zoom || mapdiv.settings.scroll_wheel_zoom===\"false\")?'': mapdiv.settings.hintScrollWheel)});\t\r\n\teditControl = new OpenLayers.Control.Panel({allowDepress: false, 'displayClass':'olControlEditingToolbar'});\r\n\tmapdiv.map.addControl(editControl);\r\n" . ($isAdmin || $sampleId == null ? "  \tmodAreaFeature = new OpenLayers.Control.ModifyFeature(editLayer,{standalone: true});\r\n\tselectFeature = new OpenLayers.Control.SelectFeature([editLayer],{standalone: true});\r\n\tpolygonDraw = new OpenLayers.Control.DrawFeature(editLayer,OpenLayers.Handler.Polygon,{'displayClass':'olControlDrawFeaturePolygon', drawFeature: addDrawnPolygonToSelection, title: '" . lang::get('Select this tool to draw a polygon, clicking on the map to place the vertices of the shape, and double clicking on the final vertex to finish. You may drag and drop vertices (circles) to move them, and draw more than one polygon, i.e. input a discontinuous site.') . "'});\r\n\tpolygonDraw.events.on({'activate': polygonDrawActivate});\r\n\teditControl.addControls([polygonDraw\r\n\t\t\t\t         ,new OpenLayers.Control.Button({displayClass: \"olControlClearLayer\", trigger: RemoveNewSite, title: '" . lang::get('Press this button to completely remove the currently drawn site.') . "'})\r\n    \t\t\t\t\t ,nav\t\r\n\t\t\t\t         ,new OpenLayers.Control.Button({displayClass: \"olControlUndo\", trigger: UndoSketchPoint, title: '" . lang::get('If you have not completed a polygon, press this button to clear the last vertex. If you have completed a polygon but wish to remove a vertex, place the mouse over the vertex and press the Delete button: this only works for the corner vertices, not the dummy ones half way down each side.') . "'})\r\n    ]);\r\n\tmapdiv.map.addControl(modAreaFeature);\r\n\tmodAreaFeature.deactivate();\r\n\tfor(var i=0; i<mapdiv.map.controls.length; i++)\r\n      mapdiv.map.controls[i].deactivate();\r\n\teditControl.activate();\r\n\tnav.activate();\r\n\t// any existing features come from the existing sites geometry: convert to ours\r\n    // will have been zoomed as well.\r\n\tfor(var i=0; i<editLayer.features.length; i++) {\r\n\t  editLayer.features[i].attributes.highlighted = true;\r\n\t  editLayer.features[i].attributes.type = 'ours';\r\n\t  editLayer.features[i].attributes.ours = true;\r\n\t  selectFeature.highlight(editLayer.features[i]);\r\n\t}\t\t\t\t         \t\t\r\n\teditLayer.events.on({\r\n\t\t'featuremodified': onFeatureModified\r\n\t});\r\n" : "\teditControl.addControls([nav]);\r\n\tfor(var i=0; i<mapdiv.map.controls.length; i++)\r\n      mapdiv.map.controls[i].deactivate();\r\n\teditControl.activate();\r\n\tnav.activate();\r\n") . "\tmapdiv.map.events.triggerEvent('zoomend');\r\n});\r\n";
     $r = '<form method="post" id="sample">' . $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="read_nonce" value="' . $auth['read']['nonce'] . '"/>';
     $r .= '<input type="hidden" name="read_auth_token" value="' . $auth['read']['auth_token'] . '"/>';
     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'] . '"/>';
     }
     // pass a param that sets the next page to display
     $r .= "<input type=\"hidden\" name=\"website_id\" value=\"" . $args['website_id'] . "\"/>\r\n<input type=\"hidden\" name=\"sample:survey_id\" value=\"" . $args['survey_id'] . "\"/>\r\n<input type=\"hidden\" name=\"page\" value=\"site\"/>";
     $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, isset(data_entry_helper::$entity_to_load['sample:id']), $auth['read']) . data_entry_helper::text_input(array('label' => lang::get('Site Name'), 'fieldname' => 'sample:location_name', 'validation' => array('required')));
     $help = lang::get('The Year field is read-only, and is calculated automatically from the date(s) of the Counts.');
     $r .= '<p class="ui-state-highlight page-notice ui-corner-all">' . $help . '</p>';
     if ($sampleId == null) {
         if (isset($_GET['date'])) {
             data_entry_helper::$entity_to_load['C1:sample:date'] = $_GET['date'];
         }
         $r .= data_entry_helper::date_picker(array('label' => lang::get('Date of first count'), 'fieldname' => 'C1:sample:date', 'validation' => array('required', 'date')));
         data_entry_helper::$javascript .= "jQuery('#C1\\\\:sample\\\\:date').change(function(){\r\n  jQuery('#sample\\\\:date').val(jQuery(this).val() == '' ? '' : jQuery(this).datepicker('getDate').getFullYear());\r\n});\r\nif(jQuery('#C1\\\\:sample\\\\:date').val() != '') jQuery('#sample\\\\:date').val(jQuery('#C1\\\\:sample\\\\:date').datepicker('getDate').getFullYear());\n";
     }
     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) - only interested in Year.
         $d = new DateTime(data_entry_helper::$entity_to_load['sample:date']);
         data_entry_helper::$entity_to_load['sample:date'] = $d->format('Y');
     }
     unset(data_entry_helper::$default_validation_rules['sample:date']);
     $r .= data_entry_helper::text_input(array('label' => lang::get('Year'), 'fieldname' => 'sample:date', 'readonly' => ' readonly="readonly" '));
     // 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);
     foreach ($blockOptions as $attr => $block) {
         foreach ($block as $item => $value) {
             switch ($item) {
                 case 'suffix':
                     data_entry_helper::$javascript .= "\$('#" . str_replace(':', '\\\\:', $attr) . "').after(' <label style=\"width:auto\">" . $value . "</label>');\n";
                     break;
                 case 'setArea':
                     $parts = explode(',', $value);
                     // 0=factor,1=number decimal places
                     data_entry_helper::$javascript .= "\$('#" . str_replace(':', '\\\\:', $attr) . "').attr('readonly','readonly');\nhook_setGeomFields.push(function(geom){\n\$('#" . str_replace(':', '\\\\:', $attr) . "').val(\n(geom.getArea()/" . $parts[0] . ").toFixed(" . $parts[1] . "));\n});\n";
                     break;
             }
         }
     }
     $r .= '<input type="hidden" name="sample:sample_method_id" value="' . $sampleMethods[0]['id'] . '" />';
     $help = lang::get('Now draw the flight area for the timed count on the map below. The Grid Reference is filled in automatically when the site is drawn.');
     $r .= '<p class="ui-state-highlight page-notice ui-corner-all">' . $help . '</p>';
     $options = iform_map_get_map_options($args, $auth['read']);
     $options['clickForSpatialRef'] = false;
     $olOptions = iform_map_get_ol_options($args);
     $systems = array();
     $list = explode(',', str_replace(' ', '', $args['spatial_systems']));
     foreach ($list as $system) {
         $systems[$system] = lang::get($system);
     }
     $r .= "<label for=\"imp-sref\">" . lang::get('Grid Reference') . ":</label> <input type=\"text\" id=\"imp-sref\" name=\"sample:entered_sref\" value=\"" . data_entry_helper::$entity_to_load['sample:entered_sref'] . "\" readonly=\"readonly\" class=\"required\" />";
     $r .= "<input type=\"hidden\" id=\"imp-geom\" name=\"sample:geom\" value=\"" . data_entry_helper::$entity_to_load['sample:geom'] . "\" />";
     if (count($systems) == 1) {
         // Hidden field for the system
         $keys = array_keys($systems);
         $r .= "<input type=\"hidden\" id=\"imp-sref-system\" name=\"sample:entered_sref_system\" value=\"" . $keys[0] . "\" />\n";
     } else {
         $r .= self::sref_system_select(array('fieldname' => 'sample:entered_sref_system'));
     }
     $r .= '<br />' . data_entry_helper::georeference_lookup(iform_map_get_georef_options($args, $auth['read']));
     $r .= data_entry_helper::map_panel($options, $olOptions);
     $r .= data_entry_helper::textarea(array('label' => 'Comment', 'fieldname' => 'sample:comment', 'class' => 'wide'));
     $r .= '<input type="submit" value="' . lang::get('Next') . '" />';
     $r .= '<a href="' . $args['summary_page'] . '"><button type="button" class="ui-state-default ui-corner-all" />' . lang::get('Cancel') . '</button></a>';
     // allow deletes if sample id is present: i.e. existing sample.
     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>';
         // note we only require bare minimum in order to flag a sample as deleted.
         $r .= '</form><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"/>';
         data_entry_helper::$javascript .= "jQuery('#delete-button').click(function(){\r\n  if(confirm(\"" . lang::get('Are you sure you want to delete this timed count?') . "\"))\r\n    jQuery('#delete-form').submit();\r\n});\n";
     }
     $r .= '</form>';
     data_entry_helper::enable_validation('sample');
     return $r;
 }
 /**
  * Get authorisation tokens to update the Warehouse, plus any other hidden
  * form inputs.
  * @param array $args The form settings.
  * @param array $auth Authorisation to access the warehouse.
  * @return string
  */
 protected static function renderHiddenInputs($args, $auth)
 {
     $r = "";
     // If mobile authentication enabled then add appname and appsecret.
     // Else - Authorisation tokens.
     if ($args['mobileauth'] == 1) {
         $r .= mobile_entry_helper::apply_template('auth', array('appname' => $args['appname'], 'appsecret' => $args['appsecret']));
     } else {
         $r .= $auth['write'];
     }
     $r .= '<input type="hidden" id="website_id" name="website_id" value="' . $args['website_id'] . '" />' . PHP_EOL;
     $r .= '<input type="hidden" id="survey_id" name="survey_id" value="' . $args['survey_id'] . '" />' . PHP_EOL;
     // Sample method
     if (!empty($args['sample_method_id'])) {
         $r .= '<input type="hidden" name="sample:sample_method_id" value="' . $args['sample_method_id'] . '"/>' . PHP_EOL;
     }
     // Check if Record Status is included as a control. If not, then add it as
     // a hidden.
     $arr = helper_base::explode_lines($args['structure']);
     if (!in_array('[record status]', $arr)) {
         $value = isset($args['defaults']['occurrence:record_status']) ? $args['defaults']['occurrence:record_status'] : 'C';
         $r .= '<input type="hidden" id="occurrence:record_status" ' . 'name="occurrence:record_status" value="' . $value . '" />' . PHP_EOL;
     }
     // User profile fields such as username, id etc.
     $exists = isset(data_entry_helper::$entity_to_load['sample:id']);
     $r .= get_user_profile_hidden_inputs(self::$smpAttrs, $args, $exists, $auth['read']);
     return $r;
 }
 protected static function getFirstTabAdditionalContent($args, $auth, &$attributes)
 {
     // Get authorisation tokens to update the Warehouse, plus any other hidden data.
     $r = $auth['write'] . "<input type=\"hidden\" id=\"website_id\" name=\"website_id\" value=\"" . $args['website_id'] . "\" />\n" . "<input type=\"hidden\" id=\"survey_id\" name=\"survey_id\" value=\"" . $args['survey_id'] . "\" />\n";
     if (!empty($args['sample_method_id'])) {
         $r .= '<input type="hidden" name="sample:sample_method_id" value="' . $args['sample_method_id'] . '"/>' . PHP_EOL;
     }
     if (isset(data_entry_helper::$entity_to_load['sample:id'])) {
         $r .= '<input type="hidden" id="sample:id" name="sample:id" value="' . data_entry_helper::$entity_to_load['sample:id'] . '" />' . PHP_EOL;
     }
     if (isset(data_entry_helper::$entity_to_load['occurrence:id'])) {
         $r .= '<input type="hidden" id="occurrence:id" name="occurrence:id" value="' . data_entry_helper::$entity_to_load['occurrence:id'] . '" />' . PHP_EOL;
     }
     if (!empty(data_entry_helper::$entity_to_load['sample:group_id'])) {
         $r .= "<input type=\"hidden\" id=\"group_id\" name=\"sample:group_id\" value=\"" . data_entry_helper::$entity_to_load['sample:group_id'] . "\" />\n";
         // If the group does not release it's records, set the release_status flag
         if (self::$group['private_records'] === 't') {
             $r .= "<input type=\"hidden\" id=\"occurrence:release_status\" name=\"occurrence:release_status\" value=\"U\" />\n";
         }
         if (empty(data_entry_helper::$entity_to_load['sample:group_title'])) {
             data_entry_helper::$entity_to_load['sample:group_title'] = self::$group['title'];
         }
         $msg = empty(self::$loadedSampleId) ? 'This form will be posted to the <strong>{1}</strong> group.' : 'This form was posted to the <strong>{1}</strong> group.';
         $r .= '<p>' . lang::get($msg, data_entry_helper::$entity_to_load['sample:group_title']) . '</p>';
     } elseif (self::$availableForGroups && !isset(data_entry_helper::$entity_to_load['sample:id'])) {
         // Group enabled form being used to add new records, but no group specified in URL path, so give
         // the user a chance to pick from their list of possible groups for this form.
         // Get the list of possible groups they might be posting into using this form. To do this we need the page
         // path without the initial leading /.
         $reload = data_entry_helper::get_reload_link_parts();
         // Slightly messy path handling. Ideally we'd call the same code as group_edit::get_path but we don't know the nid.
         $reload['path'] = preg_replace('/^\\//', '', $reload['path']);
         $dirname = preg_replace('/^\\//', '', dirname($_SERVER['SCRIPT_NAME'])) . '/';
         $reload['path'] = str_replace($dirname, '', $reload['path']);
         $possibleGroups = data_entry_helper::get_report_data(array('dataSource' => 'library/groups/groups_for_page', 'readAuth' => $auth['read'], 'extraParams' => array('currentUser' => hostsite_get_user_field('indicia_user_id'), 'path' => $reload['path'])));
         // Output a drop down so they can select the appropriate group.
         if (count($possibleGroups) > 1) {
             $options = array('' => lang::get('Ad-hoc non-group records'));
             foreach ($possibleGroups as $group) {
                 $options[$group['id']] = "{$group['group_type']}: {$group['title']}";
             }
             $r .= data_entry_helper::select(array('label' => lang::get('Record destination'), 'helpText' => lang::get('Choose whether to post your records into a group that you belong to.'), 'fieldname' => 'sample:group_id', 'lookupValues' => $options));
         } elseif (count($possibleGroups) === 1) {
             $r .= data_entry_helper::radio_group(array('label' => lang::get('Post to {1}', $possibleGroups[0]['title']), 'labelClass' => 'auto', 'helpText' => lang::get('Choose whether to post your records into {1}.', $possibleGroups[0]['title']), 'fieldname' => 'sample:group_id', 'lookupValues' => array('' => lang::get('No'), $possibleGroups[0]['id'] => lang::get('Yes'))));
         }
     }
     // Check if Record Status is included as a control. If not, then add it as a hidden.
     $arr = helper_base::explode_lines($args['structure']);
     if (!in_array('[record status]', $arr)) {
         $value = isset($args['defaults']['occurrence:record_status']) ? $args['defaults']['occurrence:record_status'] : 'C';
         $r .= '<input type="hidden" id="occurrence:record_status" name="occurrence:record_status" value="' . $value . '" />' . PHP_EOL;
     }
     if (!empty($args['defaults']['occurrence:release_status'])) {
         $r .= '<input type="hidden" id="occurrence:release_status" name="occurrence:release_status" value="' . $args['defaults']['occurrence:release_status'] . '" />' . PHP_EOL;
     }
     $r .= get_user_profile_hidden_inputs($attributes, $args, isset(data_entry_helper::$entity_to_load['sample:id']), $auth['read']);
     if ($args['multiple_occurrence_mode'] === 'multi') {
         $r .= '<input type="hidden" value="true" name="gridmode" />';
     }
     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;
 }
示例#12
0
 public static function get_sample_form($args, $node, $response)
 {
     global $user;
     iform_load_helpers(array('map_helper'));
     $auth = data_entry_helper::get_read_write_auth($args['website_id'], $args['password']);
     // either looking at existing, creating a new one, or an error occurred: no successful posts...
     // first check some conditions are met
     $sampleMethods = helper_base::get_termlist_terms($auth, 'indicia:sample_methods', array('Timed Count'));
     if (count($sampleMethods) == 0) {
         return 'The sample method "Timed Count" must be defined in the termlist in order to use this form.';
     }
     $sampleId = isset($_GET['sample_id']) ? $_GET['sample_id'] : null;
     if ($sampleId && !isset(data_entry_helper::$validation_errors)) {
         data_entry_helper::load_existing_record($auth['read'], 'sample', $sampleId);
     }
     $r = '<form method="post" id="sample">' . $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="read_nonce" value="' . $auth['read']['nonce'] . '"/>';
     $r .= '<input type="hidden" name="read_auth_token" value="' . $auth['read']['auth_token'] . '"/>';
     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'] . '"/>';
     }
     // pass a param that sets the next page to display
     $r .= "<input type=\"hidden\" name=\"website_id\" value=\"" . $args['website_id'] . "\"/>\n<input type=\"hidden\" name=\"sample:survey_id\" value=\"" . $args['survey_id'] . "\"/>\n<input type=\"hidden\" name=\"page\" value=\"site\"/>";
     $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']) . data_entry_helper::text_input(array('label' => lang::get('Site Name'), 'fieldname' => 'sample:location_name', 'validation' => array('required')));
     $help = lang::get('The Year field is read-only, and is calculated automatically from the date(s) of the Counts.');
     $r .= '<p class="ui-state-highlight page-notice ui-corner-all">' . $help . '</p>';
     if ($sampleId == null) {
         if (isset($_GET['date'])) {
             data_entry_helper::$entity_to_load['C1:sample:date'] = $_GET['date'];
         }
         $r .= data_entry_helper::date_picker(array('label' => lang::get('Date of first count'), 'fieldname' => 'C1:sample:date', 'validation' => array('required', 'date')));
         data_entry_helper::$javascript .= "jQuery('#C1\\\\:sample\\\\:date').change(function(){\n  jQuery('#sample\\\\:date').val(jQuery(this).val() == '' ? '' : jQuery(this).datepicker('getDate').getFullYear());\n});\nif(jQuery('#C1\\\\:sample\\\\:date').val() != '') jQuery('#sample\\\\:date').val(jQuery('#C1\\\\:sample\\\\:date').datepicker('getDate').getFullYear());\n";
     }
     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) - only interested in Year.
         $d = new DateTime(data_entry_helper::$entity_to_load['sample:date']);
         data_entry_helper::$entity_to_load['sample:date'] = $d->format('Y');
     }
     unset(data_entry_helper::$default_validation_rules['sample:date']);
     $r .= data_entry_helper::text_input(array('label' => lang::get('Year'), 'fieldname' => 'sample:date', 'readonly' => ' readonly="readonly" '));
     // 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'] . '" />';
     $help = lang::get('Now draw the flight area for the timed count on the map below. The Grid Reference is filled in automatically when the site is drawn.');
     $r .= '<p class="ui-state-highlight page-notice ui-corner-all">' . $help . '</p>';
     $options = iform_map_get_map_options($args, $auth['read']);
     $options['allowPolygonRecording'] = true;
     $options['clickForSpatialRef'] = false;
     if (isset($args['precision']) && $args['precision'] != '') {
         $options['clickedSrefPrecisionMin'] = $args['precision'];
         $options['clickedSrefPrecisionMax'] = $args['precision'];
     }
     $olOptions = iform_map_get_ol_options($args);
     if (!in_array('drawPolygon', $options['standardControls'])) {
         $options['standardControls'][] = 'drawPolygon';
     }
     if (!in_array('modifyFeature', $options['standardControls'])) {
         $options['standardControls'][] = 'modifyFeature';
     }
     $systems = array();
     $list = explode(',', str_replace(' ', '', $args['spatial_systems']));
     foreach ($list as $system) {
         $systems[$system] = lang::get($system);
     }
     $r .= "<label for=\"imp-sref\">" . lang::get('Grid Reference') . ":</label> <input type=\"text\" id=\"imp-sref\" name=\"sample:entered_sref\" value=\"" . data_entry_helper::$entity_to_load['sample:entered_sref'] . "\" readonly=\"readonly\" class=\"required\" />";
     $r .= "<input type=\"hidden\" id=\"imp-geom\" name=\"sample:geom\" value=\"" . data_entry_helper::$entity_to_load['sample:geom'] . "\" />";
     if (count($systems) == 1) {
         // Hidden field for the system
         $keys = array_keys($systems);
         $r .= "<input type=\"hidden\" id=\"imp-sref-system\" name=\"sample:entered_sref_system\" value=\"" . $keys[0] . "\" />\n";
     } else {
         $r .= self::sref_system_select(array('fieldname' => 'sample:entered_sref_system'));
     }
     $r .= '<br />' . data_entry_helper::georeference_lookup(iform_map_get_georef_options($args, $auth['read']));
     $r .= data_entry_helper::map_panel($options, $olOptions);
     // switch off the sref functionality.
     data_entry_helper::$javascript .= "mapInitialisationHooks.push(function(div){\n  \$('#imp-sref').unbind('change');\n  // Programatic activation does not rippleout, so deactivate Nav first, which is actibve by default.\n  for(var i=0; i<div.map.controls.length; i++)\n    if(div.map.controls[i].CLASS_NAME == \"OpenLayers.Control.Navigation\")\n      div.map.controls[i].deactivate();\n  activeCtrl = false;\n  for(var i=0; i<div.map.controls.length; i++){\n    if(div.map.controls[i].CLASS_NAME == \"" . (isset(data_entry_helper::$entity_to_load['sample:id']) ? "OpenLayers.Control.ModifyFeature" : "OpenLayers.Control.DrawFeature") . "\"){\n      div.map.controls[i].activate();\n      activeCtrl = div.map.controls[i];\n      break;\n    }}\n" . (isset(data_entry_helper::$entity_to_load['sample:id']) ? "  if(activeCtrl && div.map.editLayer.features.length>0) activeCtrl.selectFeature(div.map.editLayer.features[0]);\n" : "") . "});\n";
     $r .= data_entry_helper::textarea(array('label' => 'Comment', 'fieldname' => 'sample:comment', 'class' => 'wide'));
     $r .= '<input type="submit" value="' . lang::get('Next') . '" />';
     $r .= '<a href="' . $args['summary_page'] . '"><button type="button" class="ui-state-default ui-corner-all" />' . lang::get('Cancel') . '</button></a>';
     // allow deletes if sample id is present: i.e. existing sample.
     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>';
         // note we only require bare minimum in order to flag a sample as deleted.
         $r .= '</form><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"/>';
         data_entry_helper::$javascript .= "jQuery('#delete-button').click(function(){\n  if(confirm(\"" . lang::get('Are you sure you want to delete this timed count?') . "\"))\n    jQuery('#delete-form').submit();\n});\n";
     }
     $r .= '</form>';
     data_entry_helper::enable_validation('sample');
     return $r;
 }