Esempio n. 1
0
 /**
  * Return the Indicia form code
  * @param array $args Input parameters.
  * @param array $node Drupal node object
  * @param array $response Response from Indicia services after posting a verification.
  * @return HTML string
  */
 public static function get_form($args, $node, $response)
 {
     $auth = data_entry_helper::get_read_write_auth($args['website_id'], $args['password']);
     global $user;
     $r = '';
     $presetList = explode("\n", $args['param_presets']);
     $presets = array();
     foreach ($presetList as $param) {
         $tokens = explode('=', $param);
         if (count($tokens) == 2) {
             $presets[$tokens[0]] = $tokens[1];
         } else {
             $r .= '<div class="page-notice ui-widget ui-widget-content ui-corner-all ui-state-error">' . 'Some of the preset parameters defined for this page are not of the form param=value.</div>';
         }
     }
     $reportOptions = array('id' => 'report-grid', 'class' => '', 'thClass' => '', 'dataSource' => $args['report_name'], 'mode' => 'report', 'readAuth' => $auth['read'], 'columns' => array(), 'itemsPerPage' => 20, 'autoParamsForm' => $args['auto_params_form'], 'extraParams' => $presets);
     // Add a download link
     $r .= '<a href="' . data_entry_helper::get_report_data(array_merge($reportOptions, array('linkOnly' => true))) . '&mode=csv">Download this report</a>';
     // now the grid
     $r .= data_entry_helper::report_grid($reportOptions);
     // Set up a page refresh for dynamic update of the report at set intervals
     if ($args['refresh_timer'] !== 0 && is_numeric($args['refresh_timer'])) {
         // is_int prevents injection
         if (isset($args['load_on_refresh']) && !empty($args['load_on_refresh'])) {
             data_entry_helper::$javascript .= "setTimeout('window.location=\"" . $args['load_on_refresh'] . "\";', " . $args['refresh_timer'] . "*1000 );\n";
         } else {
             data_entry_helper::$javascript .= "setTimeout('window.location.reload( false );', " . $args['refresh_timer'] . "*1000 );\n";
         }
     }
     return $r;
 }
Esempio n. 2
0
 /**
  * Return the generated form output.
  * @return Form HTML.
  * @todo: Implement this method
  */
 public static function get_form($args)
 {
     global $user;
     $lang = isset($user) ? iform_lang_iso_639_2($user->lang) : 'eng';
     if (function_exists('iform_load_helpers')) {
         iform_load_helpers(array('map_helper'));
     } else {
         require_once dirname(dirname(__FILE__)) . '/map_helper.php';
     }
     $readAuth = data_entry_helper::get_read_auth($args['website_id'], $args['password']);
     $r = '';
     // setup the map options
     $options = iform_map_get_map_options($args, $readAuth);
     $olOptions = iform_map_get_ol_options($args);
     if (array_key_exists('table', $_GET) && $_GET['table'] == 'sample') {
         // Use a cUrl request to get the data from Indicia which contains the value we need to filter against
         // Read the record that was just posted.
         $fetchOpts = array('dataSource' => 'reports_for_prebuilt_forms/my_dot_map/occurrences_list', 'mode' => 'report', 'readAuth' => $readAuth, 'extraParams' => array('sample_id' => $_GET['id'], 'language' => $lang));
         // @todo Error handling on the response
         $occurrence = data_entry_helper::get_report_data($fetchOpts);
         self::prepare_layer_titles($args, $occurrence);
         // Add the 3 distribution layers if present. Reverse the order so 1st layer is topmost
         $layerName = self::build_distribution_layer(3, $args, $occurrence);
         if ($layerName) {
             $options['layers'][] = $layerName;
         }
         $layerName = self::build_distribution_layer(2, $args, $occurrence);
         if ($layerName) {
             $options['layers'][] = $layerName;
         }
         $layerName = self::build_distribution_layer(1, $args, $occurrence);
         if ($layerName) {
             $options['layers'][] = $layerName;
         }
         if ($layerName) {
             $options['layers'][] = $layerName;
         }
         // This is not a map used for input
         $options['editLayer'] = false;
         if ($args['hide_grid'] == false) {
             // Now output a grid of the occurrences that were just saved.
             $r .= "<table class=\"submission\"><thead><tr><th>" . lang::get('Species') . "</th><th>" . lang::get('Latin Name') . "</th><th>" . lang::get('Date') . "</th><th>" . lang::get('Spatial Ref') . "</th></tr></thead>\n";
             $r .= "<tbody>\n";
             foreach ($occurrence as $record) {
                 $r .= '<tr class="biota"><td>' . $record['lt4_taxon'] . '</td><td class="binomial"><em>' . $record['lt7_taxon'] . '</em></td><td>' . $record['lt0_date_start'] . '</td><td>' . $record['lt0_entered_sref'] . "</td></tr>\n";
             }
             $r .= "</tbody></table>\n";
         }
     }
     $r .= '<div id="mapandlegend">';
     $r .= map_helper::layer_list(array('id' => 'legend', 'includeSwitchers' => false, 'includeHiddenLayers' => false, 'includeIcons' => true, 'layerTypes' => array('overlay')));
     $r .= map_helper::map_panel($options, $olOptions);
     $r .= '</div>';
     return $r;
 }
