Example #1
0
/**
 * Method to read a parameter from the arguments of a form that contains a list of key=value pairs on separate lines. 
 * Each value is checked for references to the user's data (either {user_id}, {username}, {email} or {profile_*})
 * and if found these substitutions are replaced.
 * @param string $listData Form argument data, with each key value pair on a separate line.
 * @return array Associative array.
 */
function get_options_array_with_user_data($listData)
{
    global $user;
    $r = array();
    if ($listData != '') {
        $params = helper_base::explode_lines($listData);
        foreach ($params as $param) {
            if (!empty($param)) {
                $tokens = explode('=', $param, 2);
                if (count($tokens) == 2) {
                    $tokens[1] = apply_user_replacements($tokens[1]);
                } else {
                    throw new Exception('Some of the preset or default parameters defined for this page are not of the form param=value.');
                }
                $r[$tokens[0]] = $tokens[1];
            }
        }
    }
    return $r;
}
 /**
  * Get the location control as a select dropdown.
  * Default control ordering is by name.
  * reportProvidesOrderBy option should be set to true if the control is populated by a report that
  * provides its own Order By statement, if the reportProvidesOrderBy option is not set in this situation, then the report
  * will have two Order By statements and will fail. 
  */
 protected static function get_control_locationselect($auth, $args, $tabAlias, $options)
 {
     if (isset($options['extraParams'])) {
         foreach ($options['extraParams'] as $key => &$value) {
             $value = apply_user_replacements($value);
         }
         $options['extraParams'] = array_merge($auth['read'], $options['extraParams']);
     } else {
         $options['extraParams'] = array_merge($auth['read']);
     }
     if (empty($options['reportProvidesOrderBy']) || $options['reportProvidesOrderBy'] == 0) {
         $options['extraParams']['orderby'] = 'name';
     }
     $location_list_args = array_merge(array('label' => lang::get('LANG_Location_Label'), 'view' => 'detail'), $options);
     return data_entry_helper::location_select($location_list_args);
 }
 protected static function get_control_standardparams($auth, $args, $tabalias, $options)
 {
     self::$applyUserPrefs = false;
     $options = array_merge(array('allowSave' => true, 'sharing' => empty($args['sharing']) ? 'reporting' : $args['sharing']), $options);
     if ($args['redirect_on_success']) {
         $options['redirect_on_success'] = url($args['redirect_on_success']);
     }
     // any preset params on the report page should be loaded as initial settings for the filter.
     if (!empty($args['param_presets'])) {
         $params = data_entry_helper::explode_lines_key_value_pairs($args['param_presets']);
         foreach ($params as $key => $val) {
             $options["filter-{$key}"] = $val;
         }
     }
     foreach ($options as $key => &$value) {
         $value = apply_user_replacements($value);
     }
     if ($options['allowSave'] && !function_exists('iform_ajaxproxy_url')) {
         return 'The AJAX Proxy module must be enabled to support saving filters. Set @allowSave=false to disable this in the [standard params] control.';
     }
     if (!function_exists('hostsite_get_user_field') || !hostsite_get_user_field('indicia_user_id')) {
         return 'The standard params module requires Easy Login.';
     }
     $r = report_filter_panel($auth['read'], $options, $args['website_id'], $hiddenStuff);
     return $r . $hiddenStuff;
 }
