private static function _getCacheFileName($userID)
 {
     /* If timeout is not set, we're not caching */
     $path = data_entry_helper::$cache_folder ? data_entry_helper::$cache_folder : data_entry_helper::relative_client_helper_path() . 'cache/';
     if (!is_dir($path) || !is_writeable($path)) {
         return false;
     }
     return $path . 'cache_' . data_entry_helper::$website_id . '_CMS_User_List_' . $userID;
 }
Пример #2
0
 private static function get_template_with_map($args, $readAuth, $extraParams, $paramDefaults)
 {
     $r = '<div id="outer-with-map" class="ui-helper-clearfix">';
     $r .= '<div id="grid" class="left" style="width:65%">{paramsForm}{grid}</div>';
     $r .= '<div id="map-and-record" class="right" style="width: 34%"><div id="summary-map">';
     $options = iform_map_get_map_options($args, $readAuth);
     $olOptions = iform_map_get_ol_options($args);
     // This is used for drawing, so need an editlayer, but not used for input
     $options['editLayer'] = true;
     $options['editLayerInSwitcher'] = true;
     $options['clickForSpatialRef'] = false;
     $options['featureIdField'] = 'occurrence_id';
     $r .= map_helper::map_panel($options, $olOptions);
     $reportMapOpts = array('dataSource' => !empty($args['mapping_report_name']) ? $args['mapping_report_name'] : $args['report_name'], 'mode' => 'report', 'readAuth' => $readAuth, 'autoParamsForm' => false, 'extraParams' => $extraParams, 'paramDefaults' => $paramDefaults, 'reportGroup' => 'verification', 'clickableLayersOutputMode' => 'report', 'rowId' => 'occurrence_id', 'sharing' => 'verification', 'ajax' => TRUE);
     if (!empty($args['mapping_report_name_lores'])) {
         $reportMapOpts['dataSourceLoRes'] = $args['mapping_report_name_lores'];
     }
     $r .= report_helper::report_map($reportMapOpts);
     $r .= '</div>';
     global $user;
     if (function_exists('hostsite_get_user_field') && ($locationId = hostsite_get_user_field('location_expertise', false))) {
         iform_map_zoom_to_location($locationId, $readAuth);
     }
     $r .= '<div id="record-details-wrap" class="ui-widget ui-widget-content">';
     $r .= self::instructions('grid on the left');
     $r .= '<div id="record-details-content" style="display: none">';
     $r .= '<div id="record-details-toolbar">';
     $r .= '<div id="verify-buttons">';
     $r .= '<div id="verify-buttons-inner">';
     $r .= '<label>' . lang::get('Actions:') . '</label>';
     $imgPath = empty(data_entry_helper::$images_path) ? data_entry_helper::relative_client_helper_path() . "../media/images/" : data_entry_helper::$images_path;
     $r .= '<button type="button" id="btn-verify" title="' . lang::get('Verify') . '"><img width="18" height="18" src="' . $imgPath . 'nuvola/ok-16px.png"/></button>';
     $r .= '<button type="button" id="btn-edit-verify" title="' . lang::get('Edit determination then verify') . '"><img width="18" height="18" src="' . $imgPath . 'nuvola/package_editors-16px.png"/>' . '<img width="18" height="18" src="' . $imgPath . 'nuvola/ok-16px.png"/></button>';
     $r .= '<button type="button" id="btn-reject" title="' . lang::get('Reject') . '"><img width="18" height="18" src="' . $imgPath . 'nuvola/cancel-16px.png"/></button>';
     $r .= '<button type="button" id="btn-query" title="' . lang::get('Query') . '"><img width="18" height="18" src="' . $imgPath . 'nuvola/dubious-16px.png"/></button>';
     $r .= '<div id="redet-dropdown-ctnr" style="display: none"><div id="redet-dropdown">';
     $r .= data_entry_helper::species_autocomplete(array('fieldname' => 'redet', 'label' => lang::get('New determination'), 'labelClass' => 'auto', 'helpText' => lang::get('Enter a new determination for this record before verifying it. The previous determination will be stored with the record.'), 'cacheLookup' => true, 'extraParams' => $readAuth + array('taxon_list_id' => 1), 'speciesIncludeBothNames' => true, 'speciesIncludeTaxonGroup' => true));
     $r .= '</div></div>';
     $r .= '</div></div>';
     $r .= '<label>Contact:</label>';
     $r .= '<button type="button" id="btn-email-expert" class="default-button">' . lang::get('Another expert') . '</button>';
     $r .= '<button type="button" id="btn-email-recorder" class="default-button">' . lang::get('Recorder') . '</button>';
     $r .= '</div>';
     $r .= '<div id="record-details-tabs">';
     // note - there is a dependency in the JS that comments is the last tab and media the 2nd to last.
     $r .= data_entry_helper::tab_header(array('tabs' => array('#details-tab' => lang::get('Details'), '#experience-tab' => lang::get('Experience'), '#phenology-tab' => lang::get('Phenology'), '#media-tab' => lang::get('Media'), '#comments-tab' => lang::get('Comments'))));
     data_entry_helper::$javascript .= "indiciaData.detailsTabs = ['details','experience','phenology','media','comments'];\n";
     data_entry_helper::enable_tabs(array('divId' => 'record-details-tabs'));
     $r .= '<div id="details-tab"></div>';
     $r .= self::other_tab_html();
     $r .= '</div></div></div></div></div>';
     return $r;
 }
Пример #3
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;
 }
Пример #4
0
 /**
  * Takes a file that has been uploaded to the client website upload folder, and moves it to the warehouse upload folder using the
  * data services.
  *
  * @param string $path Path to the file to upload, relative to the interim image path folder (normally the
  * client_helpers/upload folder.
  * @param boolean $persist_auth Allows the write nonce to be preserved after sending the file, useful when several files
  * are being uploaded.
  * @return string Error message, or true if successful.
  */
 private static function send_file_to_warehouse($path, $persist_auth = false)
 {
     $interim_image_folder = isset(parent::$interim_image_folder) ? parent::$interim_image_folder : 'upload/';
     $uploadpath = data_entry_helper::relative_client_helper_path() . $interim_image_folder;
     $serviceUrl = parent::$base_url . "/index.php/services/data/handle_media";
     // This is used by the file box control which renames uploaded files using a guid system, so disable renaming on the server.
     $postargs = array('name_is_guid' => 'true');
     // attach authentication details
     if (array_key_exists('auth_token', $_POST)) {
         $postargs['auth_token'] = $_POST['auth_token'];
     }
     if (array_key_exists('nonce', $_POST)) {
         $postargs['nonce'] = $_POST['nonce'];
     }
     if ($persist_auth) {
         $postargs['persist_auth'] = 'true';
     }
     $file_to_upload = array('media_upload' => '@' . realpath($uploadpath . $path));
     $response = data_entry_helper::http_post($serviceUrl, $file_to_upload + $postargs);
     $output = json_decode($response['output'], true);
     $r = true;
     // default is success
     if (is_array($output)) {
         //an array signals an error
         if (array_key_exists('error', $output)) {
             // return the most detailed bit of error information
             if (isset($output['errors']['media_upload'])) {
                 $r = $output['errors']['media_upload'];
             } else {
                 $r = $output['error'];
             }
         }
     }
     //remove local copy
     //unlink(realpath($uploadpath.$path));
     watchdog('file exists', realpath($uploadpath . $path));
     return $r;
 }
 private static function get_notifications_html($auth, $sourceType, $website_id, $user_id, $options)
 {
     iform_load_helpers(array('report_helper'));
     $imgPath = empty(data_entry_helper::$images_path) ? data_entry_helper::relative_client_helper_path() . "../media/images/" : data_entry_helper::$images_path;
     $sendReply = $imgPath . "nuvola/mail_send-22px.png";
     $cancelReply = $imgPath . "nuvola/mail_delete-22px.png";
     //When the user wants to reply to a message, we have to add a new row
     report_helper::$javascript .= "\n    indiciaData.reply_to_message = function(notification_id, occurrence_id) {\n      if (!\$('#reply-row-'+occurrence_id).length) {\n        rowHtml = '<tr id='+\"reply-row-\"+occurrence_id+'><td><label for=\"\">" . lang::get('Enter your reply below') . ":</label><textarea style=\"width: 95%\" id=\"reply-' +occurrence_id+'\"></textarea></td>';\n        rowHtml += '<td class=\"actions\">';\n        rowHtml += '<div><img class=\"action-button\" src=\"{$sendReply}\" onclick=\"reply('+occurrence_id+','+notification_id+',true);\" title=\"Send reply\">';\n        rowHtml += '<img class=\"action-button\" src=\"{$cancelReply}\" onclick=\"reply('+occurrence_id+','+notification_id+',false);\" title=\"Cancel reply\">';\n        rowHtml += '</div></td></tr>';\n        \$(rowHtml).insertAfter('tr#row'+notification_id);\n        \$('tr#row'+notification_id+' .action-button').hide();\n      }\n    };\n\n    ";
     $urlParams = array('occurrence_id' => '{occurrence_id}');
     if (!empty($_GET['group_id'])) {
         $urlParams['group_id'] = $_GET['group_id'];
     }
     $availableActions = array(array('caption' => lang::get('Edit this record'), 'class' => 'edit-notification', 'url' => '{rootFolder}{editing_form}', 'urlParams' => $urlParams, 'img' => $imgPath . 'nuvola/package_editors-22px.png', 'visibility_field' => 'editable_flag'), array('caption' => lang::get('View this record'), 'class' => 'view-notification', 'url' => '{rootFolder}{viewing_form}', 'urlParams' => $urlParams, 'img' => $imgPath . 'nuvola/find-22px.png', 'visibility_field' => 'viewable_flag'), array('caption' => lang::get('Mark as read'), 'javascript' => 'remove_message({notification_id});', 'img' => $imgPath . 'nuvola/kmail-22px.png'));
     //Only allow replying for 'user' messages.
     if (isset($options['allowReply']) && $options['allowReply'] === true) {
         $availableActions = array_merge($availableActions, array(array('caption' => lang::get('Reply to this message'), 'img' => $imgPath . 'nuvola/mail_reply-22px.png', 'visibility_field' => 'reply_flag', 'javascript' => "indiciaData.reply_to_message(" . '{notification_id}' . "," . '{occurrence_id}' . ");")));
     }
     $extraParams = array('user_id' => $user_id, 'system_name' => 'indicia', 'orderby' => 'triggered_on', 'sortdir' => 'DESC', 'default_edit_page_path' => $options['default_edit_page_path'], 'view_record_page_path' => $options['view_record_page_path'], 'website_id' => $website_id);
     //Implode the source types so we can submit to the database in one text field.
     if (!empty($sourceType)) {
         $extraParams['source_types'] = "'" . implode("' ,'", $sourceType) . "'";
         //If the user has supplied some config options for the different source types then we don't need the
         // source filter drop down.
         $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'];
     }
     $columns = array('data' => array('fieldname' => 'data', 'json' => true, 'template' => '<div class="type-{source_type}"><div class="status-{record_status}"></div></div><div class="note-type-{source_type}">{comment}</div>' . '<div class="comment-from helpText" style="margin-left: 34px; display: block;">from {username} on {triggered_date}</div>', 'display' => 'Message'), 'occurrence_id' => array('fieldname' => 'occurrence_id'), 'actions' => array('actions' => $availableActions), 'triggered_date' => array('fieldname' => 'triggered_date', 'visible' => false));
     // allow columns config to override our default setup
     if (!empty($options['columns'])) {
         foreach ($options['columns'] as $column) {
             if (!empty($column['actions'])) {
                 $columns['actions'] = $column;
             } elseif (!empty($column['fieldname'])) {
                 $columns[$column['fieldname']] = $column;
             }
         }
     }
     $r = report_helper::report_grid(array('id' => 'notifications-' . $options['id'], 'readAuth' => $auth['read'], 'itemsPerPage' => 10, 'dataSource' => 'library/notifications/notifications_list_for_notifications_centre', 'rowId' => 'notification_id', 'ajax' => true, 'mode' => 'report', 'extraParams' => $extraParams, 'paramDefaults' => array('source_filter' => 'all'), 'paramsFormButtonCaption' => lang::get('Filter'), 'columns' => array_values($columns)));
     return $r;
 }