Esempio n. 3
0
 /**
  * Return the generated form output.
  * @return Form HTML.
  * @todo: Implement this method
  */
 public static function get_form($args)
 {
     global $user;
     $readAuth = data_entry_helper::get_read_auth($args['website_id'], $args['password']);
     // setup the map options
     $options = iform_map_get_map_options($args, $readAuth);
     $olOptions = iform_map_get_ol_options($args);
     if (array_key_exists('table', $_GET) && $_GET['table'] == 'sample') {
         // Use a cUrl request to get the data from Indicia which contains the value we need to filter against
         // Read the record that was just posted.
         $fetchOpts = array('dataSource' => 'reports_for_prebuilt_forms/my_dot_map/occurrences_list', 'mode' => 'report', 'readAuth' => $readAuth, 'extraParams' => array('sample_id' => $_GET['id'], 'language' => iform_lang_iso_639_2($user->lang)));
         // @todo Error handling on the response
         $occurrence = data_entry_helper::get_report_data($fetchOpts);
         $legend = '';
         self::prepare_layer_titles($args, $occurrence);
         // Add the 3 distribution layers if present. Reverse the order so 1st layer is topmost
         $layerName = self::build_distribution_layer(3, $args, $occurrence);
         if ($layerName) {
             $options['layers'][] = $layerName;
             $legend = '<div><img src="' . data_entry_helper::$geoserver_url . 'wms?SERVICE=WMS&VERSION=1.1.1&REQUEST=GetLegendGraphic&LAYER=detail_occurrences&Format=image/jpeg' . '&STYLE=' . $args["wms_dist_3_style"] . '" alt=""/>' . $args["wms_dist_3_title"] . '</div>' . $legend;
         }
         $layerName = self::build_distribution_layer(2, $args, $occurrence);
         if ($layerName) {
             $options['layers'][] = $layerName;
             $legend = '<div><img src="' . data_entry_helper::$geoserver_url . 'wms?SERVICE=WMS&VERSION=1.1.1&REQUEST=GetLegendGraphic&LAYER=detail_occurrences&Format=image/jpeg' . '&STYLE=' . $args["wms_dist_2_style"] . '" alt=""/>' . $args["wms_dist_2_title"] . '</div>' . $legend;
         }
         $layerName = self::build_distribution_layer(1, $args, $occurrence);
         if ($layerName) {
             $options['layers'][] = $layerName;
             $legend = '<div><img src="' . data_entry_helper::$geoserver_url . 'wms?SERVICE=WMS&VERSION=1.1.1&REQUEST=GetLegendGraphic&LAYER=detail_occurrences&Format=image/png' . '&STYLE=' . $args["wms_dist_1_style"] . '" alt=""/>' . $args["wms_dist_1_title"] . '</div>' . $legend;
         }
         if ($layerName) {
             $options['layers'][] = $layerName;
         }
         // This is not a map used for input
         $options['editLayer'] = false;
         // Now output a grid of the occurrences that were just saved.
         $r .= "<table class=\"submission\"><thead><tr><th>" . lang::get('Species') . "</th><th>" . lang::get('Latin Name') . "</th><th>" . lang::get('Date') . "</th><th>" . lang::get('Spatial Ref') . "</th></tr></thead>\n";
         $r .= "<tbody>\n";
         foreach ($occurrence as $record) {
             $r .= '<tr class="biota"><td>' . $record['lt4_taxon'] . '</td><td class="binomial"><em>' . $record['lt7_taxon'] . '</em></td><td>' . $record['lt0_date_start'] . '</td><td>' . $record['lt0_entered_sref'] . "</td></tr>\n";
         }
         $r .= "</tbody></table>\n";
         $r .= '<div id="legend" class="ui-widget ui-widget-content ui-corner-all">' . $legend . '</div>';
     }
     $r .= data_entry_helper::map_panel($options, $olOptions);
     return $r;
 }
 public function register()
 {
     try {
         $this->authenticate('write');
         self::string_validate_mandatory('email');
         self::string_validate_mandatory('surname');
         self::int_key_validate_mandatory('website_id');
         self::boolean_validate('alert_on_entry');
         self::boolean_validate('alert_on_verify');
         self::int_key_validate('location_id');
         if (!empty($_GET['user_id'])) {
             $userId = $_GET['user_id'];
         } else {
             // User was not logged in when subscribing, so use their details to find or create a warehouse user id.
             $emailIdentifierObject = new stdClass();
             $emailIdentifierObject->type = "email";
             $emailIdentifierObject->identifier = $_GET["email"];
             $userIdentificationData['identifiers'] = json_encode(array($emailIdentifierObject));
             //Also pass through these fields so if a new user is required then the system can fill in the database details
             $userIdentificationData['surname'] = $_GET["surname"];
             $userIdentificationData['first_name'] = $_GET["first_name"];
             //Call existing user identifier code that will either fetch an existing user for that email, or create a new one.
             $userDetails = user_identifier::get_user_id($userIdentificationData, $_GET["website_id"]);
             if (!empty($userDetails['userId'])) {
                 $userId = $userDetails['userId'];
             } else {
                 $userId = $userDetails['possibleMatches'][0]['user_id'];
             }
         }
         //Store the species alert for the user (which is either a new or existing user as determined by get_user_id)
         self::store_species_alert($userId);
         //Automatically register the user to receive email notifications if they have never had any settings at all
         try {
             $readAuth = data_entry_helper::get_read_auth(0 - $userId, kohana::config('indicia.private_key'));
             $freqSettingsData = data_entry_helper::get_report_data(array('dataSource' => 'library/user_email_notification_settings/user_email_notification_settings_inc_deleted', 'readAuth' => $readAuth, 'extraParams' => array('user_id' => $userId)));
             if (empty($freqSettingsData)) {
                 self::store_user_email_notification_setting($userId);
             }
         } catch (exception $e) {
             kohana::log('debug', "Unable to register user " . $userId . " for email notifications, perhaps that module is not installed?.");
         }
     } catch (Exception $e) {
         $this->handle_error($e);
     }
 }
 /**
  * Get the observer control as an autocomplete.
  */
 protected static function get_control_observerautocomplete($auth, $args, $tabAlias, $options)
 {
     global $user;
     //Get the name of the currently logged in user
     $defaultUserData = data_entry_helper::get_report_data(array('dataSource' => 'library/users/get_people_details_for_website_or_user', 'readAuth' => $auth['read'], 'extraParams' => array('user_id' => hostsite_get_user_field('indicia_user_id'), 'website_id' => $args['website_id'])));
     //If we are in edit mode then we need to get the name of the saved observer for the sample
     if (!empty($_GET['sample_id']) && !empty($args['observer_name'])) {
         $existingUserData = data_entry_helper::get_population_data(array('table' => 'sample_attribute_value', 'extraParams' => $auth['read'] + array('sample_id' => $_GET['sample_id'], 'sample_attribute_id' => $args['observer_name'])));
     }
     $observer_list_args = array_merge_recursive(array('extraParams' => array_merge($auth['read'])), $options);
     $observer_list_args['label'] = t('Observer Name');
     $observer_list_args['extraParams']['website_id'] = $args['website_id'];
     $observer_list_args['captionField'] = 'fullname_surname_first';
     $observer_list_args['id'] = 'obSelect:' . $args['observer_name'];
     $observer_list_args['report'] = 'library/users/get_people_details_for_website_or_user';
     //Auto-fill the observer name with the name of the observer of the existing saved sample if it exists,
     //else default to current user name
     if (!empty($existingUserData[0]['value'])) {
         $observer_list_args['defaultCaption'] = $existingUserData[0]['value'];
     } else {
         if (empty($_GET['sample_id'])) {
             $observer_list_args['defaultCaption'] = $defaultUserData[0]['fullname_surname_first'];
         }
     }
     return data_entry_helper::autocomplete($observer_list_args);
 }
 /**
  * Get the recorder names control
  * @param array $auth Read authorisation tokens
  * @param array $args Form configuration
  * @param array $tabAlias
  * @param array $options additional options for the control with the following possibilities
  * <li><b>defaultToCurrentUser</b><br/>
  * Set to true if the currently logged in user's name should be the default</li>
  * @return string HTML for the control.
  */
 protected static function get_control_recordernames($auth, $args, $tabAlias, $options)
 {
     iform_load_helpers(array('data_entry_helper'));
     //We don't need to touch the control in edit mode. Make the current user's name the default in add mode if the user has selected that option.
     if (empty($_GET['sample_id']) && !empty($options['defaultToCurrentUser']) && $options['defaultToCurrentUser'] == true) {
         $defaultUserData = data_entry_helper::get_report_data(array('dataSource' => 'library/users/get_people_details_for_website_or_user', 'readAuth' => $auth['read'], 'extraParams' => array('user_id' => hostsite_get_user_field('indicia_user_id'), 'website_id' => $args['website_id'])));
         data_entry_helper::$javascript .= "\$('#sample\\\\:recorder_names').val('" . $defaultUserData[0]['fullname_firstname_first'] . "');";
     }
     return data_entry_helper::textarea(array_merge(array('fieldname' => 'sample:recorder_names', 'label' => lang::get('Recorder names')), $options));
 }
 public function cudiFormButtonLink($auth, $args, $tabalias, $options, $path)
 {
     global $user;
     //Get the Count Units that are in the user's tasks list using the same report.
     $getNormalUserEditableCountUnitData = data_entry_helper::get_report_data(array('dataSource' => 'reports_for_prebuilt_forms/cudi/my_cudi_tasks', 'readAuth' => $auth['read'], 'extraParams' => array('clean_url' => $options['clean_url'], 'cudi_form_url' => $options['cudi_form_url'], 'deactivate_site_attribute_id' => $options['deactivate_site_attribute_id'], 'preferred_boundary_attribute_id' => $options['preferred_boundary_attribute_id'], 'count_unit_boundary_type_id' => $options['count_unit_boundary_type_id'], 'count_unit_type_id' => $options['count_unit_type_id'], 'is_complete_attribute_id' => $options['is_complete_attribute_id'], 'preferred_sites_attribute_id' => $options['preferred_sites_attribute_id'], 'current_user_id' => $user->profile_indicia_user_id)));
     $isNormalUserAccessibleCountUnitIds = array();
     //Convert the Count Units in the user's task list into an array of ids only.
     foreach ($getNormalUserEditableCountUnitData as $idx => $isNormalUserAccessibleDirtyItem) {
         $isNormalUserAccessibleCountUnitIds[$idx] = $isNormalUserAccessibleDirtyItem['id'];
     }
     //Only show the Cudi Form button for admin users or the Count Unit is the user's task list
     if (in_array($_GET['id'], $isNormalUserAccessibleCountUnitIds) || $options['admin_mode']) {
         global $base_url;
         $cudiFormOptions = explode('|', $options['cudiFormOptions']);
         $cudiFormPath = $cudiFormOptions[0];
         $cudiFormParam = $cudiFormOptions[1];
         $cudi_form_url = (variable_get('clean_url', 0) ? '' : '?q=') . $cudiFormPath . (variable_get('clean_url', 0) ? '?' : '&') . $cudiFormParam . '=' . $_GET[$options['urlParameter']];
         $cudiFormButtonLink = '<div>If you think any of this information is incorrect please submit a CUDI form</br>';
         $cudiFormButtonLink .= "<FORM>\n        <INPUT Type=\"BUTTON\" VALUE=\"Cudi Form\" ONCLICK=\"window.location.href='{$cudi_form_url}'\">\n      </FORM>";
         return $cudiFormButtonLink;
     }
 }