Example #4
0
 protected static function get_tab_content($auth, $args, $tab, $tabContent, $tabalias, &$attributes, &$hasControls)
 {
     // cols array used if we find | splitters
     $cols = array();
     $defAttrOptions = array('extraParams' => $auth['read']);
     if (isset($args['attribute_termlist_language_filter']) && $args['attribute_termlist_language_filter']) {
         $defAttrOptions['language'] = iform_lang_iso_639_2($args['language']);
     }
     //create array of attribute field names to test against later
     $attribNames = array();
     foreach ($attributes as $key => $attrib) {
         $attribNames[$key] = $attrib['id'];
     }
     $html = '';
     // Now output the content of the tab. Use a for loop, not each, so we can treat several rows as one object
     for ($i = 0; $i < count($tabContent); $i++) {
         $component = trim($tabContent[$i]);
         if (preg_match('/\\A\\?[^�]*\\?\\z/', $component) === 1) {
             // Component surrounded by ? so represents a help text
             $helpText = substr($component, 1, -1);
             $html .= '<div class="page-notice ui-state-highlight ui-corner-all">' . lang::get($helpText) . "</div>";
         } elseif (preg_match('/\\A\\[[^�]*\\]\\z/', $component) === 1) {
             // Component surrounded by [] so represents a control or control block
             // Anything following the component that starts with @ is an option to pass to the control
             $options = array();
             while ($i < count($tabContent) - 1 && substr($tabContent[$i + 1], 0, 1) == '@' || trim($tabContent[$i]) === '') {
                 $i++;
                 // ignore empty lines
                 if (trim($tabContent[$i]) !== '') {
                     $option = explode('=', substr($tabContent[$i], 1), 2);
                     if (!isset($option[1]) || $option[1] === 'false') {
                         $options[$option[0]] = FALSE;
                     } else {
                         $options[$option[0]] = json_decode($option[1], TRUE);
                         // if not json then need to use option value as it is
                         if ($options[$option[0]] == '') {
                             $options[$option[0]] = $option[1];
                         }
                     }
                     // urlParam is special as it loads the control's default value from $_GET
                     if ($option[0] === 'urlParam' && isset($_GET[$option[1]])) {
                         $options['default'] = $_GET[$option[1]];
                     }
                 }
             }
             // if @permission specified as an option, then check that the user has access to this control
             if (!empty($options['permission']) && !user_access($options['permission'])) {
                 continue;
             }
             $parts = explode('.', str_replace(array('[', ']'), '', $component));
             $method = 'get_control_' . preg_replace('/[^a-zA-Z0-9]/', '', strtolower($component));
             if (!empty($args['high_volume']) && $args['high_volume']) {
                 // enable control level report caching when in high_volume mode
                 $options['caching'] = empty($options['caching']) ? true : $options['caching'];
                 $options['cachetimeout'] = empty($options['cachetimeout']) ? HIGH_VOLUME_CONTROL_CACHE_TIMEOUT : $options['cachetimeout'];
             }
             // allow user settings to override the control - see iform_user_ui_options.module
             if (isset(data_entry_helper::$data['structureControlOverrides']) && !empty(data_entry_helper::$data['structureControlOverrides'][$component])) {
                 $options = array_merge($options, data_entry_helper::$data['structureControlOverrides'][$component]);
             }
             if (count($parts) === 1 && method_exists(self::$called_class, $method)) {
                 //outputs a control for which a specific output function has been written.
                 $html .= call_user_func(array(self::$called_class, $method), $auth, $args, $tabalias, $options);
                 $hasControls = true;
             } elseif (count($parts) === 2) {
                 require_once dirname($_SERVER['SCRIPT_FILENAME']) . '/' . data_entry_helper::relative_client_helper_path() . '/prebuilt_forms/extensions/' . $parts[0] . '.php';
                 if (method_exists('extension_' . $parts[0], $parts[1])) {
                     //outputs a control for which a specific extension function has been written.
                     $path = call_user_func(array(self::$called_class, 'getReloadPath'));
                     //pass the classname of the form through to the extension control method to allow access to calling class functions and variables
                     $args["calling_class"] = 'iform_' . self::$node->iform;
                     $html .= call_user_func(array('extension_' . $parts[0], $parts[1]), $auth, $args, $tabalias, $options, $path, $attributes);
                     $hasControls = true;
                     // auto-add JavaScript for the extension
                     if (file_exists(iform_client_helpers_path() . 'prebuilt_forms/extensions/' . $parts[0] . '.js')) {
                         drupal_add_js(iform_client_helpers_path() . 'prebuilt_forms/extensions/' . $parts[0] . '.js', array('preprocess' => FALSE));
                     }
                     if (file_exists(iform_client_helpers_path() . 'prebuilt_forms/extensions/' . $parts[0] . '.css')) {
                         drupal_add_css(iform_client_helpers_path() . 'prebuilt_forms/extensions/' . $parts[0] . '.css', array('preprocess' => FALSE));
                     }
                 } else {
                     $html .= lang::get("The {$component} extension cannot be found.");
                 }
             } elseif (($attribKey = array_search(substr($component, 1, -1), $attribNames)) !== false || preg_match('/^\\[[a-zA-Z]+:(?P<ctrlId>[0-9]+)\\]/', $component, $matches)) {
                 // control is a smpAttr or other attr control.
                 if (empty($options['extraParams'])) {
                     $options['extraParams'] = array_merge($defAttrOptions['extraParams']);
                 } else {
                     $options['extraParams'] = array_merge($defAttrOptions['extraParams'], (array) $options['extraParams']);
                 }
                 //merge extraParams first so we don't loose authentication
                 $options = array_merge($defAttrOptions, $options);
                 foreach ($options as $key => &$value) {
                     $value = apply_user_replacements($value);
                 }
                 if ($attribKey !== false) {
                     // a smpAttr control
                     $html .= data_entry_helper::outputAttribute($attributes[$attribKey], $options);
                     $attributes[$attribKey]['handled'] = true;
                 } else {
                     // if the control name of form name:id, then we will call get_control_name passing the id as a parameter
                     $method = 'get_control_' . preg_replace('/[^a-zA-Z]/', '', strtolower($component));
                     if (method_exists(self::$called_class, $method)) {
                         $options['ctrlId'] = $matches['ctrlId'];
                         $html .= call_user_func(array(self::$called_class, $method), $auth, $args, $tabalias, $options);
                     } else {
                         $html .= "Unsupported control {$component}<br/>";
                     }
                 }
                 $hasControls = true;
             } elseif ($component === '[*]') {
                 // this outputs any custom attributes that remain for this tab. The custom attributes can be configured in the
                 // settings text using something like @smpAttr:4|label=My label. The next bit of code parses these out into an
                 // array used when building the html.
                 // Alternatively, a setting like @option=value is applied to all the attributes.
                 $attrSpecificOptions = array();
                 foreach ($options as $option => $value) {
                     // split the id of the option into the control name and option name.
                     $optionId = explode('|', $option);
                     if (count($optionId) > 1) {
                         // Found an option like @smpAttr:4|label=My label
                         if (!isset($attrSpecificOptions[$optionId[0]])) {
                             $attrSpecificOptions[$optionId[0]] = array();
                         }
                         $attrSpecificOptions[$optionId[0]][$optionId[1]] = apply_user_replacements($value);
                     } else {
                         // Found an option like @option=value
                         $defAttrOptions = array_merge($defAttrOptions, array($option => $value));
                     }
                 }
                 $attrHtml = get_attribute_html($attributes, $args, $defAttrOptions, $tab, $attrSpecificOptions);
                 if (!empty($attrHtml)) {
                     $hasControls = true;
                 }
                 $html .= $attrHtml;
             } else {
                 $html .= "The form structure includes a control called {$component} which is not recognised.<br/>";
                 //ensure $hasControls is true so that the error message is shown
                 $hasControls = true;
             }
         } elseif ($component === '|') {
             // column splitter. So, store the col html and start on the next column.
             $cols[] = $html;
             $html = '';
         } else {
             // output anything else as is. This allow us to add html to the form structure.
             $html .= $component;
         }
     }
     if (count($cols) > 0) {
         $cols[] = $html;
         // a splitter in the structure so put the stuff so far in a 50% width left float div, and the stuff that follows in a 50% width right float div.
         global $indicia_templates;
         $html = str_replace(array('{col-1}', '{col-2}'), $cols, $indicia_templates['two-col-50']);
         if (count($cols) > 2) {
             unset($cols[1]);
             unset($cols[0]);
             $html .= '<div class="follow_on_block" style="clear:both;">' . implode('', $cols) . '</div>';
         } else {
             $html .= '<div class="follow_on_block" style="clear:both;"></div>';
         }
         // needed so any tab div is stretched around them
     }
     return $html;
 }
 /**
  * Returns the species checklist input control.
  * @param array $auth Read authorisation tokens
  * @param array $args Form configuration
  * @param array $extraParams Extra parameters array, pre-configured with filters for taxa and name types.
  * @param array $options additional options for the control, e.g. those configured in the form structure.
  * @return HTML for the species_checklist control.
  * Again, this is an altered copy of the one found in dynamic_sample_occurrence with support for preloading a species grid with sample images from second level samples
  * and then loading it with occurrence images attached to occurrences which are attached to third level samples.
  * May contain coded that is not needed and can be removed if possible
  */
 protected static function get_control_species_checklist($auth, $args, $extraParams, $options)
 {
     global $user;
     // Build the configuration options
     if (isset($options['view'])) {
         $extraParams['view'] = $options['view'];
     }
     // There may be options in the form occAttr:n|param => value targetted at specific attributes
     $occAttrOptions = array();
     $optionToUnset = array();
     foreach ($options as $option => $value) {
         // split the id of the option into the attribute name and option name.
         $optionParts = explode('|', $option);
         if ($optionParts[0] != $option) {
             // an occurrence attribute option was found
             $attrName = $optionParts[0];
             $optName = $optionParts[1];
             // split the attribute name into the type and id (type will always be occAttr)
             $attrParts = explode(':', $attrName);
             $attrId = $attrParts[1];
             if (!isset($occAttrOptions[$attrId])) {
                 $occAttrOptions[$attrId] = array();
             }
             $occAttrOptions[$attrId][$optName] = apply_user_replacements($value);
             $optionToUnset[] = $option;
         }
     }
     // tidy up options array
     foreach ($optionToUnset as $value) {
         unset($options[$value]);
     }
     // make sure that if extraParams is specified as a config option, it does not replace the essential stuff
     if (isset($options['extraParams'])) {
         $options['extraParams'] = array_merge($extraParams, $options['extraParams']);
     }
     $species_ctrl_opts = array_merge(array('occAttrOptions' => $occAttrOptions, 'listId' => $args['list_id'], 'label' => lang::get('occurrence:taxa_taxon_list_id'), 'columns' => 1, 'extraParams' => $extraParams, 'survey_id' => $args['survey_id'], 'occurrenceComment' => $args['occurrence_comment'], 'occurrenceSensitivity' => isset($args['occurrence_sensitivity']) ? $args['occurrence_sensitivity'] : false, 'occurrenceImages' => $args['occurrence_images'], 'PHPtaxonLabel' => true, 'language' => iform_lang_iso_639_2(hostsite_get_user_field('language')), 'cacheLookup' => $args['cache_lookup'], 'speciesNameFilterMode' => self::getSpeciesNameFilterMode($args), 'userControlsTaxonFilter' => isset($args['user_controls_taxon_filter']) ? $args['user_controls_taxon_filter'] : false, 'subSpeciesColumn' => $args['sub_species_column'], 'copyDataFromPreviousRow' => !empty($args['copy_species_row_data_to_new_rows']) && $args['copy_species_row_data_to_new_rows'], 'previousRowColumnsToInclude' => empty($args['previous_row_columns_to_include']) ? '' : $args['previous_row_columns_to_include'], 'editTaxaNames' => !empty($args['edit_taxa_names']) && $args['edit_taxa_names'], 'includeSpeciesGridLinkPage' => !empty($args['include_species_grid_link_page']) && $args['include_species_grid_link_page'], 'speciesGridPageLinkUrl' => $args['species_grid_page_link_url'], 'speciesGridPageLinkParameter' => $args['species_grid_page_link_parameter'], 'speciesGridPageLinkTooltip' => $args['species_grid_page_link_tooltip']), $options);
     if ($groups = hostsite_get_user_field('taxon_groups')) {
         $species_ctrl_opts['usersPreferredGroups'] = unserialize($groups);
     }
     if ($args['extra_list_id']) {
         $species_ctrl_opts['lookupListId'] = $args['extra_list_id'];
     }
     //We only do the work to setup the filter if the user has specified a filter in the box
     if (!empty($args['taxon_filter_field']) && !empty($args['taxon_filter'])) {
         $species_ctrl_opts['taxonFilterField'] = $args['taxon_filter_field'];
         $filterLines = helper_base::explode_lines($args['taxon_filter']);
         $species_ctrl_opts['taxonFilter'] = $filterLines;
     }
     if (isset($args['col_widths']) && $args['col_widths']) {
         $species_ctrl_opts['colWidths'] = explode(',', $args['col_widths']);
     }
     call_user_func(array(self::$called_class, 'build_grid_taxon_label_function'), $args, $options);
     if (self::$mode == self::MODE_CLONE) {
         $species_ctrl_opts['useLoadedExistingRecords'] = true;
     }
     return self::species_checklist($species_ctrl_opts);
 }
 /**
  * Get a location select control pair, first the user must select a square then a plot associated with a square.
  * Only squares that are associated with the user and also have plots are displayed
  * When a plot is selected, then a mini report about the plot is displayed.
  *
  * $options Options array with the following possibilities:<ul>
  * <li><b>coreSquareLocationTypeId</b><br/>
  * The location type id of a core square</li>
  * <li><b>additionalSquareLocationTypeId</b><br/>
  * The location type id of an additional square</li>
  * <li><b>viceCountyLocationAttributeId</b><br/>
  * The attribute ID that holds the vice counties associated with a square</li>
  * <li><b>noViceCountyFoundMessage</b><br/>
  * A square's vice country makes up part of its name, however if it doesn't have a vice county then display this replacement text instead</li>
  * <li><b>userSquareAttrId</b><br/>
  * The ID of the person attribute that holds the user squares.</li>
  * <li><b>orientationAttributeId</b><br/>
  * The location attribute id that holds a plot's Orientation</li>
  * <li><b>aspectAttributeId</b><br/>
  * The location attribute id that holds a plot's Aspect</li>
  * <li><b>slopeAttributeId</b><br/>
  * The location attribute id that holds a plot's Slope</li>
  * <li><b>ashAttributeId</b><br/>
  * The location attribute id that holds a plot's % Ash Coverage</li>
  * <li><b>privatePlotAttrId</b><br/>
  * Optional attribute for the location attribute id which holds whether a plot is private. If supplied then when a private plot is selected
  * as the location then all occurrences are set to have a sensitivity_precision=10000</li>
  * <li><b>rowInclusionCheckModeHasData</b><br/>
  * Optional. Supply this as true if the species grid is in rowInclusionCheck=hasData mode and you are using the privatePlotAttrId option.
  * <li><b>noPlotMessageInAlert</b><br/>
  * Optional. Override the default message that is displayed if a user has not plots to select. This message is displayed in an alert box as well.
  * </ul>
  */
 public static function splash_location_select($auth, $args, $tabAlias, $options)
 {
     if (empty($options['coreSquareLocationTypeId'])) {
         drupal_set_message('Please fill in the @coreSquareLocationTypeId option for the splash_location_select control');
         return '';
     }
     if (empty($options['additionalSquareLocationTypeId'])) {
         drupal_set_message('Please fill in the @additionalSquareLocationTypeId option for the splash_location_select control');
         return '';
     }
     if (empty($options['viceCountyLocationAttributeId'])) {
         drupal_set_message('Please fill in the @viceCountyLocationAttributeId option for the splash_location_select control');
         return '';
     }
     if (empty($options['noViceCountyFoundMessage'])) {
         drupal_set_message('Please fill in the @noViceCountyFoundMessage option for the splash_location_select control');
         return '';
     }
     if (empty($options['userSquareAttrId'])) {
         drupal_set_message('Please fill in the @userSquareAttrId option for the splash_location_select control');
         return '';
     }
     $coreSquareLocationTypeId = $options['coreSquareLocationTypeId'];
     $additionalSquareLocationTypeId = $options['additionalSquareLocationTypeId'];
     $currentUserId = hostsite_get_user_field('indicia_user_id');
     $viceCountyLocationAttributeId = $options['viceCountyLocationAttributeId'];
     $noViceCountyFoundMessage = $options['noViceCountyFoundMessage'];
     $userSquareAttrId = $options['userSquareAttrId'];
     $extraParamForSquarePlotReports = array('core_square_location_type_id' => $coreSquareLocationTypeId, 'additional_square_location_type_id' => $additionalSquareLocationTypeId, 'current_user_id' => $currentUserId, 'vice_county_location_attribute_id' => $viceCountyLocationAttributeId, 'no_vice_county_found_message' => $noViceCountyFoundMessage, 'user_square_attr_id' => $userSquareAttrId);
     $reportOptions = array('dataSource' => 'reports_for_prebuilt_forms/Splash/get_my_squares_that_have_plots', 'readAuth' => $auth['read'], 'mode' => 'report', 'extraParams' => $extraParamForSquarePlotReports);
     //In PSS/NPMS we don't show the Vice County in the label.
     if (!empty($reportOptions['extraParams']) && !empty($options['pssMode']) && $options['pssMode'] === true) {
         $reportOptions['extraParams'] = array_merge($reportOptions['extraParams'], ['pss_mode' => true]);
         data_entry_helper::$javascript .= "\$('#imp-sref').attr('readonly','readonly');";
     }
     $rawData = data_entry_helper::get_report_data($reportOptions);
     if (empty($rawData)) {
         //If the user doesn't have any plots, then hide the map and disable the Spatial Ref field so they can't continue
         if (!empty($options['noPlotMessageInAlert'])) {
             data_entry_helper::$javascript .= "alert('" . $options['noPlotMessageInAlert'] . "');";
         } else {
             drupal_set_message('Note: You have not been allocated any squares to input data for, or the squares you have been allocated do not have plots.');
         }
         drupal_set_message('You cannot enter data without having a plot to select.');
         data_entry_helper::$javascript .= "\$('#map').hide();";
         data_entry_helper::$javascript .= "\$('#imp-sref').attr('disabled','disabled');";
         if (!empty($options['noPlotMessageInAlert'])) {
             return '<b>' . $options['noPlotMessageInAlert'] . '</b></br>';
         } else {
             return '<b>You have not been allocated any Squares that contain plots</b></br>';
         }
     } else {
         //Convert the raw data in the report into array format suitable for the Select drop-down to user (an array of ID=>Name pairs)
         foreach ($rawData as $rawRow) {
             $squaresData[$rawRow['id']] = $rawRow['name'];
         }
         //Need a report to collect the square to default the Location Select to in edit mode, as this is not stored against the sample directly.
         if (!empty($_GET['sample_id'])) {
             $squareData = data_entry_helper::get_report_data(array('dataSource' => 'reports_for_prebuilt_forms/Splash/get_square_for_sample', 'readAuth' => $auth['read'], 'extraParams' => array('sample_id' => $_GET['sample_id'])));
             $defaultSquareSelection = $squareData[0]['id'];
         } else {
             $defaultSquareSelection = '';
         }
         $r = data_entry_helper::select(array('id' => 'squares-select-list', 'blankText' => '<Please select>', 'fieldname' => 'squares-select-list', 'label' => lang::get('Select a Square'), 'helpText' => lang::get('Select a square to input data for before selecting a plot.'), 'lookupValues' => $squaresData, 'default' => $defaultSquareSelection));
         //This code is same as standard lookup control
         if (isset($options['extraParams'])) {
             foreach ($options['extraParams'] as $key => &$value) {
                 $value = apply_user_replacements($value);
             }
             $options['extraParams'] = array_merge($auth['read'], $options['extraParams']);
         } else {
             $options['extraParams'] = array_merge($auth['read']);
         }
         if (empty($options['reportProvidesOrderBy']) || $options['reportProvidesOrderBy'] == 0) {
             $options['extraParams']['orderby'] = 'name';
         }
         //Setup the Plot drop-down which uses the Suqare selection the user makes.
         $options['parentControlId'] = 'squares-select-list';
         $options['filterField'] = 'square_id';
         $options['reportProvidesOrderBy'] = true;
         $options['searchUpdatesSref'] = true;
         $options['label'] = 'Plot';
         $options['report'] = 'reports_for_prebuilt_forms/Splash/get_plots_for_square_id';
         if (!empty($options['plotNumberAttrId'])) {
             $options['extraParams']['plot_number_attr_id'] = $options['plotNumberAttrId'];
         }
         //Create the drop-down for the plot
         $location_list_args = array_merge(array('label' => lang::get('LANG_Location_Label'), 'view' => 'detail'), $options);
         $r .= data_entry_helper::location_select($location_list_args);
         //Create the mini report, not currently required on PSS site
         if (empty($options['pssMode'])) {
             $r .= self::plot_report_panel($auth, $options);
         }
         //If an attribute holding whether plots are private is supplied, then we want to return
         //whether the selected plot is private and set the occurrence sensitivity_precision appropriately
         if (!empty($options['privatePlotAttrId'])) {
             $extraParamForSquarePlotReports = array_merge($extraParamForSquarePlotReports, array('private_plot_attr_id' => $options['privatePlotAttrId'], 'only_return_private_plots' => true));
             //When the page initially loads, collect all the private plots that can be selected by the user, rather than
             //load whether the plot is private when each selection is made.
             $myPlotsAndSquares = data_entry_helper::get_report_data(array('dataSource' => 'reports_for_prebuilt_forms/Splash/get_my_squares_and_plots', 'readAuth' => $auth['read'], 'extraParams' => $extraParamForSquarePlotReports));
             $privatePlots = array();
             foreach ($myPlotsAndSquares as $locationDataItem) {
                 $privatePlots[] = $locationDataItem['id'];
             }
             //Need option to tell the system if the species grid has rowInclusionCheck=hasData, and we are setting the occurrences
             //sensitivity_precision for occurrences when a plot is private.
             //This is because the way the system detects if an occurrence is present is different.
             if (!empty($options['rowInclusionCheckModeHasData']) && $options['rowInclusionCheckModeHasData'] == true) {
                 $rowInclusionCheckModeHasData = 'true';
             } else {
                 $rowInclusionCheckModeHasData = 'false';
             }
             if (!empty($_GET['sample_id'])) {
                 $editMode = 'true';
             } else {
                 $editMode = 'false';
             }
             data_entry_helper::$javascript .= '
     private_plots_set_precision(' . json_encode($privatePlots) . ',' . $rowInclusionCheckModeHasData . ',' . $editMode . ');
     ';
         }
         return $r;
     }
 }
 protected static function get_control_sampleattributes($auth, $args, $tabAlias, $options)
 {
     $r = '';
     $tab = isset($options['tab']) ? $options['tab'] : null;
     $attrArgs = array('valuetable' => 'sample_attribute_value', 'attrtable' => 'sample_attribute', 'key' => 'sample_id', 'fieldprefix' => 'smpAttr', 'extraParams' => $auth['read'], 'survey_id' => $args['survey_id']);
     if (self::$loadedSampleId) {
         // if we have a single occurrence Id to load, use it to get attribute values
         $attrArgs['id'] = self::$loadedSampleId;
     }
     if (isset($args['sample_method_id']) && !empty($args['sample_method_id'])) {
         $attrArgs['sample_method_id'] = $args['sample_method_id'];
     }
     if (!empty($options['attributeIds'])) {
         $attrArgs['extraParams']['query'] = json_encode(array('in' => array('id' => $options['attributeIds'])));
     }
     $smpAttrs = data_entry_helper::getAttributes($attrArgs, false);
     $ctrlOptions = array('extraParams' => $auth['read']);
     $attrSpecificOptions = array();
     self::parseForAttrSpecificOptions($options, $ctrlOptions, $attrSpecificOptions);
     foreach ($attrSpecificOptions as $attr => $opts) {
         if (isset($attrSpecificOptions[$attr]['default'])) {
             $attrSpecificOptions[$attr]['default'] = apply_user_replacements($attrSpecificOptions[$attr]['default']);
         }
     }
     foreach ($smpAttrs as &$attribute) {
         if (in_array($attribute['id'], data_entry_helper::$handled_attributes)) {
             $attribute['handled'] = 1;
         }
         // Hide controls that have already been handled.
         if (($tab === null || strcasecmp($tab, $attribute['inner_structure_block']) == 0) && !isset($attribute['handled'])) {
             $options = $ctrlOptions + get_attr_validation($attribute, $args);
             // when getting the options, only use the first 2 parts of the fieldname as any further imply an existing record ID so would differ.
             $fieldNameParts = explode(':', $attribute['fieldname']);
             if (preg_match('/[a-z][a-z][a-z]Attr/', $fieldNameParts[count($fieldNameParts) - 2])) {
                 $optionFieldName = $fieldNameParts[count($fieldNameParts) - 2] . ':' . $fieldNameParts[count($fieldNameParts) - 1];
             } elseif (preg_match('/[a-za-za-z]Attr/', $fieldNameParts[count($fieldNameParts) - 3])) {
                 $optionFieldName = $fieldNameParts[count($fieldNameParts) - 3] . ':' . $fieldNameParts[count($fieldNameParts) - 2];
             } else {
                 throw new exception('Option fieldname not found');
             }
             $dummy = null;
             if (isset($attrSpecificOptions[$optionFieldName])) {
                 $options = array_merge($options, $attrSpecificOptions[$optionFieldName]);
             }
             $r .= data_entry_helper::outputAttribute($attribute, $options);
             $attribute['handled'] = true;
         }
     }
     return $r;
 }