Пример #6
0
 /** 
  * Survey control that supports multiple surveys each with a date
  */
 protected static function get_control_surveys($auth, $args, $tabalias, $options)
 {
     //Get the Delete icon for the Surveys Grid
     $imgPath = empty(data_entry_helper::$images_path) ? data_entry_helper::relative_client_helper_path() . "../media/images/" : data_entry_helper::$images_path;
     $deleteIcon = $imgPath . "delete.png";
     //Pass the delete icon to javascript
     data_entry_helper::$javascript .= "indiciaData.deleteImagePath='" . $deleteIcon . "';\n";
     if (!empty($_GET['parent_id'])) {
         $countUnitId = $_GET['parent_id'];
     } else {
         $countUnitId = $_GET['location_id'];
     }
     //Get the data for all surveys that are relevant
     $surveysData = data_entry_helper::get_population_data(array('table' => 'survey', 'extraParams' => $auth['read'], 'nocache' => true, 'sharing' => $sharing));
     //If we are in edit mode, then collect the data relating to the previously selected surveys, the ID and Date are
     //held as JSON, so we need to decode it.
     if ($countUnitId) {
         $selectedSurveysData = data_entry_helper::get_population_data(array('table' => 'location_attribute_value', 'extraParams' => $auth['read'] + array('location_attribute_id' => $args['surveys_attribute_id'], 'location_id' => $countUnitId), 'nocache' => true, 'sharing' => $sharing));
         if (!empty($selectedSurveysData)) {
             foreach ($selectedSurveysData as $idx => $theSurveyData) {
                 $decodedSavedSurvey[$idx] = json_decode($theSurveyData['raw_value']);
                 $decodedSavedSurveyIds[$idx] = $decodedSavedSurvey[$idx][0];
             }
         }
     }
     //We need to populate the surveys drop-down but not include items that are already on the grid.
     $r = '<div id="surveys-control">';
     $r .= '<h3>Surveys</h3>';
     $r .= '<label>Surveys: </label><select id = "survey-select">';
     $r .= '<option id="please-select-surveys-item">Please Select</option>';
     if (!empty($surveysData)) {
         foreach ($surveysData as $surveyData) {
             if (empty($decodedSavedSurveyIds) || !in_array($surveyData['id'], $decodedSavedSurveyIds)) {
                 $r .= '<option id="survey-select-' . $surveyData['id'] . '" value="' . $surveyData['id'] . '">' . $surveyData['title'] . '</option>';
             }
             //Get the names of the survey items in the grid and save them in an array where the ids are the keys - for use in a minute
             if (!empty($decodedSavedSurveyIds)) {
                 if (in_array($surveyData['id'], $decodedSavedSurveyIds)) {
                     $surveyNameInGrid[$surveyData['id']]['title'] = $surveyData['title'];
                 }
             }
         }
     }
     $r .= '</select><br>';
     $r .= data_entry_helper::date_picker(array_merge(array('label' => lang::get('LANG_Location_Surveys_Date'), 'fieldname' => 'survey:date'), $options));
     $r .= '</br>';
     $r .= '<input type="button" id="select-surveys-add" value="Add" onclick="select_survey_and_date();"><br>';
     $r .= '<table id="surveys-table" id="surveys-table" border="3">' . '<tr>' . '<th>Survey Id</th>' . '<th>Survey Name</th>' . '<th>Date</th>' . '<th>Remove</th>' . '<th style="display:none;">Existing Attribute Id</th>' . '<th style="display:none;" type="hidden">Deleted</th></tr>' . '<tr>' . '</tr>';
     if ($countUnitId) {
         if (!empty($selectedSurveysData)) {
             foreach ($selectedSurveysData as $idx => $theSurveyData) {
                 //Add a row to the grid of Selected Suveys and Dates for each existing survey that has been saved against the Count Unit
                 //Note we use the Survey Id on the end of the various html ids. The fields that will be used in submission also have a
                 //"name" otherwise they won't show in the submission $values variable
                 $r .= "\r\n        <tr id='" . "selected-survey-row-" . $decodedSavedSurvey[$idx][0] . "'>\r\n          <td>\r\n            <input style='border: none;' id='" . "selected-survey-id-" . $decodedSavedSurvey[$idx][0] . "' name='" . "selected-survey-id-" . $decodedSavedSurvey[$idx][0] . "' value='" . $decodedSavedSurvey[$idx][0] . "' readonly>\r\n          </td>\r\n          <td>\r\n            <input style='border: none;' id='" . "selected-survey-name-" . $decodedSavedSurvey[$idx][0] . "' value='" . $surveyNameInGrid[$decodedSavedSurvey[$idx][0]]['title'] . "' readonly>\r\n          </td>\r\n          <td>\r\n            <input id='" . "selected-survey-date-" . $decodedSavedSurvey[$idx][0] . "' name='" . "selected-survey-date-" . $decodedSavedSurvey[$idx][0] . "' value='" . $decodedSavedSurvey[$idx][1] . "'>\r\n          </td>\r\n          <td>\r\n            <img class=\"action-button\" src=\"{$deleteIcon}\" onclick=\"remove_survey_selection(" . $decodedSavedSurvey[$idx][0] . ",'" . $surveyNameInGrid[$decodedSavedSurvey[$idx][0]]['title'] . "');\" title=\"Delete Survey Selection\">\r\n          </td>\r\n          <td style='display:none;'>\r\n            <input id='" . "selected-survey-existing-" . $decodedSavedSurvey[$idx][0] . "' name='" . "selected-survey-existing-" . $decodedSavedSurvey[$idx][0] . "' value='" . $theSurveyData['id'] . "'>\r\n          </td>\r\n          <td style='display:none;'>\r\n            <input id='" . "selected-survey-deleted-" . $decodedSavedSurvey[$idx][0] . "' name='" . "selected-survey-deleted-" . $decodedSavedSurvey[$idx][0] . "' value='false'>\r\n          </td>\r\n        </tr>";
             }
         }
     }
     $r .= '</table>';
     $r .= '</div>';
     return $r;
 }