Esempio n. 8
0
 private static function user_select_for_add_sites_to_any_user_control($readAuth, $args)
 {
     $reportOptions = array('dataSource' => 'library/users/get_people_details_for_website_or_user', 'readAuth' => $readAuth, 'extraParams' => array('website_id' => $args['website_id']), 'valueField' => 'id', 'captionField' => 'fullname_surname_first');
     $userData = data_entry_helper::get_report_data($reportOptions);
     $r = '<select id="user-select">\\n';
     $r .= '<option value="">' . 'please select' . '</option>\\n';
     foreach ($userData as $userItem) {
         $r .= '<option value=' . $userItem['id'] . '>' . $userItem['fullname_surname_first'] . '</option>';
     }
     $r .= '</select>';
     return '<label>User : </label>' . $r . '<br>';
 }
 /**
  * Hierarchy map control, which can be added to user interface form configurations using [site_hierarchy_navigator.map].
  *
  * Display a map with polygons loaded onto it of a particular location type. When the user clicks on one, reloads the map layer
  * to show the intersecting polygons from the next location type. Continues down the locations hierarchy in a supplied sequence of 
  * location types (e.g. you might set the location type sequence to Country, County, Parish, Site). 
  *
  * Supply an option @layerLocationTypes with a comma separated array of the location types ID to load in top down order.
  */
 public function map($auth, $args, $tabalias, $options, $path)
 {
     global $base_root;
     //Setup the path to the cudi information sheets.
     //Include the parameter on the end of the path, but leave off the parameter values
     //as these will change for each path used.
     iform_load_helpers(array('map_helper', 'report_helper'));
     $informationSheetLinkParts = explode('|', $options['informationSheetLink']);
     $path = $base_root . base_path() . (variable_get('clean_url', 0) ? '' : '?q=') . $informationSheetLinkParts[0] . (variable_get('clean_url', 0) ? '?' : '&') . $informationSheetLinkParts[1] . '=';
     map_helper::$javascript .= "indiciaData.informationSheetLink='" . $path . "';\n";
     if (empty($options['layerLocationTypes'])) {
         return '<p>Please provide a @layerLocationTypes option for the [site_hierarchy_navigator.map] map control on the edit tab</p>';
     }
     $msg = self::check_format($options, 'layerLocationTypes', 'location_type_id (from the termlists term table)', '/^([0-9]*,\\s*)*[0-9]*\\s*$/');
     if ($msg !== true) {
         return $msg;
     }
     //This option is optional, so don't need to check if it isn't present
     $msg = self::check_format($options, 'showCountUnitsForLayers', 'location_type_id (from the termlists term table)', '/^([0-9]*,\\s*)*[0-9]*\\s*$/');
     if ($msg !== true) {
         return $msg;
     }
     drupal_add_js(iform_client_helpers_path() . 'prebuilt_forms/extensions/site_hierarchy_navigator.js');
     //The location types are supplied by the user in a comma seperated list.
     //The first number is used as the initial location type to display.
     //The second number is used after the user clicks the first time on a feature and so on
     $layerLocationTypes = explode(',', $options['layerLocationTypes']);
     //Comma seperated list of location types which signify which layers should also display the Count Unit location type.
     //This should be a subset of $layerLocationTypes.
     $showCountUnitsForLayers = explode(',', $options['showCountUnitsForLayers']);
     $locationTypesWithSymbols = explode(',', $options['locationTypesWithSymbols']);
     //Annotation location types as defined on edit tab
     $annotationTypeIds = explode(',', $options['annotationTypeIds']);
     $mapOptions = iform_map_get_map_options($args, $auth);
     $olOptions = iform_map_get_ol_options($args);
     $mapOptions['readAuth'] = $mapOptions['readAuth']['read'];
     $mapOptions['clickForSpatialRef'] = false;
     //When user clicks on map, run specified Javascript function
     $mapOptions['clickableLayersOutputMode'] = 'customFunction';
     $mapOptions['customClickFn'] = 'move_to_new_layer';
     $mapOptions['clickableLayersOutputDiv'] = '';
     //Tell the system which layers we to be clickable.
     $mapOptions['clickableLayers'] = array('indiciaData.reportlayer');
     $r .= map_helper::map_panel($mapOptions, $olOptions);
     map_helper::$javascript .= "indiciaData.layerLocationTypes=" . json_encode($layerLocationTypes) . ";\n";
     $reportOptions = array('dataSource' => 'reports_for_prebuilt_forms/CUDI/get_layer_list_names', 'readAuth' => $auth['read'], 'mode' => 'report', 'extraParams' => array('layer_ids' => $options['layerLocationTypes']));
     //Return a list of location type names for the location type id layers list
     //provided by the user in the form structure.
     $locationTypeNamesDirty = data_entry_helper::get_report_data($reportOptions);
     //The data returned by the database is not a simple array of names, so convert the data and put into correct order
     foreach ($layerLocationTypes as $originalLayerIndex => $layerLocationTypeFromOriginalList) {
         foreach ($locationTypeNamesDirty as $locationTypeNamesData) {
             if ($locationTypeNamesData['id'] === $layerLocationTypeFromOriginalList) {
                 $locationTypeNamesClean[$originalLayerIndex] = $locationTypeNamesData['name'];
             }
         }
     }
     //Send the array of names to javascript
     map_helper::$javascript .= "indiciaData.layerLocationTypesNames=" . json_encode($locationTypeNamesClean) . ";\n";
     //Send the user supplied options for layers to display count units to Javascript
     map_helper::$javascript .= "indiciaData.showCountUnitsForLayers=" . json_encode($showCountUnitsForLayers) . ";\n";
     map_helper::$javascript .= "indiciaData.countUnitBoundaryTypeId=" . $options['countUnitBoundaryTypeId'] . ";\n";
     map_helper::$javascript .= "indiciaData.annotationTypeIds=" . json_encode($annotationTypeIds) . ";\n";
     map_helper::$javascript .= "indiciaData.deactivateSiteAttributeId=" . $options['deactivateSiteAttributeId'] . ";\n";
     //Get translatable label for top-level breadcrub item.
     map_helper::$javascript .= "indiciaData.allSitesLabel='" . lang::get('All Sites') . "';\n";
     $reportOptions = array('linkOnly' => 'true', 'dataSource' => 'reports_for_prebuilt_forms/cudi/get_boundaries_and_locations_for_cudi_map', 'readAuth' => $auth['read']);
     //Get the report options such as the Preset Parameters on the Edit Tab
     $reportOptions = array_merge(iform_report_get_report_options($args, $readAuth), $reportOptions);
     //Run the report that shows the locations (features) to the user when the map loads the first time.
     map_helper::$javascript .= "indiciaData.layerReportRequest='" . report_helper::get_report_data($reportOptions) . "';\n";
     //Options for the report that is used to draw the map breadcrumb
     $reportOptions = array('linkOnly' => 'true', 'dataSource' => 'reports_for_prebuilt_forms/CUDI/get_map_hierarchy_for_current_position', 'readAuth' => $auth['read']);
     //Get the report options such as the Preset Parameters on the Edit Tab
     $reportOptions = array_merge(iform_report_get_report_options($args, $readAuth), $reportOptions);
     //Run the report that builds the map breadcrumb.
     map_helper::$javascript .= "indiciaData.breadcrumbReportRequest='" . report_helper::get_report_data($reportOptions) . "';\n";
     return $r;
 }