Пример #7
0
 private static function get_notifications_html($auth, $sourceType, $website_id, $user_id, $options)
 {
     iform_load_helpers(array('report_helper'));
     global $auth;
     $readNonce = $auth['nonce'];
     $readAuthToken = $auth['auth_token'];
     $imgPath = empty(data_entry_helper::$images_path) ? data_entry_helper::relative_client_helper_path() . "../media/images/" : data_entry_helper::$images_path;
     $sendReply = $imgPath . "nuvola/mail_send-22px.png";
     $cancelReply = $imgPath . "nuvola/mail_delete-22px.png";
     //When the user wants to reply to a message, we have to add a new row
     report_helper::$javascript .= "\n    indiciaData.reply_to_message = function(notification_id, occurrence_id) {\n      if (!\$('#reply-row-'+occurrence_id).length) {\n        rowHtml = '<tr id='+\"reply-row-\"+occurrence_id+'><td><label for=\"\">" . lang::get('Enter your reply below') . ":</label><textarea style=\"width: 95%\" id=\"reply-' +occurrence_id+'\"></textarea></td>';\n        rowHtml += '<td class=\"actions\">';\n        rowHtml += '<div><img class=\"action-button\" src=\"{$sendReply}\" onclick=\"reply('+occurrence_id+','+notification_id+',true);\" title=\"Send reply\">';\n        rowHtml += '<img class=\"action-button\" src=\"{$cancelReply}\" onclick=\"reply('+occurrence_id+','+notification_id+',false);\" title=\"Cancel reply\">';\n        rowHtml += '</div></td></tr>';\n        \$(rowHtml).insertAfter('tr#row'+notification_id);\n        \$('tr#row'+notification_id+' .action-button').hide();\n      }\n    };\n\n    ";
     //Setup the javascript needed to support the remove notification button.
     self::setup_source_types_hidden_fields($options, $sourceType, $website_id, $auth);
     $auth = report_helper::get_read_auth(variable_get('indicia_website_id', ''), variable_get('indicia_password', ''));
     //Implode the source types so we can submit to the database in one text field.
     foreach ($sourceType as &$type) {
         $type = "'" . $type . "'";
     }
     $sourceType = implode(',', $sourceType);
     $availableActions = array(array('caption' => lang::get('Edit this record'), 'class' => 'edit-notification', 'url' => '{rootFolder}{editing_form}', 'urlParams' => array('occurrence_id' => '{occurrence_id}'), 'img' => $imgPath . 'nuvola/package_editors-22px.png', 'visibility_field' => 'editable_flag'), array('caption' => lang::get('View this record'), 'class' => 'view-notification', 'url' => '{rootFolder}{viewing_form}', 'urlParams' => array('occurrence_id' => '{occurrence_id}'), 'img' => $imgPath . 'nuvola/find-22px.png', 'visibility_field' => 'viewable_flag'), array('caption' => lang::get('Mark as read'), 'javascript' => 'remove_message({notification_id});', 'img' => $imgPath . 'nuvola/kmail-22px.png'));
     //Only allow replying for 'user' messages.
     if ($options['allowReply'] === true) {
         $availableActions = array_merge($availableActions, array(array('caption' => lang::get('Reply to this message'), 'img' => $imgPath . 'nuvola/mail_reply-22px.png', 'javascript' => "indiciaData.reply_to_message(" . '{notification_id}' . "," . '{occurrence_id}' . ");")));
     }
     return report_helper::report_grid(array('id' => 'notifications-' . $options['id'], 'readAuth' => $auth, 'itemsPerPage' => 10, 'dataSource' => 'library/notifications/notifications_list_for_notifications_centre', 'rowId' => 'notification_id', 'ajax' => true, 'mode' => 'report', 'extraParams' => array('user_id' => $user_id, 'system_name' => 'indicia', 'source_types' => $sourceType, 'orderby' => 'triggered_on', 'sortdir' => 'DESC', 'default_edit_page_path' => $options['default_edit_page_path'], 'view_record_page_path' => $options['view_record_page_path'], 'website_id' => $website_id), 'columns' => array(array('fieldname' => 'data', 'json' => true, 'template' => '<div class="type-{source_type}"><div class="status-{record_status}"></div></div><div class="note-type-{source_type}">{comment}</div>' . '<div class="comment-from helpText" style="margin-left: 34px; display: block;">from {username} on {triggered_date}</div>', 'display' => 'Message'), array('actions' => $availableActions), array('fieldname' => 'triggered_date', 'visible' => false))));
 }
 private static function get_comments($readAuth, $includeAddNew = true)
 {
     iform_load_helpers(array('data_entry_helper'));
     $comments = data_entry_helper::get_population_data(array('table' => 'sample_comment', 'extraParams' => $readAuth + array('sample_id' => $_GET['sample_id'], 'sortdir' => 'DESC', 'orderby' => 'updated_on'), 'nocache' => true, 'sharing' => 'verification'));
     $imgPath = empty(data_entry_helper::$images_path) ? data_entry_helper::relative_client_helper_path() . "../media/images/" : data_entry_helper::$images_path;
     $r = '';
     if (count($comments) === 0) {
         $r .= '<p id="no-comments">' . lang::get('No comments have been made.') . '</p>';
     }
     $r .= '<div id="comment-list">';
     foreach ($comments as $comment) {
         $r .= '<div class="comment">';
         $r .= '<div class="header">';
         $r .= self::status_icons($comment['record_status'], $imgPath);
         if ($comment['query'] === 't') {
             $hint = lang::get('This is a query');
             $r .= "<img width=\"12\" height=\"12\" src=\"{$imgPath}nuvola/dubious-16px.png\" title=\"{$hint}\" alt=\"{$hint}\"/>";
         }
         $r .= '<strong>' . (empty($comment['person_name']) ? $comment['username'] : $comment['person_name']) . '</strong> ';
         $commentTime = strtotime($comment['updated_on']);
         // Output the comment time. Skip if in future (i.e. server/client date settings don't match)
         if ($commentTime < time()) {
             $r .= self::ago($commentTime);
         }
         $r .= '</div>';
         $c = str_replace("\n", '<br/>', $comment['comment']);
         $r .= "<div>{$c}</div>";
         $r .= '</div>';
     }
     $r .= '</div>';
     if ($includeAddNew) {
         $r .= '<form><fieldset><legend>' . lang::get('Add new comment') . '</legend>';
         $r .= '<textarea id="comment-text"></textarea><br/>';
         $r .= '<button type="button" class="default-button" onclick="saveComment(jQuery(\'#comment-text\').val());">' . lang::get('Save') . '</button>';
         $r .= '</fieldset></form>';
     }
     return $r;
 }
Пример #9
0
 /**
  * Return the Indicia form code
  * @param array $args Input parameters.
  * @param array $node Drupal node object
  * @param array $response Response from Indicia services after posting.
  * @return HTML string
  */
 public static function get_form($args, $node, $response)
 {
     $r = "";
     data_entry_helper::add_resource('jquery_ui');
     if (isset($args['advancedUI']) && $args['advancedUI']) {
         // TODO Sort out
         //    	data_entry_helper::$resource_list['jquery_ui_slider'] =
         //    		array('deps' => array('jquery_ui'), 'javascript' => array('/misc/ui/jquery.ui.slider.js'));
         //    	data_entry_helper::add_resource('jquery_ui_slider');
         //      drupal_add_js(drupal_get_path('module', 'jquery_update') .'/replace/ui/ui/jquery.ui.slider.js');
         //      drupal_add_js('/misc/ui/jquery.ui.slider.min.js');
         drupal_add_js('/misc/ui/jquery.ui.slider.js');
         //      drupal_add_js('/misc/ui/jquery.ui.button.min.js');
     }
     $readAuth = data_entry_helper::get_read_auth($args['website_id'], $args['password']);
     $now = new DateTime('now');
     $year = isset($_REQUEST['year']) ? $_REQUEST['year'] : ($year = $now->format('Y'));
     iform_load_helpers(array('report_helper', 'map_helper'));
     $options = iform_report_get_report_options($args, $readAuth);
     $currentParamValues = array();
     if (isset($options['extraParams'])) {
         foreach ($options['extraParams'] as $key => $value) {
             // trim data to ensure blank lines are not handled.
             $key = trim($key);
             $value = trim($value);
             // We have found a parameter, so put it in the request to the report service
             if (!empty($key)) {
                 $currentParamValues[$key] = $value;
             }
         }
     }
     $extras = '&wantColumns=1&wantParameters=1&' . report_helper::array_to_query_string($currentParamValues, true);
     $canIDuser = false;
     // Report record should have location_id, sample_id, occurrence_id, sample_date, species ttl_id, attributes, geometry. created_by_id is optional
     // Event definition: Name|attribute_id|attribute_values
     // Loop through event definitions
     /*    $events = array(array('type'=>'arrayVal', 'name'=>'Budburst', 'attr'=>'289', 'values'=>array(3904,3961,3905,3906,3962,3907)),
           array('type'=>'arrayVal', 'name'=>'Leaf', 'attr'=>'289', 'values'=>array(3906,3962,3907)),
           array('type'=>'arrayVal', 'name'=>'Flowering', 'attr'=>'291', 'values'=>array(3912,3913,3914,3916,3917,3918)),
           array('type'=>'presence', 'name'=>'Presence')); */
     $events = str_replace("\r\n", "\n", $args['triggerEvents']);
     $events = str_replace("\r", "\n", $events);
     $events = explode("\n", trim($events));
     foreach ($events as $idx => $event) {
         $events[$idx] = explode(':', $event);
     }
     $triggerEvents = array();
     $SpeciesEventSelections = array();
     $Species = array();
     $r .= '<div id="errorMsg"></div>' . '<table class="ui-widget ui-widget-content ui-corner-all controls-table" id="controls-table">' . '<thead class="ui-widget-header">' . '<tr><th><label for="yearControl">' . lang::get("Year") . ' : </label><select id="yearControl" name="year">';
     for ($i = $now->format('Y'); $i >= $args['first_year']; $i--) {
         $r .= '<option value="' . $i . '">' . $i . '</option>';
     }
     $r .= '</select></th>' . '<th><label for="speciesControl">' . lang::get("Species") . ' : </label><select id="speciesControl"><option value="">' . lang::get("Please select species") . '</option></select></th>' . '<th><label for="eventControl">' . lang::get("Event") . ' : </label><select id="eventControl"><option value="">' . lang::get("Please select event") . '</option>';
     foreach ($events as $index => $event) {
         $r .= '<option value="' . $index . '">' . $event[0] . '</option>';
         $triggerEvents[] = '{"name":"' . $event[0] . '","type":"' . $event[1] . '"' . (count($event) > 2 ? ',"attr":' . $event[2] . ',"values":[' . $event[3] . ']' : '') . '}';
     }
     $r .= "</select></th>\n";
     if (isset($args['twinMaps']) && $args['twinMaps']) {
         $r .= '<th><label for="rhsCtrl">' . lang::get("Compare") . ' : </label><select id="rhsCtrl" name="rhsCtrl"><option value="">' . lang::get("Please select.") . '</option><option value="Test">' . lang::get("Test.") . "</option></select></th>\n";
     }
     $r .= '</tr></thead></table>' . "\n";
     $args['map_width'] = "auto";
     $options = iform_map_get_map_options($args, $readAuth);
     $olOptions = iform_map_get_ol_options($args);
     $options['editLayer'] = false;
     $options['clickForSpatialRef'] = false;
     $options['scroll_wheel_zoom'] = false;
     $r .= '<div class="leftMap mapContainers leftMapOnly">' . map_helper::map_panel($options, $olOptions) . '</div>';
     $options['divId'] = 'map2';
     if (isset($args['twinMaps']) && $args['twinMaps']) {
         $r .= '<div class="rightMap mapContainers leftMapOnly">' . map_helper::map_panel($options, $olOptions) . '</div>';
     }
     $r .= '<div class="ui-helper-clearfix"></div><div id="timeControls">' . (isset($args['advancedUI']) && $args['advancedUI'] ? '<div id="timeSlider"></div>' : '') . '<div id="toolbar">' . '<span id="dotControlLabel">' . lang::get('Dot Size') . ' :</span>' . (isset($args['advancedUI']) && $args['advancedUI'] ? '<div id="dotSlider"></div>' : '<select id="dotSelect"><option>2</option><option>3</option><option>4</option><option>5</option></select>') . '<button id="beginning">go to beginning</button><button id="playMap">play</button><button id="end">go to end</button>' . '<span id="dateControlLabel">' . lang::get("Date Currently displayed") . ' : ' . (isset($args['advancedUI']) && $args['advancedUI'] ? '<span id="displayDate" ></span>' : '<select id="timeSelect"><option value="">' . lang::get("Please select date") . '</option></select>') . '</span>' . '</div>';
     $imgPath = empty(data_entry_helper::$images_path) ? data_entry_helper::relative_client_helper_path() . "../media/images/" : data_entry_helper::$images_path;
     data_entry_helper::$javascript .= "\ninitTreeMap2({\n  advanced_UI: " . (isset($args['advancedUI']) && $args['advancedUI'] ? "true" : "false") . ",\n  dotSize: " . $args['dotSize'] . ",\n  lat: " . $args['map_centroid_lat'] . ",\n  long: " . $args['map_centroid_long'] . ",\n  zoom: " . $args['map_zoom'] . ",\n  triggerEvents: [" . implode(',', $triggerEvents) . "],\n  base_url: '" . data_entry_helper::$base_url . "',\n  report_name: '" . $args['report_name'] . "',\n  auth_token: '" . $readAuth['auth_token'] . "',\n  nonce: '" . $readAuth['nonce'] . "',\n  reportExtraParams: '" . $extras . "',\n  indicia_user_id: " . (hostsite_get_user_field('indicia_user_id') ? hostsite_get_user_field('indicia_user_id') : 'false') . ",\n  timeControlSelector: '" . (isset($args['advancedUI']) && $args['advancedUI'] ? '#timeSlider' : '#timeSelect') . "',\n  dotControlSelector: '" . (isset($args['advancedUI']) && $args['advancedUI'] ? '#dotSlider' : '#dotSelect') . "',\n  timerDelay: " . (int) 1000 / $args['frameRate'] . ",\n  twinMaps: " . (isset($args['twinMaps']) && $args['twinMaps'] ? 'true' : 'false') . ",\n  imgPath: '" . $imgPath . "'\n});\n";
     $r .= '</div>';
     return $r;
 }
 private static function _getCacheFileName()
 {
     $cacheFolder = data_entry_helper::relative_client_helper_path() . (isset(data_entry_helper::$cache_folder) ? data_entry_helper::$cache_folder : 'cache/');
     if (!is_dir($cacheFolder) || !is_writeable($cacheFolder)) {
         return false;
     }
     return $cacheFolder . 'cache_CMS_User_List';
 }
Пример #11
0
 /**
  * <p>Outputs a calendar based summary grid that loads the results of the summary builder module.</p>
  * <p>If you need 2 grids on one page, then you must define a different id in the options for each grid.</p>
  * <p>The grid operation has NOT been AJAXified. There is no download option.</p>
  *
  * @param array $options Options array with the following possibilities:<ul>
  * <li><b>id</b><br/>
  * Optional unique identifier for the grid's container div. This is required if there is more than
  * one grid on a single web page to allow separation of the page and sort $_GET parameters in the URLs
  * generated.</li>
  * <li><b>mode</b><br/>
  * Pass report for a report, or direct for an Indicia table or view. Default is report.</li>
  * <li><b>readAuth</b><br/>
  * Read authorisation tokens.</li>
  * <li><b>dataSource</b><br/>
  * Name of the report file or table/view. when used, any user_id must refer to the CMS user ID, not the Indicia
  * User.</li>
  * <li><b>view</b>
  * When loading from a view, specify list, gv or detail to determine which view variant is loaded. Default is list.
  * </li>
  * <li><b>extraParams</b><br/>
  * Array of additional key value pairs to attach to the request. This should include fixed values which cannot be changed by the
  * user and therefore are not needed in the parameters form.
  * </li>
  * <li><b>paramDefaults</b>
  * Optional associative array of parameter default values. Default values appear in the parameter form and can be overridden.</li>
  * <li><b>tableHeaders</b>
  * Defines which week column headers should be included: date, number or both
  * <li><b>weekstart</b>
  * Defines the first day of the week. There are 2 options.<br/>'.
  *  weekday=<n> where <n> is a number between 1 (for Monday) and 7 (for Sunday). Default is 'weekday=7'
  *  date=MMM-DD where MMM-DD is a month/day combination: e.g. choosing Apr-1 will start each week on the day of the week on which the 1st of April occurs.</li>
  * <li><b>weekOneContains</b>
  * Defines week one as the week which contains this date. Format should be MMM-DD, which is a month/day combination: e.g. choosing Apr-1 will define
  * week one as being the week containing the 1st of April. Defaults to the 1st of January.</li>
  * <li><b>weekNumberFilter</b>
  * Restrict displayed weeks to between 2 weeks defined by their week numbers. Colon separated.
  * Leaving an empty value means the end of the year.
  * Examples: "1:30" - Weeks one to thirty inclusive.
  * "4:" - Week four onwards.
  * ":5" - Upto and including week five.</li>
  * <li><b>rowGroupColumn</b>
  * The column in the report which is used as the label for the vertical axis on the grid.</li>
  * <li><b>rowGroupID</b>
  * The column in the report which is used as the id for the vertical axis on the grid.</li>
  * <li><b>countColumn</b>
  * OPTIONAL: The column in the report which contains the count for this occurrence. If omitted then the default
  * is to assume one occurrence = count of 1</li>
  * <li><b>includeChartItemSeries</b>
  * Defaults to true. Include a series for each item in the report output.
  * </li>
  * <li><b>includeChartTotalSeries</b>
  * Defaults to true. Include a series for the total of each item in the report output.
  * </li>
  * </ul>
  * @todo: Future Enhancements? Allow restriction to month.
  */
 public static function report_calendar_summary2($options)
 {
     $r = "";
     // I know that there are better ways to approach some of the date manipulation, but they are PHP 5.3+.
     // We support back to PHP 5.2
     // TODO put following JS into a control JS file.
     $warnings = '<span style="display:none;">Starting report_calendar_summary2 : ' . date(DATE_ATOM) . '</span>' . "\n";
     data_entry_helper::add_resource('jquery_ui');
     $options = self::get_report_calendar_summary_options($options);
     // don't use all of these now, eg. extraParams: this is used later for raw data
     $extras = '';
     $extraParams = $options['readAuth'] + array('year' => $options['year'], 'survey_id' => $options['survey_id']);
     // at the moment the summary_builder module indexes the user_id on the created_by_id field on the parent sample.
     // this effectively means that it assumes easy_login.
     // Also means we have to use the converted Indicia user_id, stored by options function above in the extraParams.
     $extraParams['user_id'] = !isset($options['extraParams']['user_id']) || $options['extraParams']['user_id'] == "" ? 'NULL' : $options['extraParams']['user_id'];
     if (isset($options['taxon_list_id']) && $options['taxon_list_id'] != "") {
         $extraParams['taxon_list_id'] = $options['taxon_list_id'];
     }
     if (isset($options['location_id']) && $options['location_id'] != "") {
         $extraParams['location_id'] = $options['location_id'];
     } else {
         if (isset($options['branch_location_list'])) {
             $extraParams['query'] = urlencode(json_encode(array('in' => array('location_id', $options['branch_location_list']))));
         } else {
             $extraParams['location_id'] = 'NULL';
         }
     }
     $records = data_entry_helper::get_population_data(array('table' => 'summary_occurrence', 'extraParams' => $extraParams));
     if (isset($records['error'])) {
         return $records['error'];
     }
     data_entry_helper::$javascript .= "\r\nvar pageURI = \"" . $_SERVER['REQUEST_URI'] . "\";\r\nfunction rebuild_page_url(oldURL, overrideparam, overridevalue) {\r\n  var parts = oldURL.split('?');\r\n  var params = [];\r\n  if(overridevalue!=='') params.push(overrideparam+'='+overridevalue);\r\n  if(parts.length > 1) {\r\n    var oldparams = parts[1].split('&');\r\n    for(var i = 0; i < oldparams.length; i++){\r\n      var bits = oldparams[i].split('=');\r\n      if(bits[0] != overrideparam) params.push(oldparams[i]);\r\n    }\r\n  }\r\n  return parts[0]+(params.length > 0 ? '?'+params.join('&') : '');\r\n};\r\nfunction update_controls(){\r\n  \$('#year-control-previous').attr('href',rebuild_page_url(pageURI,'year'," . $options['year'] . "-1));\r\n  \$('#year-control-next').attr('href',rebuild_page_url(pageURI,'year'," . $options['year'] . "+1));\r\n  // user and location ids are dealt with in the main form. their change functions look a pageURI\r\n}\r\nupdate_controls();\r\n";
     // ISO Date - Mon=1, Sun=7
     // Week 1 = the week with date_from in
     if (!isset($options['weekstart']) || $options['weekstart'] == "") {
         $options['weekstart'] = "weekday=7";
         // Default Sunday
     }
     if (!isset($options['weekNumberFilter']) || $options['weekNumberFilter'] == "") {
         $options['weekNumberFilter'] = ":";
     }
     $weeknumberfilter = explode(':', $options['weekNumberFilter']);
     if (count($weeknumberfilter) != 2) {
         $warnings .= "Week number filter unrecognised {" . $options['weekNumberFilter'] . "} defaulting to all<br />";
         $weeknumberfilter = array('', '');
     } else {
         if ($weeknumberfilter[0] != '' && (intval($weeknumberfilter[0]) != $weeknumberfilter[0] || $weeknumberfilter[0] > 52)) {
             $warnings .= "Week number filter start unrecognised or out of range {" . $weeknumberfilter[0] . "} defaulting to year start<br />";
             $weeknumberfilter[0] = '';
         }
         if ($weeknumberfilter[1] != '' && (intval($weeknumberfilter[1]) != $weeknumberfilter[1] || $weeknumberfilter[1] < $weeknumberfilter[0] || $weeknumberfilter[1] > 52)) {
             $warnings .= "Week number filter end unrecognised or out of range {" . $weeknumberfilter[1] . "} defaulting to year end<br />";
             $weeknumberfilter[1] = '';
         }
     }
     $weekstart = explode('=', $options['weekstart']);
     if ($weekstart[0] == 'date') {
         $weekstart_date = date_create($options['year'] . "-" . $weekstart[1]);
         if (!$weekstart_date) {
             $warnings .= "Weekstart month-day combination unrecognised {" . $weekstart[1] . "} defaulting to weekday=7 - Sunday<br />";
             $weekstart[1] = 7;
         } else {
             $weekstart[1] = $weekstart_date->format('N');
         }
     }
     if (intval($weekstart[1]) != $weekstart[1] || $weekstart[1] < 1 || $weekstart[1] > 7) {
         $warnings .= "Weekstart unrecognised or out of range {" . $weekstart[1] . "} defaulting to 7 - Sunday<br />";
         $weekstart[1] = 7;
     }
     if (isset($options['weekOneContains']) && $options['weekOneContains'] != "") {
         $weekOne_date = date_create($options['year'] . '-' . $options['weekOneContains']);
         if (!$weekOne_date) {
             $warnings .= "Week one month-day combination unrecognised {" . $options['weekOneContains'] . "} defaulting to Jan-01<br />";
             $weekOne_date = date_create($options['year'] . '-Jan-01');
         }
     } else {
         $weekOne_date = date_create($options['year'] . '-Jan-01');
     }
     $weekOne_date_weekday = $weekOne_date->format('N');
     if ($weekOne_date_weekday > $weekstart[1]) {
         // scan back to start of week
         $weekOne_date->modify('-' . ($weekOne_date_weekday - $weekstart[1]) . ' day');
     } else {
         if ($weekOne_date_weekday < $weekstart[1]) {
             $weekOne_date->modify('-' . (7 + $weekOne_date_weekday - $weekstart[1]) . ' day');
         }
     }
     $firstWeek_date = clone $weekOne_date;
     // date we start providing data for
     $weekOne_date_yearday = $weekOne_date->format('z');
     // day within year note year_start_yearDay is by definition 0
     $weekOne_date_weekday = $weekOne_date->format('N');
     // day within week
     $minWeekNo = $weeknumberfilter[0] != '' ? $weeknumberfilter[0] : 1;
     $numWeeks = ceil($weekOne_date_yearday / 7);
     // number of weeks in year prior to $weekOne_date - 1st Jan gives zero, 2nd-8th Jan gives 1, etc
     if ($minWeekNo - 1 < -1 * $numWeeks) {
         $minWeekNo = -1 * $numWeeks + 1;
     }
     // have to allow for week zero
     if ($minWeekNo < 1) {
         $firstWeek_date->modify(($minWeekNo - 1) * 7 . ' days');
     } else {
         if ($minWeekNo > 1) {
             $firstWeek_date->modify('+' . ($minWeekNo - 1) * 7 . ' days');
         }
     }
     if ($weeknumberfilter[1] != '') {
         $maxWeekNo = $weeknumberfilter[1];
     } else {
         $year_end = date_create($options['year'] . '-Dec-25');
         // don't want to go beyond the end of year: this is 1st Jan minus 1 week: it is the start of the last full week
         $year_end_yearDay = $year_end->format('z');
         // day within year
         $maxWeekNo = 1 + ceil(($year_end_yearDay - $weekOne_date_yearday) / 7);
     }
     $warnings .= '<span style="display:none;">Initial date processing complete : ' . date(DATE_ATOM) . '</span>' . "\n";
     $tableNumberHeaderRow = "";
     $tableDateHeaderRow = "";
     $downloadNumberHeaderRow = "";
     $downloadDateHeaderRow = "";
     $chartNumberLabels = array();
     $chartDateLabels = array();
     $fullDates = array();
     for ($i = $minWeekNo; $i <= $maxWeekNo; $i++) {
         $tableNumberHeaderRow .= '<th class="week">' . $i . '</th>';
         $tableDateHeaderRow .= '<th class="week">' . $firstWeek_date->format('M') . '<br/>' . $firstWeek_date->format('d') . '</th>';
         $downloadNumberHeaderRow .= ',' . $i;
         $downloadDateHeaderRow .= ',' . $firstWeek_date->format('d/m/Y');
         $chartNumberLabels[] = "" . $i;
         $chartDateLabels[] = $firstWeek_date->format('M-d');
         $fullDates[$i] = $firstWeek_date->format('d/m/Y');
         $firstWeek_date->modify('+7 days');
     }
     $summaryArray = array();
     // this is used for the table output format
     $rawArray = array();
     // this is used for the table output format
     // In order to apply the data combination and estmation processing, we assume that the the records are in taxon, location_id, sample_id order.
     $locationArray = array();
     // this is for a single species at a time.
     $lastLocation = false;
     $seriesLabels = array();
     $lastTaxonID = false;
     $lastSample = false;
     $locationSamples = array();
     $weekList = array();
     $sampleFieldList = !empty($options['sampleFields']) ? explode(',', $options['sampleFields']) : false;
     if (!$sampleFieldList || count($sampleFieldList) == 0) {
         $sampleFields = false;
     } else {
         $sampleFields = array();
         foreach ($sampleFieldList as $sampleField) {
             $parts = explode(':', $sampleField);
             $field = array('caption' => $parts[0], 'field' => $parts[1], 'attr' => false);
             if (count($parts) == 3 && ($parts[1] = 'smpattr')) {
                 $smpAttribute = data_entry_helper::get_population_data(array('table' => 'sample_attribute', 'extraParams' => $options['readAuth'] + array('view' => 'list', 'id' => $parts[2])));
                 if (count($smpAttribute) >= 1) {
                     // may be assigned to more than one survey on this website. This is not relevant to info we want.
                     $field['id'] = $parts[2];
                     $field['attr'] = $smpAttribute[0];
                 }
             }
             $sampleFields[] = $field;
         }
     }
     if ($options['location_list'] != 'all' && count($options['location_list']) == 0) {
         $options['location_list'] = 'none';
     }
     foreach ($records as $recid => $record) {
         // If the taxon has changed
         $this_date = date_create(str_replace('/', '-', $record['date']));
         // prevents day/month ordering issues
         $this_index = $this_date->format('z');
         $this_weekday = $this_date->format('N');
         if ($this_weekday > $weekstart[1]) {
             // scan back to start of week
             $this_date->modify('-' . ($this_weekday - $weekstart[1]) . ' day');
         } else {
             if ($this_weekday < $weekstart[1]) {
                 $this_date->modify('-' . (7 + $this_weekday - $weekstart[1]) . ' day');
             }
         }
         // this_date now points to the start of the week. Next work out the week number.
         $this_yearday = $this_date->format('z');
         $weekno = $record['period_number'];
         if (isset($weekList[$weekno])) {
             if (!in_array($record['location_name'], $weekList[$weekno])) {
                 $weekList[$weekno][] = $record['location_name'];
             }
         } else {
             $weekList[$weekno] = array($record['location_name']);
         }
     }
     $warnings .= '<span style="display:none;">Records date pre-processing complete : ' . date(DATE_ATOM) . '</span>' . "\n";
     $count = count($records);
     $warnings .= '<span style="display:none;">Number of records processed : ' . $count . ' : ' . date(DATE_ATOM) . '</span>' . "\n";
     $summaryArray = array();
     $sortData = array();
     foreach ($records as $idex => $record) {
         $taxonID = $record['taxon_meaning_id'];
         // TODO ??
         if (!empty($record['default_common_name'])) {
             $seriesLabels[$taxonID] = array('label' => $record['default_common_name']);
         }
         // TODO user to be able to choose from taxon or common
         if (empty($seriesLabels[$taxonID])) {
             $seriesLabels[$taxonID] = array('label' => $record['taxon']);
         }
         // various fall backs.
         if (empty($seriesLabels[$taxonID])) {
             $seriesLabels[$taxonID] = array('label' => '[' . $record['taxa_taxon_list_id'] . ']');
         }
         if (!empty($record['preferred_taxon'])) {
             $seriesLabels[$taxonID]['preferred'] = $record['preferred_taxon'];
         }
         $weekno = $record['period_number'];
         $count = $record['count'];
         if (!isset($summaryArray[$taxonID])) {
             $summaryArray[$taxonID] = array();
         }
         $sortData[$taxonID] = array($record['taxonomic_sort_order'], $taxonID);
         if ($weekno >= $minWeekNo && $weekno <= $maxWeekNo) {
             if (!isset($summaryArray[$taxonID][$weekno])) {
                 $summaryArray[$taxonID][$weekno] = array('total' => null, 'estimate' => 0);
             }
             if ($count !== null) {
                 $summaryArray[$taxonID][$weekno]['total'] = ($summaryArray[$taxonID][$weekno]['total'] == null ? 0 : $summaryArray[$taxonID][$weekno]['total']) + $count;
             }
             $summaryArray[$taxonID][$weekno]['estimate'] += $record['estimate'];
         }
     }
     usort($sortData, array('report_helper', 'report_calendar_summary_sort1'));
     $warnings .= '<span style="display:none;">Estimate processing finished : ' . date(DATE_ATOM) . '</span>' . "\n";
     // will storedata in an array[Y][X]
     data_entry_helper::add_resource('jqplot');
     switch ($options['chartType']) {
         case 'bar':
             self::add_resource('jqplot_bar');
             $renderer = '$.jqplot.BarRenderer';
             break;
         case 'pie':
             self::add_resource('jqplot_pie');
             $renderer = '$.jqplot.PieRenderer';
             break;
         default:
             // default is line
             $renderer = '$.jqplot.LineRenderer';
             break;
     }
     self::add_resource('jqplot_category_axis_renderer');
     $opts = array();
     $opts[] = "seriesDefaults:{\n" . (isset($renderer) ? "  renderer:{$renderer},\n" : '') . "  rendererOptions:" . json_encode($options['rendererOptions']) . "}";
     $warnings .= '<span style="display:none;">Controls complete : ' . date(DATE_ATOM) . '</span>' . "\n";
     $seriesToDisplay = isset($options['outputSeries']) ? explode(',', $options['outputSeries']) : 'all';
     $thClass = $options['thClass'];
     $summaryTab = '<div class="results-grid-wrapper-outer"><div class="results-grid-wrapper-inner"><table id="' . $options['tableID'] . '-summary" class="' . $options['tableClass'] . '"><thead class="' . $thClass . '">';
     $estimateTab = '<div class="results-grid-wrapper-outer"><div class="results-grid-wrapper-inner"><table id="' . $options['tableID'] . '-estimate" class="' . $options['tableClass'] . '"><thead class="' . $thClass . '">';
     $summaryDataDownloadGrid = '';
     $estimateDataDownloadGrid = '';
     $rawDataDownloadGrid = '';
     $summaryTab .= '<tr><th class="freeze-first-col">' . lang::get('Week') . '</th>' . $tableNumberHeaderRow . '<th>Total</th></tr>' . '<tr><th class="freeze-first-col">' . lang::get('Date') . '</th>' . $tableDateHeaderRow . '<th></th></tr></thead><tbody>';
     $estimateTab .= '<tr><th class="freeze-first-col">' . lang::get('Week') . '</th>' . $tableNumberHeaderRow . '<th>Total with<br/>estimates</th></tr>' . '<tr><th class="freeze-first-col">' . lang::get('Date') . '</th>' . $tableDateHeaderRow . '<th></th></tr></thead><tbody>';
     $summaryDataDownloadGrid .= 'Week,' . $downloadNumberHeaderRow . ',Total' . "\n" . lang::get('Date') . ',' . $downloadDateHeaderRow . ",\n";
     $estimateDataDownloadGrid .= 'Week,' . $downloadNumberHeaderRow . ',Estimates Total' . "\n" . lang::get('Date') . ',' . $downloadDateHeaderRow . ",\n";
     $altRow = false;
     $grandTotal = 0;
     $totalRow = array();
     $estimatesGrandTotal = 0;
     $totalEstimatesRow = array();
     $seriesIDs = array();
     $summarySeriesData = array();
     $estimatesSeriesData = array();
     $seriesOptions = array();
     for ($i = $minWeekNo; $i <= $maxWeekNo; $i++) {
         $totalRow[$i] = 0;
         $totalEstimatesRow[$i] = 0;
     }
     foreach ($sortData as $sortedTaxon) {
         $seriesID = $sortedTaxon[1];
         $summaryRow = $summaryArray[$seriesID];
         $summaryValues = array();
         $estimatesValues = array();
         if (!empty($seriesLabels[$seriesID])) {
             $total = 0;
             // row total
             $estimatesTotal = 0;
             // row total
             $summaryTab .= '<tr class="datarow ' . ($altRow ? $options['altRowClass'] : '') . '"><td class="freeze-first-col"' . (isset($seriesLabels[$seriesID]['preferred']) ? ' title="' . $seriesLabels[$seriesID]['preferred'] . '"' : '') . '>' . $seriesLabels[$seriesID]['label'] . '</td>';
             $estimateTab .= '<tr class="datarow ' . ($altRow ? $options['altRowClass'] : '') . '"><td class="freeze-first-col"' . (isset($seriesLabels[$seriesID]['preferred']) ? ' title="' . $seriesLabels[$seriesID]['preferred'] . '"' : '') . '>' . $seriesLabels[$seriesID]['label'] . '</td>';
             $summaryDataDownloadGrid .= '"' . $seriesLabels[$seriesID]['label'] . '","' . (isset($seriesLabels[$seriesID]['preferred']) ? $seriesLabels[$seriesID]['preferred'] : '') . '"';
             $estimateDataDownloadGrid .= '"' . $seriesLabels[$seriesID]['label'] . '","' . (isset($seriesLabels[$seriesID]['preferred']) ? $seriesLabels[$seriesID]['preferred'] : '') . '"';
             for ($i = $minWeekNo; $i <= $maxWeekNo; $i++) {
                 $summaryDataDownloadGrid .= ',';
                 $estimateDataDownloadGrid .= ',';
                 if (isset($summaryRow[$i])) {
                     $summaryValue = $summaryRow[$i]['total'];
                     $estimateValue = $summaryRow[$i]['estimate'];
                     $class = $summaryValue !== null && $summaryValue === 0 ? 'forcedZero' : '';
                     $estimatesClass = $summaryValue === null || $summaryValue != $estimateValue ? 'highlight-estimates' : '';
                     if ($summaryValue !== null && $summaryValue === 0 && $estimateValue === 0) {
                         $estimatesClass = 'forcedZero';
                     }
                     $summaryDataDownloadGrid .= $summaryValue;
                     $estimateDataDownloadGrid .= $estimateValue;
                     $summaryTab .= '<td class="' . $class . '">' . ($summaryValue !== '' ? $summaryValue : '') . '</td>';
                     $estimateTab .= '<td class="' . $estimatesClass . '">' . $estimateValue . '</td>';
                     if ($summaryValue !== null && $summaryValue !== 0) {
                         $total += $summaryValue;
                         $totalRow[$i] += $summaryValue;
                         // = $summaryTotalRow
                         $grandTotal += $summaryValue;
                         $summaryValues[] = $summaryValue;
                     } else {
                         $summaryValues[] = 0;
                     }
                     $estimatesValues[] = $estimateValue;
                     $estimatesTotal += $estimateValue;
                     $totalEstimatesRow[$i] += $estimateValue;
                     // = $estimatesTotalRow
                     $estimatesGrandTotal += $estimateValue;
                 } else {
                     $summaryTab .= '<td></td>';
                     $estimateTab .= '<td></td>';
                     $summaryValues[] = 0;
                     $estimatesValues[] = 0;
                 }
             }
             if ($options['includeChartItemSeries']) {
                 $seriesIDs[] = $seriesID;
                 $summarySeriesData[] = '[' . implode(',', $summaryValues) . ']';
                 $estimatesSeriesData[] = '[' . implode(',', $estimatesValues) . ']';
                 $seriesOptions[] = '{"show":' . ($seriesToDisplay == 'all' || in_array($seriesID, $seriesToDisplay) ? 'true' : 'false') . ',"label":"' . $seriesLabels[$seriesID]['label'] . '","showlabel":true}';
             }
             $summaryTab .= '<td class="total-column">' . $total . '</td></tr>';
             $summaryDataDownloadGrid .= ',' . $total . "\n";
             $estimateTab .= '<td class="total-column estimates">' . $estimatesTotal . '</td></tr>';
             $estimateDataDownloadGrid .= ',' . $estimatesTotal . "\n";
             $altRow = !$altRow;
         }
     }
     if (isset($options['includeChartTotalSeries']) && $options['includeChartTotalSeries']) {
         // totals are put at the start
         array_unshift($seriesIDs, 0);
         // Total has ID 0
         array_unshift($summarySeriesData, '[' . implode(',', $totalRow) . ']');
         array_unshift($estimatesSeriesData, '[' . implode(',', $totalEstimatesRow) . ']');
         array_unshift($seriesOptions, '{"show":' . ($seriesToDisplay == 'all' || in_array(0, $seriesToDisplay) ? 'true' : 'false') . ',"label":"' . lang::get('Total') . '","showlabel":true}');
     }
     $opts[] = 'series:[' . implode(',', $seriesOptions) . ']';
     $options['axesOptions']['xaxis']['renderer'] = '$.jqplot.CategoryAxisRenderer';
     if (isset($options['chartLabels']) && $options['chartLabels'] == 'number') {
         $options['axesOptions']['xaxis']['ticks'] = $chartNumberLabels;
     } else {
         $options['axesOptions']['xaxis']['ticks'] = $chartDateLabels;
     }
     // We need to fudge the json so the renderer class is not a string
     $axesOpts = str_replace('"$.jqplot.CategoryAxisRenderer"', '$.jqplot.CategoryAxisRenderer', 'axes:' . json_encode($options['axesOptions']));
     $opts[] = $axesOpts;
     $summaryTab .= "<tr class=\"totalrow\"><td class=\"freeze-first-col\">" . lang::get('Total (Summary)') . '</td>';
     $estimateTab .= "<tr class=\"totalrow estimates\"><td class=\"freeze-first-col\">" . lang::get('Total inc Estimates') . '</td>';
     $summaryDataDownloadGrid .= '"' . lang::get('Total (Summary)') . '",';
     $estimateDataDownloadGrid .= '"' . lang::get('Total') . '",';
     for ($i = $minWeekNo; $i <= $maxWeekNo; $i++) {
         $summaryTab .= '<td>' . $totalRow[$i] . '</td>';
         $estimateTab .= '<td>' . $totalEstimatesRow[$i] . '</td>';
         $estimateDataDownloadGrid .= ',' . $totalEstimatesRow[$i];
         $summaryDataDownloadGrid .= ',' . $totalRow[$i];
     }
     $summaryTab .= '<td class="total-column grand-total">' . $grandTotal . '</td></tr>';
     $summaryDataDownloadGrid .= ',' . $grandTotal . "\n";
     $estimateTab .= '<td class="total-column grand-total estimates">' . $estimatesGrandTotal . '</td></tr>';
     $estimateDataDownloadGrid .= ',' . $estimatesGrandTotal . "\n";
     $summaryTab .= "</tbody></table></div></div>\n";
     $estimateTab .= "</tbody></table></div></div>\n";
     data_entry_helper::$javascript .= "var seriesData = {ids: [" . implode(',', $seriesIDs) . "], summary: [" . implode(',', $summarySeriesData) . "], estimates: [" . implode(',', $estimatesSeriesData) . "]};\n";
     data_entry_helper::$javascript .= "\r\nfunction replot(type){\r\n  // there are problems with the coloring of series when added to a plot: easiest just to completely redraw.\r\n  var max=0;\r\n  \$('#" . $options['chartID'] . "-'+type).empty();\n" . (!isset($options['width']) || $options['width'] == '' ? "  jQuery('#" . $options['chartID'] . "-'+type).width(jQuery('#" . $options['chartID'] . "-'+type).width());\n" : '') . "  var opts = {" . implode(",\n", $opts) . "};\r\n  // copy series from checkboxes.\r\n  \$('#" . $options['chartID'] . "-'+type).parent().find('[name=" . $options['chartID'] . "-series]').each(function(idx, elem){\r\n      opts.series[idx].show = (jQuery(elem).filter('[checked]').length > 0);\r\n  });\r\n  for(var i=0; i<seriesData[type].length; i++)\r\n    if(opts.series[i].show)\r\n      for(var j=0; j<seriesData[type][i].length; j++)\r\n          max=(max>seriesData[type][i][j]?max:seriesData[type][i][j]);\r\n  opts.axes.yaxis.max=max+1;\r\n  opts.axes.yaxis.tickInterval = Math.floor(max/15); // number of ticks - too many takes too long to display\r\n  if(!opts.axes.yaxis.tickInterval) opts.axes.yaxis.tickInterval=1;\r\n  \$('.legend-colours').remove();\r\n  if(\$('#" . $options['chartID'] . "-'+type).parent().find('[name=" . $options['chartID'] . "-series]').filter('[checked]').length == 0) return;\r\n  var plot = \$.jqplot('" . $options['chartID'] . "-'+type, seriesData[type], opts);\r\n  for(var i=0; i<plot.series.length; i++){\r\n  \tif(plot.series[i].show==true) {\r\n\t    var elem = \$('#" . $options['chartID'] . "-'+type).parent().find('[name=" . $options['chartID'] . "-series]').eq(i);\r\n    \telem.after('<div class=\"legend-colours\"><div class=\"legend-colours-inner\" style=\"background:'+plot.series[i].color+';\">&nbsp;</div></div>');\r\n\t}\r\n  }\r\n};\r\nindiciaFns.bindTabsActivate(\$('#controls'), function(event, ui) {\r\n  panel = typeof ui.newPanel==='undefined' ? ui.panel : ui.newPanel[0];\r\n  if (panel.id==='summaryChart') { replot('summary'); }\r\n  if (panel.id==='estimateChart') { replot('estimates'); }\r\n  if (panel.id==='summaryData' || panel.id==='estimateData' || panel.id==='rawData') {\r\n  \tvar max=0;\r\n  \tvar extMax=0;\r\n  \t\$('#'+panel.id+' .freeze-first-col').each(function(idx, elem){\r\n  \t  \$(elem).css('width',''); \r\n  \t  if(max < \$(elem).width()) max= \$(elem).width();\r\n  \t  if(extMax < \$(elem).outerWidth(true)) extMax= \$(elem).outerWidth(true);});\r\n  \t\$('#'+panel.id+' .freeze-first-col').width(max+1);\r\n  \t\$('#'+panel.id+' .results-grid-wrapper-inner').css('margin-left',extMax+1);\r\n  \t\$('#'+panel.id+' table').hide();\r\n  \t\$('#'+panel.id+' > div.results-grid-wrapper-outer').each(function(idx, elem){ \$(elem).css('width',''); \$(elem).width(\$(elem).width());});\r\n  \t\$('#'+panel.id+' table').show();\r\n  }\r\n});\r\n";
     $summarySeriesPanel = "";
     if (isset($options['disableableSeries']) && $options['disableableSeries'] && count($summaryArray) > (isset($options['includeChartTotalSeries']) && $options['includeChartTotalSeries'] ? 0 : 1) && isset($options['includeChartItemSeries']) && $options['includeChartItemSeries']) {
         $class = 'series-fieldset';
         if (function_exists('hostsite_add_library') && (!defined('DRUPAL_CORE_COMPATIBILITY') || DRUPAL_CORE_COMPATIBILITY !== '7.x')) {
             hostsite_add_library('collapse');
             $class .= ' collapsible collapsed';
         }
         $summarySeriesPanel .= '<fieldset id="' . $options['chartID'] . '-series" class="' . $class . '"><legend>' . lang::get('Display Series') . "</legend><span>\n";
         $summarySeriesPanel .= '<input type="button" class="disable-button" value="' . lang::get('Hide all ') . $options['rowGroupColumn'] . "\"/>\n";
         $idx = 0;
         if (isset($options['includeChartTotalSeries']) && $options['includeChartTotalSeries']) {
             // use series ID = 0 for Total
             $summarySeriesPanel .= '<span class="chart-series-span"><input type="checkbox" checked="checked" id="' . $options['chartID'] . '-series-' . $idx . '" name="' . $options['chartID'] . '-series" value="' . $idx . '"/><label for="' . $options['chartID'] . '-series-' . $idx . '">' . lang::get('Total') . "</label></span>\n";
             $idx++;
             data_entry_helper::$javascript .= "\njQuery('[name=" . $options['chartID'] . "-series]').filter('[value=0]')." . ($seriesToDisplay == 'all' || in_array(0, $seriesToDisplay) ? 'attr("checked","checked");' : 'removeAttr("checked");');
         }
         foreach ($sortData as $sortedTaxon) {
             $seriesID = $sortedTaxon[1];
             $summaryRow = $summaryArray[$seriesID];
             $summarySeriesPanel .= '<span class="chart-series-span"><input type="checkbox" checked="checked" id="' . $options['chartID'] . '-series-' . $idx . '" name="' . $options['chartID'] . '-series" value="' . $seriesID . '"/><label for="' . $options['chartID'] . '-series-' . $idx . '"' . (isset($seriesLabels[$seriesID]['preferred']) ? ' title="' . $seriesLabels[$seriesID]['preferred'] . '"' : '') . '>' . $seriesLabels[$seriesID]['label'] . "</label></span>\n";
             $idx++;
             data_entry_helper::$javascript .= "\njQuery('[name=" . $options['chartID'] . "-series]').filter('[value=" . $seriesID . "]')." . ($seriesToDisplay == 'all' || in_array($seriesID, $seriesToDisplay) ? 'attr("checked","checked");' : 'removeAttr("checked");');
         }
         $summarySeriesPanel .= "</span></fieldset>\n";
         // Known issue: jqplot considers the min and max of all series when drawing on the screen, even those which are not displayed
         // so replotting doesn't scale to the displayed series!
         // Note we are keeping the 2 charts in sync.
         data_entry_helper::$javascript .= "\r\njQuery('#summaryChart [name=" . $options['chartID'] . "-series]').change(function(){\r\n  \$('#estimateChart [name=" . $options['chartID'] . "-series]').filter('[value='+\$(this).val()+']').attr('checked',\$(this).attr('checked'));\r\n  replot('summary');\r\n});\r\njQuery('#estimateChart [name=" . $options['chartID'] . "-series]').change(function(){\r\n  \$('#summaryChart [name=" . $options['chartID'] . "-series]').filter('[value='+\$(this).val()+']').attr('checked',\$(this).attr('checked'));\r\n  replot('estimates');\r\n});\r\njQuery('#summaryChart .disable-button').click(function(){\r\n  if(jQuery(this).is('.cleared')){ // button is to show all\r\n    jQuery('[name=" . $options['chartID'] . "-series]').not('[value=0]').attr('checked','checked');\r\n    jQuery('.disable-button').removeClass('cleared').val(\"" . lang::get('Hide all ') . $options['rowGroupColumn'] . "\");\r\n  } else {\r\n    jQuery('[name=" . $options['chartID'] . "-series]').not('[value=0]').removeAttr('checked');\r\n    jQuery('.disable-button').addClass('cleared').val(\"" . lang::get('Show all ') . $options['rowGroupColumn'] . "\");\r\n  }\r\n  replot('summary');\r\n});\r\njQuery('#estimateChart .disable-button').click(function(){\r\n  if(jQuery(this).is('.cleared')){ // button is to show all\r\n    jQuery('[name=" . $options['chartID'] . "-series]').not('[value=0]').attr('checked','checked');\r\n    jQuery('.disable-button').removeClass('cleared').val(\"" . lang::get('Hide all ') . $options['rowGroupColumn'] . "\");\r\n  } else {\r\n    jQuery('[name=" . $options['chartID'] . "-series]').not('[value=0]').removeAttr('checked');\r\n    jQuery('.disable-button').addClass('cleared').val(\"" . lang::get('Show all ') . $options['rowGroupColumn'] . "\");\r\n  }\r\n  replot('estimates');\r\n});\r\n";
     }
     $hasRawData = false;
     if (isset($options['location_id']) && $options['location_id'] != "") {
         // get the raw data for a single location.
         $options['extraParams']['orderby'] = 'date';
         self::request_report($response, $options, $currentParamValues, false, '');
         if (isset($response['error'])) {
             $rawTab = "ERROR RETURNED FROM request_report:<br />" . print_r($response, true);
         } else {
             if (isset($response['parameterRequest'])) {
                 // We're not even going to bother with asking the user to populate a partially filled in report parameter set.
                 $rawTab = '<p>Internal Error: Report request parameters not set up correctly.<br />' . print_r($response, true) . '<p>';
             } else {
                 // convert records to a date based array so it can be used when generating the grid.
                 $altRow = false;
                 $records = $response['records'];
                 $rawTab = isset($options['linkMessage']) ? $options['linkMessage'] : '';
                 $rawDataDownloadGrid = lang::get('Date') . ',';
                 $rawArray = array();
                 $sampleList = array();
                 $sampleDateList = array();
                 $smpIdx = 0;
                 $hasRawData = count($records) > 0;
                 if (!$hasRawData) {
                     $rawTab .= '<p>' . lang::get('No raw data available for this period with these filter values.') . '</p>';
                 } else {
                     $rawTab = '<div class="results-grid-wrapper-outer"><div class="results-grid-wrapper-inner"><table class="' . $options['tableClass'] . '"><thead class="' . $thClass . '"><tr><th class="freeze-first-col">' . lang::get('Date') . '</th>';
                     foreach ($records as $occurrence) {
                         if (!in_array($occurrence['sample_id'], $sampleList)) {
                             $sampleList[] = $occurrence['sample_id'];
                             $sampleData = array('id' => $occurrence['sample_id'], 'date' => $occurrence['date'], 'location' => $occurrence['locaton_name']);
                             $rawArray[$occurrence['sample_id']] = array();
                             if ($sampleFields) {
                                 foreach ($sampleFields as $sampleField) {
                                     if ($sampleField['attr'] === false) {
                                         $sampleData[$sampleField['caption']] = $occurrence[$sampleField['field']];
                                     } else {
                                         if ($sampleField['attr']['data_type'] == 'L') {
                                             $sampleData[$sampleField['caption']] = $occurrence['attr_sample_term_' . $sampleField['id']];
                                         } else {
                                             $sampleData[$sampleField['caption']] = $occurrence['attr_sample_' . $sampleField['id']];
                                         }
                                     }
                                 }
                             }
                             $sampleDateList[] = $sampleData;
                         }
                         if ($occurrence['taxon_meaning_id'] !== null && $occurrence['taxon_meaning_id'] != '') {
                             $count = isset($options['countColumn']) && $options['countColumn'] != '' ? isset($occurrence[$options['countColumn']]) ? $occurrence[$options['countColumn']] : 0 : 1;
                             if (!isset($rawArray[$occurrence['sample_id']][$occurrence['taxon_meaning_id']])) {
                                 $rawArray[$occurrence['sample_id']][$occurrence['taxon_meaning_id']] = $count;
                             } else {
                                 $rawArray[$occurrence['sample_id']][$occurrence['taxon_meaning_id']] += $count;
                             }
                         }
                     }
                     foreach ($sampleDateList as $sample) {
                         $sample_date = date_create($sample['date']);
                         $rawTab .= '<th>' . (isset($options['linkURL']) && $options['linkURL'] != '' ? '<a href="' . $options['linkURL'] . $sample['id'] . '" target="_blank" title="Link to data entry form for ' . $sample['location'] . ' on ' . $sample['date'] . ' (Sample ID ' . $sample['id'] . ')">' : '') . $sample_date->format('M') . '<br/>' . $sample_date->format('d') . (isset($options['linkURL']) && $options['linkURL'] != '' ? '</a>' : '') . '</th>';
                         $rawDataDownloadGrid .= ',' . $sample['date'];
                     }
                     $rawDataDownloadGrid .= "\n";
                     $rawTab .= '</tr></thead><tbody>';
                     if ($sampleFields) {
                         foreach ($sampleFields as $sampleField) {
                             // last-sample-datarow
                             $rawTab .= '<tr class="sample-datarow ' . ($altRow ? $options['altRowClass'] : '') . '"><td class="freeze-first-col">' . $sampleField['caption'] . '</td>';
                             $rawDataDownloadGrid .= '"' . $sampleField['caption'] . '",';
                             foreach ($sampleDateList as $sample) {
                                 $rawTab .= '<td>' . ($sample[$sampleField['caption']] === null || $sample[$sampleField['caption']] == '' ? '&nbsp;' : $sample[$sampleField['caption']]) . '</td>';
                                 $rawDataDownloadGrid .= ',' . $sample[$sampleField['caption']];
                             }
                             $rawTab .= '</tr>';
                             $rawDataDownloadGrid .= "\n";
                             $altRow = !$altRow;
                         }
                         data_entry_helper::$javascript .= "var sampleDatarows = \$('#rawData .sample-datarow').length;\n\$('#rawData .sample-datarow').eq(sampleDatarows-1).addClass('last-sample-datarow');\n";
                     }
                     foreach ($sortData as $sortedTaxon) {
                         $seriesID = $sortedTaxon[1];
                         // this is the meaning id
                         if (!empty($seriesLabels[$seriesID])) {
                             $rawTab .= '<tr class="datarow ' . ($altRow ? $options['altRowClass'] : '') . '"><td class="freeze-first-col"' . (isset($seriesLabels[$seriesID]['preferred']) ? ' title="' . $seriesLabels[$seriesID]['preferred'] . '"' : '') . '>' . $seriesLabels[$seriesID]['label'] . '</td>';
                             $rawDataDownloadGrid .= '"' . $seriesLabels[$seriesID]['label'] . '","' . (isset($seriesLabels[$seriesID]['preferred']) ? $seriesLabels[$seriesID]['preferred'] : '') . '",';
                             foreach ($sampleList as $sampleID) {
                                 $rawTab .= '<td>' . (isset($rawArray[$sampleID][$seriesID]) ? $rawArray[$sampleID][$seriesID] : '&nbsp;') . '</td>';
                                 $rawDataDownloadGrid .= ',' . (isset($rawArray[$sampleID][$seriesID]) ? $rawArray[$sampleID][$seriesID] : '');
                             }
                             $rawTab .= '</tr>';
                             $rawDataDownloadGrid .= "\n";
                             $altRow = !$altRow;
                         }
                     }
                     $rawTab .= '</tbody></table></div></div>';
                 }
             }
         }
     } else {
         $rawTab = "<p>Raw Data is only available when a location is specified.</p>";
     }
     $hasData = count($summaryArray) > 0;
     $tabs = array('#summaryData' => lang::get('Summary Table'));
     if ($hasData) {
         $tabs = array_merge($tabs, array('#summaryChart' => lang::get('Summary Chart'), '#estimateData' => lang::get('Estimate Table'), '#estimateChart' => lang::get('Estimate Chart')));
     }
     $tabs['#rawData'] = lang::get('Raw Data');
     $downloadTab = "";
     $timestamp = isset($options['includeReportTimeStamp']) && $options['includeReportTimeStamp'] ? '_' . date('YmdHis') : '';
     unset($options['extraParams']['orderby']);
     // may have been set for raw data
     // No need for saved reports to be atomic events. Will be purged automatically.
     global $base_url;
     $cacheFolder = data_entry_helper::$cache_folder ? data_entry_helper::$cache_folder : data_entry_helper::relative_client_helper_path() . 'cache/';
     if ($hasData && $options['includeSummaryGridDownload']) {
         $cacheFile = $options['downloadFilePrefix'] . 'summaryDataGrid' . $timestamp . '.csv';
         $handle = fopen($cacheFolder . $cacheFile, 'wb');
         fwrite($handle, $summaryDataDownloadGrid);
         fclose($handle);
         $downloadTab .= '<tr><td>' . lang::get('Download Summary Grid (CSV Format)') . ' : </td><td><a target="_blank" href="' . $base_url . '/' . drupal_get_path('module', 'iform') . '/client_helpers/cache/' . $cacheFile . '" download type="text/csv"><button type="button">' . lang::get('Download') . '</button></a></td></tr>' . "\n";
     }
     if ($hasData && $options['includeEstimatesGridDownload']) {
         $cacheFile = $options['downloadFilePrefix'] . 'estimateDataGrid' . $timestamp . '.csv';
         $handle = fopen($cacheFolder . $cacheFile, 'wb');
         fwrite($handle, $estimateDataDownloadGrid);
         fclose($handle);
         $downloadTab .= '<tr><td>' . lang::get('Download Estimates Grid (CSV Format)') . ' : </td><td><a target="_blank" href="' . $base_url . '/' . drupal_get_path('module', 'iform') . '/client_helpers/cache/' . $cacheFile . '" download type="text/csv"><button type="button">' . lang::get('Download') . '</button></a></td></tr>' . "\n";
     }
     if ($hasRawData && $options['includeRawGridDownload']) {
         $cacheFile = $options['downloadFilePrefix'] . 'rawDataGrid' . $timestamp . '.csv';
         $handle = fopen($cacheFolder . $cacheFile, 'wb');
         fwrite($handle, $rawDataDownloadGrid);
         fclose($handle);
         $downloadTab .= '<tr><td>' . lang::get('Download Raw Data Grid (CSV Format)') . ' : </td><td><a target="_blank" href="' . $base_url . '/' . drupal_get_path('module', 'iform') . '/client_helpers/cache/' . $cacheFile . '" download type="text/csv"><button type="button">' . lang::get('Download') . '</button></a></td></tr>' . "\n";
     }
     if ($hasData && count($options['downloads']) > 0) {
         // format is assumed to be CSV
         global $indicia_templates;
         $indicia_templates['report_download_link'] = '<a target="_blank" href="{link}" download ><button type="button">' . lang::get('Download') . '</button></a>';
         $downloadOptions = array('readAuth' => $options['readAuth'], 'extraParams' => array_merge($options['extraParams'], array('date_from' => $options['date_start'], 'date_to' => $options['date_end'])), 'itemsPerPage' => false);
         // there are problems dealing with location_list as an array if empty, so connvert
         if ($downloadOptions['extraParams']['location_list'] == "") {
             $downloadOptions['extraParams']['location_list'] = "(-1)";
         } else {
             $downloadOptions['extraParams']['location_list'] = '(' . $downloadOptions['extraParams']['location_list'] . ')';
         }
         foreach ($options['downloads'] as $download) {
             $downloadOptions['dataSource'] = $download['dataSource'];
             $downloadOptions['filename'] = $download['filename'];
             $downloadTab .= '<tr><td>' . $download['caption'] . ' : </td><td>' . report_helper::report_download_link($downloadOptions) . '</td></tr>';
         }
     }
     if ($downloadTab != "") {
         $tabs['#dataDownloads'] = lang::get('Downloads');
     }
     $r .= '<div id="controls">' . data_entry_helper::enable_tabs(array('divId' => 'controls')) . data_entry_helper::tab_header(array('tabs' => $tabs)) . ($hasData ? '<div id="summaryData">' . $summaryTab . '</div>' . '<div id="summaryChart"><div id="' . $options['chartID'] . '-summary" style="height:' . $options['height'] . 'px;' . (isset($options['width']) && $options['width'] != '' ? 'width:' . $options['width'] . 'px;' : '') . '"></div>' . $summarySeriesPanel . '</div>' . '<div id="estimateData">' . $estimateTab . '</div>' . '<div id="estimateChart"><div id="' . $options['chartID'] . '-estimates" style="height:' . $options['height'] . 'px;' . (isset($options['width']) && $options['width'] != '' ? 'width:' . $options['width'] . 'px;' : '') . '"></div>' . $summarySeriesPanel . '</div>' : '<div id="summaryData"><p>' . lang::get('No data available for this period with these filter values.') . '</p></div>') . '<div id="rawData">' . $rawTab . '</div>' . ($downloadTab != "" ? '<div id="dataDownloads"><table><tbody style="border:none;">' . $downloadTab . '</tbody></table></div>' : '') . '</div>';
     $warnings .= '<span style="display:none;">Finish report_calendar_summary : ' . date(DATE_ATOM) . '</span>' . "\n";
     return $warnings . $r;
 }