Esempio n. 10
0
 protected static function get_control_locationcreatedby($auth, $args, $tabalias, $options)
 {
     //The URL parameter varies depending on whether we are viewing a count unit record or have selected a boundary to views
     if (!empty($_GET['parent_id'])) {
         $countUnitId = $_GET['parent_id'];
     }
     if ($_GET['location_id']) {
         $countUnitId = $_GET['location_id'];
     }
     //Get the created by id from view before putting it into the report. This might not be the quickest way
     //of doing this, but is perhaps more elegant as we don't write another report that is specific only to a very small part of a single project.
     //Only show in add mode
     if (!empty($countUnitId)) {
         $locationCreatedByData = data_entry_helper::get_population_data(array('table' => 'location', 'extraParams' => $auth['read'] + array('id' => $countUnitId, 'view' => 'detail'), 'nocache' => true, 'sharing' => $sharing));
         $reportOptions = array('dataSource' => 'library/users/get_people_details_for_website_or_user', 'readAuth' => $auth['read'], 'mode' => 'report', 'extraParams' => array('user_id' => $locationCreatedByData[0]['created_by_id']));
         $userData = data_entry_helper::get_report_data($reportOptions);
         return "<label>" . lang::get('LANG_Location_Created_By') . ":</label> <label>" . $userData[0]['fullname_firstname_first'] . "</label><br>";
     }
 }
 /**
  * Build a submission that the system can understand that includes the notifications we
  * want to remove.
  * @param type $auth
  * @param integer $user_id
  * @param array $options
  * 
  */
 private static function build_notifications_removal_submission($user_id, $options)
 {
     // rebuild the auth token since this is a reporting page but we need to submit data.
     $auth = data_entry_helper::get_read_write_auth(variable_get('indicia_website_id', ''), variable_get('indicia_password', ''));
     //Using 'submission_list' and 'entries' allows us to specify several top-level submissions to the system
     //i.e. we need to be able to submit several notifications.
     $submission['submission_list']['entries'] = array();
     $submission['id'] = 'notification';
     $extraParams = array('user_id' => $user_id, 'system_name' => 'indicia', 'default_edit_page_path' => '', 'view_record_page_path' => '', 'website_id' => variable_get('indicia_website_id', ''));
     //If the page is using a filter drop-down option, then collect the type of notification
     //to remove from the filter drop-down
     $extraParams['source_filter'] = empty($_POST['source-filter']) ? 'all' : $_POST['source-filter'];
     //Get the source types to remove from a hidden field if the user has configured the page
     //to use a user specified option to specify exactly what kind of notifications to display
     if (!empty($options['sourceType'])) {
         $sourceTypesToClearFromConfig = explode(',', $options['sourceType']);
     }
     //Place quotes around the source type letters for the report to accept as strings
     if (!empty($sourceTypesToClearFromConfig)) {
         if (array_key_exists(0, $sourceTypesToClearFromConfig) && !empty($sourceTypesToClearFromConfig[0])) {
             foreach ($sourceTypesToClearFromConfig as &$type) {
                 $type = "'" . $type . "'";
             }
             $extraParams['source_types'] = implode(',', $sourceTypesToClearFromConfig);
         }
     }
     //If the user has supplied some config options for the different source types
     if (!empty($options['sourceTypes'])) {
         // this disables the param for picking a single source type
         $extraParams['source_filter'] = 'all';
     }
     //Only include notifications associated with a set of recording group ids if option is supplied.
     if (!empty($options['groupIds'])) {
         $extraParams['group_ids'] = $options['groupIds'];
     }
     // respect training mode
     if (hostsite_get_user_field('training')) {
         $extraParams['training'] = 'true';
     }
     $notifications = data_entry_helper::get_report_data(array('dataSource' => 'library/notifications/notifications_list_for_notifications_centre', 'readAuth' => $auth['read'], 'extraParams' => $extraParams));
     $count = 0;
     if (count($notifications) > 0) {
         //Setup the structure we need to submit.
         foreach ($notifications as $notification) {
             $data['id'] = 'notification';
             $data['fields']['id']['value'] = $notification['notification_id'];
             $data['fields']['acknowledged']['value'] = 't';
             $submission['submission_list']['entries'][] = $data;
             $count++;
         }
         //Submit the stucture for processing
         $response = data_entry_helper::forward_post_to('save', $submission, $auth['write_tokens']);
         if (is_array($response) && array_key_exists('success', $response)) {
             if ($count === 1) {
                 drupal_set_message(lang::get("1 notification has been removed."));
             } else {
                 drupal_set_message(lang::get("{1} notifications have been removed.", $count));
             }
         } else {
             drupal_set_message(print_r($response, true));
         }
     }
 }
 private static function transfer_occurrences_to_third_level_samples($modelWrapped, $thirdLevelSamples, $presentSpeciesListSubSampleIds, $gpsArray, $website_id, $password, $gpxDataAttrId)
 {
     //Loop through each 2nd level sample.
     foreach ($modelWrapped['subModels'] as $secondLevelSampleIdx => &$secondLevelSample) {
         //Only work on the second level sample in the situation where there are some third level samples to create for it ready to put an occurrence onto.
         if (!empty($secondLevelSample['model']['fields']['id']['value']) && !empty($presentSpeciesListSubSampleIds)) {
             if (in_array($secondLevelSample['model']['fields']['id']['value'], $presentSpeciesListSubSampleIds)) {
                 foreach ($thirdLevelSamples as $thirdLevelSample) {
                     //Add the media currently attached to the second-level sample  to the empty third level sample
                     foreach ($secondLevelSample['model']['subModels'] as $subSampleMedium) {
                         //Add the third level sample to the second level sample, but only if the image added to the third level sample's occurrence matches one on the second level sample (the second level
                         //sample image is going to be deleted in a minute)
                         if ($subSampleMedium['model']['fields']['path']['value'] == $thirdLevelSample['model']['subModels'][0]['model']['subModels'][0]['model']['fields']['path']['value']) {
                             //Need to get exifs for media items
                             $readAuth = data_entry_helper::get_read_auth($website_id, $password);
                             //Use this report to return the photos
                             $reportName = 'reports_for_prebuilt_forms/seasearch/get_media_for_media_id';
                             $reportOptions = array('readAuth' => $readAuth, 'dataSource' => $reportName, 'extraParams' => array('media_ids' => $subSampleMedium['model']['fields']['id']['value']));
                             $photoResults = data_entry_helper::get_report_data($reportOptions);
                             //TODO this code is very similar to code used earlier, perhaps put in separate method when get chance.
                             $mediaSpatialRefs = array();
                             $smallestTimeDistance = null;
                             $photoResultExifDecoded = json_decode($photoResults[0]['exif'], true);
                             $photoResultExifFormatted = strtotime($photoResultExifDecoded['EXIF']['DateTimeOriginal']);
                             foreach ($gpsArray as $gpsArrayPosTimeString) {
                                 $gpsArrayPosTimeArray = explode(',', $gpsArrayPosTimeString);
                                 $gpsArrayPosTimeArray[2] = self::convertGPXDateToStrToTimeCompatibleFormat($gpsArrayPosTimeArray[2]);
                                 $timeDistance = strtotime($gpsArrayPosTimeArray[2]) - $photoResultExifFormatted;
                                 //We are only interested in finding the closet GPX time to the exif one, as exif times can be earlier or later than the GPX one, we need
                                 //to ignore whether it is earlier or later and just find cloest match, so if the number is negative then make it positive.
                                 if ($timeDistance < 0) {
                                     $timeDistance = $timeDistance * -1;
                                 }
                                 if ($smallestTimeDistance === null || $timeDistance < $smallestTimeDistance) {
                                     $smallestTimeDistance = $timeDistance;
                                     $mediaSpatialRef = $gpsArrayPosTimeArray[0] . ',' . $gpsArrayPosTimeArray[1];
                                 }
                             }
                             if (!empty($mediaSpatialRef)) {
                                 $northSouthPos = self::convert_to_north_south_lat_lon($mediaSpatialRef);
                                 //Automatically select the correct lat,lon position from the GPS file.
                                 $thirdLevelSample['model']['fields']['entered_sref']['value'] = $northSouthPos;
                             } else {
                                 //If there is no GPS match then fall back on the spatial reference for the main sample (e.g. we didn't upload a GPX file)
                                 $thirdLevelSample['model']['fields']['entered_sref']['value'] = $modelWrapped['fields']['entered_sref']['value'];
                             }
                             //Only add third level samples which have had their occurrence setup, else the third level sample isn't intended for this habitat (second level sample)
                             if (!empty($thirdLevelSample['model']['subModels'])) {
                                 $secondLevelSample['model']['subModels'][] = $thirdLevelSample;
                             }
                         }
                     }
                 }
                 //Clear any media already associated with the second level sample, as this media will now be held at the 3rd level.
                 self::set_sub_sample_media_items_to_deleted($secondLevelSample);
             }
         }
     }
     return $modelWrapped;
 }
 /**
  * Handles the construction of a submission array from a set of form values.
  * This is different to a standard location submission because when we submit a new additional square, we find any vice counties the
  * square intersects with, and then we save them to a custom attribute ready for use in the square's name. We use a custom attribute as
  * it is faster than doing the intersection in real-time, particularly in report grids.
  * 
  * @param array $values Associative array of form data values. 
  * @param array $args iform parameters. 
  * @return array Submission structure.
  */
 public static function get_submission($values, $args)
 {
     $s = parent::get_submission($values, $args);
     //We only want to find vice counties for additional squares and when in add mode.
     if (!empty($_GET['location_type_id']) && $_GET['location_type_id'] != $args['core_square_id']) {
         $readAuth = data_entry_helper::get_read_auth($args['website_id'], $args['password']);
         $userData = data_entry_helper::get_population_data(array('table' => 'user', 'extraParams' => $readAuth + array('id' => hostsite_get_user_field('indicia_user_id'))));
         $s['subModels'][] = array('fkId' => 'int_value', 'model' => array('id' => 'person_attribute_value', 'fields' => array('person_id' => $userData[0]['person_id'], 'person_attribute_id' => $args['user_squares_person_attr_id'])));
         //Use a report to collect the names of the vice counties that intersect the square.
         $readAuth = data_entry_helper::get_read_auth($args['website_id'], $args['password']);
         $reportOptions = array('dataSource' => 'reports_for_prebuilt_forms/Splash/get_vice_county_names_for_grid_ref', 'readAuth' => $readAuth, 'extraParams' => array('website_id' => $args['website_id'], 'vice_county_location_type_id' => $args['vice_county_location_type_id'], 'square_grid_ref' => $s['fields']['geom']['value']), 'valueField' => 'id', 'captionField' => 'name');
         $squareViceCountyData = data_entry_helper::get_report_data($reportOptions);
         //Build up a comma seperate list of vice counties if the square interects more than one.
         $squareViceCountyDataForDatabase = '';
         foreach ($squareViceCountyData as $squareViceCounty) {
             if (isset($squareViceCounty['name'])) {
                 $squareViceCountyDataForDatabase .= $squareViceCounty['name'] . ', ';
             }
         }
         //Chop off the last comma and space
         if (!empty($squareViceCountyDataForDatabase)) {
             $squareViceCountyDataForDatabase = substr($squareViceCountyDataForDatabase, 0, -2);
         }
         //Save the custom attribute which holds the vice counties.
         if (!empty($squareViceCountyData[0]['name'])) {
             $s['subModels'][] = array('fkId' => 'location_id', 'model' => array('id' => 'location_attribute_value', 'fields' => array('text_value' => $squareViceCountyDataForDatabase, 'location_attribute_id' => $args['square_vice_county_location_attr_id'])));
         }
     }
     return $s;
 }
 /**
  * Return the generated form output.
  * @param array $args List of parameter values passed through to the form depending on how the form has been configured.
  * This array always contains a value for language.
  * @param object $node The Drupal node object.
  * @param array $response When this form is reloading after saving a submission, contains the response from the service call.
  * Note this does not apply when redirecting (in this case the details of the saved object are in the $_GET data).
  * @return Form HTML.
  * @todo: Implement this method 
  */
 public static function get_form($args, $node, $response = null)
 {
     if (empty($args['group_id'])) {
         drupal_set_message('Please specify a group_id in the page configuration.');
     }
     if (empty($args['instructions_configuration'])) {
         drupal_set_message('Please provide a page configuration in the User Interface options.');
     }
     //Only perform if the user has specified an instruction to appear under each page like.
     if (!empty($args['instructions_configuration'])) {
         $configuration = data_entry_helper::explode_lines($args['instructions_configuration']);
         $key = '';
         $description = '';
         //Keep track of the ordering of the titles
         $titleNumber = 0;
         //For each configured line we need to find all the descriptions and store them against the page titles in an array
         foreach ($configuration as $configLineNum => $configurationLine) {
             //If line is a link title (specified inside square brackets)
             if (preg_match('/^\\[.+\\]$/', $configurationLine)) {
                 //If this isn't the first title, then we need to store the description for the previous title into an
                 //array. The key is a number representing the order of the titles in the configuration, the sub array key is the name of the page link.
                 if (!empty($key)) {
                     $titleDescriptions[$titleNumber] = array($key => $description);
                     $description = '';
                 }
                 //Get the next array key we will use from the specified page link title. Chop the square brackets off the ends.
                 $key = substr($configurationLine, 1, -1);
                 $titleNumber++;
             } else {
                 //If the line does not use square brackets then we know it is part of the description/instruction. We do an
                 //append as the instruction might span several lines.
                 $description .= $configurationLine;
             }
         }
         //For the last description we still need to save it to the array.
         $titleDescriptions[$titleNumber] = array($key => $description);
         $description = '';
     }
     $r = '';
     global $user;
     $auth = data_entry_helper::get_read_write_auth($args['website_id'], $args['password']);
     //Get all the links to display
     $reportOptions = array('dataSource' => 'library/groups/groups_list', 'readAuth' => $auth['read'], 'mode' => 'report', 'extraParams' => array('currentUser' => hostsite_get_user_field('indicia_user_id'), 'id' => $args['group_id'], 'pending_path' => '{rootFolder}?q=groups/pending&group_id=', 'userFilterMode' => 'member'));
     // automatic handling for Drupal clean urls.
     $pathParam = function_exists('variable_get') && variable_get('clean_url', 0) == '0' ? 'q' : '';
     $rootFolder = helper_base::getRootFolder() . (empty($pathParam) ? '' : "?{$pathParam}=");
     $groupsData = data_entry_helper::get_report_data($reportOptions);
     if (empty($groupsData)) {
         if (!empty($args['no_group_found_message'])) {
             $r = '<div>' . $args['no_group_found_message'] . '</div>';
         } else {
             $r = '<div>' . 'Sorry, you do not appear to be a member of this group so there are no links to display.' . '</div>';
         }
         return $r;
     }
     foreach ($groupsData as $groupDataItem) {
         $pageLinks = $groupDataItem['pages'];
         $groupTitle = $groupDataItem['title'];
     }
     //All the page links come out of the database in one cluster. Explode these so we have each link separately
     $explodedPageLinks = explode('</a>', $pageLinks);
     // reinsert the closing </a> used in the explode above
     foreach ($explodedPageLinks as &$pageLink) {
         $pageLink .= '</a>';
     }
     $pageLinkHtml = '';
     //Go through all the page links to display
     foreach ($titleDescriptions as $titleDescArr) {
         foreach ($explodedPageLinks as &$pageLink) {
             //Each page link is a html link, we just want the plain name
             $plainPageLink = trim(strip_tags($pageLink));
             //If the user has specified an instruction/description for the page link, then display the instruction in the lines following the link
             //using italics.
             if (array_key_exists($plainPageLink, $titleDescArr)) {
                 if (!empty($titleDescArr[$plainPageLink])) {
                     $pageLinkHtml .= "<h3>{$pageLink}</a></h3><p>{$titleDescArr[$plainPageLink]}</p>\n";
                 } else {
                     $pageLinkHtml .= "<h3>{$pageLink}</a></h3>";
                 }
             }
         }
     }
     $r = "<div><h2>{$groupTitle} Links</h2>";
     $r .= str_replace(array('{rootFolder}', '{sep}'), array($rootFolder, strpos($rootFolder, '?') === FALSE ? '?' : '&'), $pageLinkHtml);
     $r .= '</div><br>';
     $r .= parent::get_form($args, $node, $response = null);
     return $r;
 }