From 561c094b391a2a2d6b1d90b1fe5c591f6aa84073 Mon Sep 17 00:00:00 2001 From: Stephen Ficklin Date: Wed, 20 Nov 2019 12:11:06 -0800 Subject: [PATCH] Fixed bug with display of HTML reports. Fixed but with providing files directly to the tool (not via a data uploader step). Created a new tripal_galaxy.results.inc file to make finding the functions that generate results pages much easiers --- api/tripal_galaxy.api.inc | 61 +- includes/tripal_galaxy.admin.inc | 0 .../tripal_galaxy.admin_settings_form.inc | 0 .../tripal_galaxy.admin_workflow_form.inc | 0 includes/tripal_galaxy.results.inc | 681 ++++++++++++++++++ includes/tripal_galaxy.user.inc | 0 includes/tripal_galaxy.webform.inc | 26 +- includes/views_handler_view_delete_field.inc | 0 includes/views_handler_view_rerun_field.inc | 0 includes/views_handler_view_results_field.inc | 0 .../views_handler_view_submission_field.inc | 0 tripal_galaxy.module | 614 +--------------- 12 files changed, 700 insertions(+), 682 deletions(-) mode change 100755 => 100644 includes/tripal_galaxy.admin.inc mode change 100755 => 100644 includes/tripal_galaxy.admin_settings_form.inc mode change 100755 => 100644 includes/tripal_galaxy.admin_workflow_form.inc create mode 100644 includes/tripal_galaxy.results.inc mode change 100755 => 100644 includes/tripal_galaxy.user.inc mode change 100755 => 100644 includes/tripal_galaxy.webform.inc mode change 100755 => 100644 includes/views_handler_view_delete_field.inc mode change 100755 => 100644 includes/views_handler_view_rerun_field.inc mode change 100755 => 100644 includes/views_handler_view_results_field.inc mode change 100755 => 100644 includes/views_handler_view_submission_field.inc diff --git a/api/tripal_galaxy.api.inc b/api/tripal_galaxy.api.inc index 6efc38d..642f4a4 100755 --- a/api/tripal_galaxy.api.inc +++ b/api/tripal_galaxy.api.inc @@ -951,8 +951,12 @@ function tripal_galaxy_invoke_workflow(GalaxyInstance $galaxy, $submission, arra drupal_set_message($error_msg, 'error'); db_update('tripal_galaxy_workflow_submission')->fields([ 'status' => 'Error', - 'errors' => $error_msg, - ]) + 'errors' => serialize([ + 'history' => $history, + 'history_contents' => '', + 'history_info' => '', + 'error' => $error_msg]) + ]) ->condition('sid', $sid) ->execute(); tripal_galaxy_send_submission_failed_mail($sid); @@ -967,7 +971,7 @@ function tripal_galaxy_invoke_workflow(GalaxyInstance $galaxy, $submission, arra 'history' => $history, 'history_contents' => '', 'history_info' => '', - ]), + 'error' => '']), ]) ->condition('sid', $sid) ->execute(); @@ -1495,54 +1499,3 @@ function tripal_galaxy_download_file(stdClass $submission, array $dataset, int $ return $file; } -/** - * Adds a URL to the proxy array. - * - * This function can be used to create a URL for downloading of a dataset from - * a remote Galaxy server. - * - * @param stdClass $submission - * A submission object as obtained by the tripal_galaxy_get_submission() - * function. - * @param array $dataset - * An array describing the dataset as returned by the - * tripal_galaxy_get_dataset() or tripal_galaxy_get_datasets() functions. - * @param int $uid - * The user that is allowed to view this link. - * @param string $action - * The action to perform when the link is clicked. Can be 'viewer', - * 'viewer-full', or 'download'. The action 'viewer' will create a link for - * results to be shown inside of a page on the Drupal site. The action - * 'viewer-full' will create a link for results to be shown stand-alone. The - * action 'download' will create a link that will start a download of the - * file. - * - * @throws Exception - * - * @return - * A URL that can be used, when clicked by the end-user, to either view or - * download the dataset. - * - * @ingroup tripal_galaxy_api - */ -function tripal_galaxy_get_proxy_url(stdClass $submission, array $dataset, int $uid, string $action) { - - if (!in_array($action, ['viewer', 'viewer-full', 'download'])) { - throw new Exception('Please indicate the action as: "viewer" or "download".'); - } - - $galaxy_id = $submission->workflow->galaxy_id; - $galaxy = tripal_galaxy_get_connection($galaxy_id); - - if (!array_key_exists('tripal_galaxy_proxy_urls', $_SESSION)) { - $_SESSION['tripal_galaxy_proxy_urls'] = []; - }; - $id = uniqid('TGPX', TRUE); - $_SESSION['tripal_galaxy_proxy_urls'][$id]['dataset'] = $dataset; - $_SESSION['tripal_galaxy_proxy_urls'][$id]['sid'] = $submission->sid; - $_SESSION['tripal_galaxy_proxy_urls'][$id]['uid'] = $uid; - - // Create the link. - $url = 'galaxy/' . $action . '/' . $id; - return $url; -} diff --git a/includes/tripal_galaxy.admin.inc b/includes/tripal_galaxy.admin.inc old mode 100755 new mode 100644 diff --git a/includes/tripal_galaxy.admin_settings_form.inc b/includes/tripal_galaxy.admin_settings_form.inc old mode 100755 new mode 100644 diff --git a/includes/tripal_galaxy.admin_workflow_form.inc b/includes/tripal_galaxy.admin_workflow_form.inc old mode 100755 new mode 100644 diff --git a/includes/tripal_galaxy.results.inc b/includes/tripal_galaxy.results.inc new file mode 100644 index 0000000..baa0faa --- /dev/null +++ b/includes/tripal_galaxy.results.inc @@ -0,0 +1,681 @@ +', "https://galaxyproject.org/", [ + 'html' => TRUE, + 'attributes' => [ + 'target' => '_blank', + ], + ]); + + // Get the submission details. + $submission = tripal_galaxy_get_submission($sid); + if (!$submission) { + return FALSE; + } + + $title = $submission->workflow_name; + + // If this a webform submission make sure the user has access to the + // node that this workflow belongs to. + if ($submission->nid) { + $node = node_load($submission->nid); + + // Does this user have access to this node? + if (!node_access('view', $node)) { + drupal_access_denied(); + module_invoke_all('exit'); + drupal_exit(); + } + $title = $node->title; + } + + // Get the galaxy server. + $galaxy = db_select('tripal_galaxy', 'tg') + ->fields('tg') + ->condition('galaxy_id', $submission->galaxy_id) + ->execute() + ->fetchObject(); + + // Before doing anything check that the history has not been deleted. + $galaxy_instance = tripal_galaxy_get_connection($submission->galaxy_id); + $history_name = tripal_galaxy_get_history_name($submission); + $error = []; + $history = tripal_galaxy_get_history($galaxy_instance, $history_name); + + if ($history['deleted'] === TRUE) { + $content['deleted'] = [ + '#type' => 'item', + '#title' => t('Results deleted from Galaxy Server'), + '#description' => t('It appears this analysis result has been deleted from the galaxy server on which it was run. Please return to the previous page and delete this from your workflow listing.'), + ]; + db_update('tripal_galaxy_workflow_submission')->fields([ + 'status' => 'deleted', + ]) + ->condition('sid', $submission->sid) + ->execute(); + return $content; + } + + // Get the list of input files so we can exclude them from the results + $files_query = db_select('file_usage', 'fu'); + $files_query->join('file_managed', 'fm', 'fu.fid = fm.fid'); + $files_query->fields('fm', ['filename']); + $files_query->condition('fu.id', $sid); + $files_query->condition('fu.module', 'tripal_galaxy'); + $files_query->condition('fu.type', 'submission'); + $input_files = $files_query->execute()->fetchCol(); + + $headers = []; + $submission_details = []; + $submission_details[] = [ + [ + 'data' => 'Workflow Name', + 'header' => TRUE, + 'width' => '25%', + ], + $title, + ]; + if (user_access('administer galaxy')) { + $submission_details[] = [ + [ + 'data' => 'Submission ID', + 'header' => TRUE, + 'width' => '25%', + ], + $submission->sid, + ]; + $submission_details[] = [ + [ + 'data' => 'Workflow ID', + 'header' => TRUE, + 'width' => '25%', + ], + $submission->workflow_id, + ]; + $submission_details[] = [ + [ + 'data' => 'Invocation ID', + 'header' => TRUE, + 'width' => '25%', + ], + $submission->invocation_id, + ]; + } + $submission_details[] = [ + [ + 'data' => 'Status', + 'header' => TRUE, + ], + $submission->status, + ]; + $submission_details[] = [ + [ + 'data' => 'Submission Error', + 'header' => TRUE, + ], + array_key_exists('error', $submission->errors) ? $submission->errors['error'] : '', + ]; + $submission_details[] = [ + [ + 'data' => 'Submission Date', + 'header' => TRUE, + ], + format_date($submission->submit_date), + ]; + $submission_details[] = [ + [ + 'data' => 'History Name', + 'header' => TRUE, + ], + tripal_galaxy_get_history_name($submission), + ]; + $submission_details[] = [ + [ + 'data' => 'Start Time', + 'header' => TRUE, + ], + $submission->start_time ? format_date($submission->start_time) : '', + ]; + $submission_details[] = [ + [ + 'data' => 'End Time', + 'header' => TRUE, + ], + $submission->end_time ? format_date($submission->end_time) : '', + ]; + + $submission_details[] = [ + [ + 'data' => 'Galaxy Server', + 'header' => TRUE, + ], + $galaxy->servername . '
' . $galaxy_logo, + ]; + + if ($submission->status == 'Error') { + $content['status_message'] = [ + '#type' => 'markup', + '#markup' => '
' . t('This analysis failed. Check for errors in the subission details or in the error section if result files are present.') . '
', + ]; + } + + $content['analysis_name'] = [ + '#type' => 'item', + '#title' => 'Analysis Name', + '#markup' => $title, + ]; + + $content['submission_details'] = [ + '#type' => 'fieldset', + '#title' => t('Submission Details'), + '#collapsible' => TRUE, + '#collapsed' => TRUE, + '#attributes' => [ + 'class' => [ + 'collapsible', + 'collapsed', + ], + ], + '#attached' => [ + 'js' => [ + 'misc/collapse.js', + 'misc/form.js', + ], + ], + ]; + + $content['submission_details']['table'] = [ + '#type' => 'markup', + '#markup' => theme_table([ + 'header' => $headers, + 'rows' => $submission_details, + 'attributes' => [ + 'class' => 'tripal-galaxy-submission-table' + ], + 'sticky' => FALSE, + 'caption' => '', + 'colgroups' => [], + 'empty' => '', + ]), + ]; + + + $content['errors'] = [ + '#type' => 'fieldset', + '#title' => t('Errors'), + '#collapsible' => TRUE, + '#collapsed' => TRUE, + '#attributes' => [ + 'class' => [ + 'collapsible', + 'collapsed', + ], + ], + '#attached' => [ + 'js' => [ + 'misc/collapse.js', + 'misc/form.js', + ], + ], + ]; + + + // Get details about the galaxy server and the connection to Galaxy. + $galaxy_server = tripal_galaxy_get_galaxy($submission->galaxy_id); + $galaxy = tripal_galaxy_get_connection($submission->galaxy_id); + + // This is just a placeholder for the results text. It will get fully + // set below. + $content['results'] = [ + '#type' => 'item', + ]; + + $errors = []; + $has_any_results = FALSE; + if (is_array($submission->errors)) { + + // If the workflow status is 'Completed' then there will be a history and + // history contents. We'll get those out and remove them so we + // can more easily iterate through the steps. + if (array_key_exists('history_contents', $submission->errors)) { + $history_contents = $submission->errors['history_contents']; + } + if (array_key_exists('history_info', $submission->errors)) { + $history_info = $submission->errors['history_info']; + } + + if (isset($history_contents) and is_array($history_contents) and + isset($history_info) and is_array($history_info)) { + foreach ($history_contents as $index => $history_content) { + + // Skip history items that does not have 'ok' or 'error' state. + if (!in_array($history_content['id'], array_merge($history_info['state_ids']['ok'], $history_info['state_ids']['error']))) { + continue; + } + + // If there are any errors on any file creation, then we'll add + // the error message to tour file_errors list. + if ($history_content['state'] == 'error') { + $errors[] = [ + [ + 'data' => $history_content['name'], + 'header' => TRUE, + ], + '
' . $history_content['creating_job']['stderr'] . '
' + ]; + continue; + } + + // Skip history content items that should be hidden. + if ($history_content['visible'] != TRUE) { + continue; + } + + // Don't show input files. + if (in_array($history_content['name'], $input_files)) { + continue; + } + + $has_any_results = TRUE; + + $step_content = []; + $step_content['history_content_' . $history_content['id'] . '_' . $index] = [ + '#type' => 'fieldset', + '#title' => $history_content['name'], + '#collapsed' => TRUE, + '#collapsible' => TRUE, + '#attributes' => [ + 'class' => ['collapsible', 'collapsed'], + ], + '#attached' => [ + 'js' => [ + 'misc/collapse.js', + 'misc/form.js', + ], + ], + ]; + + // If this is a file add viewing and download links + if ($history_content['type'] == 'file') { + if (!isset($history_content['content_link'])) { + break; + } + + // If this is an HTML file then add a view link. + if ($history_content['extension'] == 'html') { + $dataset_id = $history_content['id']; + $dataset = tripal_galaxy_get_dataset($submission, $dataset_id); + $proxy_url = tripal_galaxy_get_proxy_url($submission, $dataset, $node->uid, 'download'); + $step_content['history_content_' . $history_content['id'] . '_' . $index]['html_view'] = [ + '#type' => 'item', + '#title' => t('Download web page report'), + '#markup' => l($history_content['name'], $proxy_url, ['attributes' => ['target' => '_blank']]), + ]; + } + // If this is not an HTML file then provide link to view the file + // unless it exceeds 1MB. If Galaxy provides a peek then show that. + else { + $link = $history_content['content_link']; + $dataset_id = $history_content['id']; + $dataset = tripal_galaxy_get_dataset($submission, $dataset_id); + $proxy_url = tripal_galaxy_get_proxy_url($submission, $dataset, $node->uid, 'download'); + $file_size = tripal_format_bytes($history_content['file_size']); + $step_content['history_content_' . $history_content['id'] . '_' . $index]['download_link'] = [ + '#type' => 'item', + '#title' => t('Download File'), + '#markup' => l($history_content['name'], $proxy_url) . ' (' . $file_size . ')', + ]; + + // Any files that are smaller than 1MB can be shown in a browser. + if ($history_content['file_size'] < pow(10, 6)) { + // SPF: originally this was $history_content['dataset_id'] but for + // some reason that value seems off for v17.09 as it does not + // point to the correct dataset. Rather the 'id' does. However, + // in v18.01 it seems fixed and both 'id' and 'dataset_id' are the + // same. + $dataset_id = $history_content['id']; + $dataset = tripal_galaxy_get_dataset($submission, $dataset_id); + $proxy_url = tripal_galaxy_get_proxy_url($submission, $dataset, $node->uid, 'viewer-full'); + $step_content['history_content_' . $history_content['id'] . '_' . $index]['html_view'] = [ + '#type' => 'item', + '#title' => t('View File'), + '#markup' => l($history_content['name'], $proxy_url, ['attributes' => ['target' => '_blank']] ), + ]; + } + + // Provide a peek if one is provided. + if ($history_content['peek'] != NULL) { + $step_content['history_content_' . $history_content['id'] . '_' . $index]['peek'] = [ + '#type' => 'item', + '#title' => 'Peek', + '#description' => 'A short view of the first few lines of the output file.', + '#markup' => '
' . $history_content['peek'] . '
', + ]; + } + } + } // End switch ($history_content['extension']) { ... + // end foreach ($history_contents as $index => $history_content) { ... + $content['history_content_' . $history_content['id'] . '_' . $index] = $step_content['history_content_' . $history_content['id'] . '_' . $index]; + } + } + } + + if (count($errors) > 0) { + $content['errors']['table'] = [ + '#type' => 'markup', + '#markup' => theme_table([ + 'header' => $headers, + 'rows' => $errors, + 'attributes' => [ + 'class' => 'tripal-galaxy-error-table' + ], + 'sticky' => FALSE, + 'caption' => '', + 'colgroups' => [], + 'empty' => '', + ]), + ]; + } + else { + unset($content['errors']); + } + + if ($has_any_results) { + $content['results'] = [ + '#type' => 'item', + '#title' => t('Result Files'), + '#markup' => t('The result files are listed below. Click the filename to view or download results. Expand the field for the result below to + view the status, peek or download result files.'), + ]; + } + else { + $content['results'] = [ + '#type' => 'item', + '#title' => t('Results'), + '#markup' => t('Currently, no results exist for this job. The current state of the job is: %state.', [ + '%state' => $submission->status, + ]), + ]; + } + + + + return $content; +} + + +/** + * A generic full page for viewing content from Galaxy. + * + * @param string $proxy_id + * A unique proxy ID that maps to a URL. + */ +function tripal_galaxy_stream_link_proxy(string $proxy_id) { + if (array_key_exists($proxy_id, $_SESSION['tripal_galaxy_proxy_urls'])) { + + // Get the current proxy details, so we can map links for download. + $cproxy = $_SESSION['tripal_galaxy_proxy_urls'][$proxy_id]; + $dataset = $cproxy['dataset']; + $uid = $cproxy['uid']; + $sid = $cproxy['sid']; + + // retrieve the pertinents needed to download the file. + $submission = tripal_galaxy_get_submission($sid); + $galaxy_id = $submission->workflow->galaxy_id; + $galaxy = tripal_galaxy_get_connection($galaxy_id); + $dataset_id = $dataset['id']; + + $url = $galaxy->getURL() . $dataset['download_url']; + $headers = get_headers($url); + foreach ($headers as $header) { + $results = preg_split('/:/', $header, 2); + if (count($results) == 2) { + drupal_add_http_header($results[0], $results[1]); + } + } + print tripal_galaxy_stream_url_proxy_url($url); + + exit(); + } + else { + $content['name'] = [ + '#type' => 'markup', + '#markup' => t('This page has expired. Please reload the job results page for uploaded links.'), + ]; + return $content; + } +} + +/** + * A generic full page for viewing content from Galaxy. + * + * @param string $proxy_id + * A unique proxy ID that maps to a URL. + */ +function tripal_galaxy_results_viewer_full_page(string $proxy_id) { + if (array_key_exists($proxy_id, $_SESSION['tripal_galaxy_proxy_urls'])) { + $content = tripal_galaxy_stream_url_proxy($proxy_id); + + // Replace relative URLs to have the proxy. + $url = url('galaxy/link/' . $proxy_id); + $content = preg_replace('/href\s*=\s*[\'"](?!\s*http)(.*?)[\'"]/', 'href=' . $url . '?url=\1', $content); + return $content; + } + else { + $content['name'] = [ + '#type' => 'markup', + '#markup' => t('This link has expired. Please reload the job results page for uploaded links.'), + ]; + return $content; + } +} + +/** + * A generic page for viewing content from Galaxy. + * + * @param string $proxy_id + * A unique proxy ID that maps to a URL. + */ +function tripal_galaxy_results_viewer_page(string $proxy_id) { + if (array_key_exists($proxy_id, $_SESSION['tripal_galaxy_proxy_urls'])) { + + // Get the current proxy details, so we can map links for download. + $cproxy = $_SESSION['tripal_galaxy_proxy_urls'][$proxy_id]; + $dataset = $cproxy['dataset']; + $uid = $cproxy['uid']; + $sid = $cproxy['sid']; + + $user = user_load($uid); + + // Set the breadcrumb. + $breadcrumb = []; + $breadcrumb[] = l(t('Home'), ''); + $breadcrumb[] = l($user->name, 'user/' . $uid); + $breadcrumb[] = l(t('Analyses'), 'user/' . $uid . 'galaxy-jobs'); + $breadcrumb[] = l(t('Analysis Results'), 'user/' . $uid . '/galaxy-jobs/' . $sid); + drupal_set_breadcrumb($breadcrumb); + + // retrieve the pertinents needed to download the file. + $submission = tripal_galaxy_get_submission($sid); + $galaxy_id = $submission->workflow->galaxy_id; + $galaxy = tripal_galaxy_get_connection($galaxy_id); + $dataset_id = $dataset['id']; + $name = $dataset['name']; + + $content['sub_title'] = [ + '#type' => 'markup', + '#markup' => '

Viewing results for ' . $name . '

', + ]; + $content['name'] = [ + '#type' => 'markup', + '#markup' => l(t('View full screen'), 'galaxy/viewer-full/' . $proxy_id), + ]; + $content['viewer'] = [ + '#type' => 'item', + '#markup' => '', + ]; + + return $content; + } + else { + $content['name'] = [ + '#type' => 'markup', + '#markup' => t('This link has expired. Please reload the job results page for uploaded links.'), + ]; + return $content; + } +} + +/** + * A generic callback for downloading content from Galaxy. + * + * @param string $proxy_id + * A unique proxy ID that maps to a URL. + */ +function tripal_galaxy_results_download(string $proxy_id) { + + // Get the current proxy details, so we can map links for download. + $cproxy = $_SESSION['tripal_galaxy_proxy_urls'][$proxy_id]; + $dataset = $cproxy['dataset']; + $uid = $cproxy['uid']; + $sid = $cproxy['sid']; + + // retrieve the pertinents needed to download the file. + $submission = tripal_galaxy_get_submission($sid); + $galaxy_id = $submission->workflow->galaxy_id; + $galaxy = tripal_galaxy_get_connection($galaxy_id); + $dataset_id = $dataset['id']; + + $url = $galaxy->getURL() . $dataset['download_url'] . '?to_ext=' . $dataset['extension']; + + $headers = get_headers($url); + foreach ($headers as $header) { + $results = preg_split('/:/', $header, 2); + if (count($results) == 2) { + drupal_add_http_header($results[0], $results[1]); + } + } + print tripal_galaxy_stream_url_proxy_url($url); + + exit(); +} + + +/** + * Retrieves content from a Galaxy URL and stream it back. + * + * @param string $proxy_id + * A unique ID that maps to a URL. + */ +function tripal_galaxy_stream_url_proxy(string $proxy_id) { + // Get the current proxy details, so we can map links for download. + $cproxy = $_SESSION['tripal_galaxy_proxy_urls'][$proxy_id]; + $dataset = $cproxy['dataset']; + $uid = $cproxy['uid']; + $sid = $cproxy['sid']; + + // retrieve the pertinents needed to download the file. + $submission = tripal_galaxy_get_submission($sid); + $galaxy_id = $submission->workflow->galaxy_id; + $galaxy = tripal_galaxy_get_connection($galaxy_id); + $dataset_id = $dataset['id']; + + $url = $galaxy->getURL() . $dataset['download_url']; + + return tripal_galaxy_stream_url_proxy_url($url); +} + +/** + * Retrieves content from a Galaxy URL and stream it back. + * + * @param string $url + * A valid URL on the remote Galaxy server. + */ +function tripal_galaxy_stream_url_proxy_url(string $url) { + $headers = get_headers($url); + $ch = curl_init(); + + curl_setopt($ch, CURLOPT_URL, $url); + curl_setopt($ch, CURLOPT_RETURNTRANSFER, TRUE); + $output = curl_exec($ch); + if ($output === FALSE) { + $error_msg = curl_error($ch); + $this->error->setError('HTTP', $error_msg); + return $error_msg; + } + curl_close($ch); + + if (!$output) { + $output = 'The remote Galaxy server returns no display.'; + } + return $output; +} + + +/** + * Adds a URL to the proxy array. + * + * This function can be used to create a URL for downloading of a dataset from + * a remote Galaxy server. + * + * @param stdClass $submission + * A submission object as obtained by the tripal_galaxy_get_submission() + * function. + * @param array $dataset + * An array describing the dataset as returned by the + * tripal_galaxy_get_dataset() or tripal_galaxy_get_datasets() functions. + * @param int $uid + * The user that is allowed to view this link. + * @param string $action + * The action to perform when the link is clicked. Can be 'viewer', + * 'viewer-full', or 'download'. The action 'viewer' will create a link for + * results to be shown inside of a page on the Drupal site. The action + * 'viewer-full' will create a link for results to be shown stand-alone. The + * action 'download' will create a link that will start a download of the + * file. + * + * @throws Exception + * + * @return + * A URL that can be used, when clicked by the end-user, to either view or + * download the dataset. + * + * @ingroup tripal_galaxy_api + */ +function tripal_galaxy_get_proxy_url(stdClass $submission, array $dataset, int $uid, string $action) { + + if (!in_array($action, ['viewer', 'viewer-full', 'download'])) { + throw new Exception('Please indicate the action as: "viewer" or "download".'); + } + + $galaxy_id = $submission->workflow->galaxy_id; + $galaxy = tripal_galaxy_get_connection($galaxy_id); + + if (!array_key_exists('tripal_galaxy_proxy_urls', $_SESSION)) { + $_SESSION['tripal_galaxy_proxy_urls'] = []; + }; + $id = uniqid('TGPX', TRUE); + $_SESSION['tripal_galaxy_proxy_urls'][$id]['dataset'] = $dataset; + $_SESSION['tripal_galaxy_proxy_urls'][$id]['sid'] = $submission->sid; + $_SESSION['tripal_galaxy_proxy_urls'][$id]['uid'] = $uid; + + // Create the link. + $url = 'galaxy/' . $action . '/' . $id; + return $url; +} \ No newline at end of file diff --git a/includes/tripal_galaxy.user.inc b/includes/tripal_galaxy.user.inc old mode 100755 new mode 100644 diff --git a/includes/tripal_galaxy.webform.inc b/includes/tripal_galaxy.webform.inc old mode 100755 new mode 100644 index f6e66b9..16567fe --- a/includes/tripal_galaxy.webform.inc +++ b/includes/tripal_galaxy.webform.inc @@ -53,6 +53,7 @@ function tripal_galaxy_build_webform($galaxy_id, $workflow_id) { // Iterate through each step of the workflow. $tool_list = []; $steps = $workflow['steps']; + //dpm($steps); foreach ($steps as $step_index => $step) { if (isset($step['annotation'])) { @@ -204,6 +205,7 @@ function tripal_galaxy_build_webform($galaxy_id, $workflow_id) { drupal_set_message('Error building tool: ' . $tool_id . '. Galaxy Server response: ' . $error['message'], 'error'); return FALSE; } + //dpm($tool); $tool_list[] = '' . $tool['name'] . ' (version ' . $tool['version'] . '): ' . $tool['description']; // We want to change the name of the fieldset to have the name of @@ -733,12 +735,12 @@ function tripal_galaxy_build_webform_add_component($webform, $workflow, $step, $ case 'integer': $webform_type = 'number'; - $webform_value = (int) $webform_value; + $webform_value = $webform_value; break; case 'float': $webform_type = 'number'; - $webform_value = (float) $webform_value; + $webform_value = $webform_value; break; case 'boolean': @@ -1293,9 +1295,12 @@ function tripal_galaxy_invoke_webform_submission($sid, $job = NULL) { $file = $inputs[$data->form_key]; foreach ($history_contents as $hcontent) { if ($hcontent['name'] == $file['name']) { - $value = $hcontent['id']; + $value = [ + 'id' => $hcontent['dataset_id'], + 'src' => 'hda', + ]; $input_datasets[$step_index] = [ - 'id' => $value, + 'id' => $hcontent['dataset_id'], 'src' => 'hda', ]; } @@ -1306,7 +1311,7 @@ function tripal_galaxy_invoke_webform_submission($sid, $job = NULL) { $dataset = $inputs[$data->form_key]; $value = $dataset['id']; $input_datasets[$step_index] = [ - 'id' => $value, + 'id' => $dataset['id'], 'src' => 'hdca', ]; } @@ -1315,7 +1320,7 @@ function tripal_galaxy_invoke_webform_submission($sid, $job = NULL) { $dataset = $inputs[$data->form_key]; $value = $dataset['id']; $input_datasets[$step_index] = [ - 'id' => $value, + 'id' => $dataset['id'], 'src' => 'hdca', ]; } @@ -1335,19 +1340,10 @@ function tripal_galaxy_invoke_webform_submission($sid, $job = NULL) { $parameters[$step_index] = []; } $current_values = $parameters[$step_index]; - _tripal_galaxy_invoke_webform_build_values($current_values, $input_name, $value); $parameters[$step_index] = $current_values; } - if (key($parameters[0]) == 'vcf_input') { - $parameters[0]['Data File'] = $parameters[0]['vcf_input']; - $parameters[1]['vcf_input'] = $parameters[0]['vcf_input']; - // unset($parameters[0]['vcf_input']); - // $parameters[0]['vcf_input'] = $parameters[0]['Data File']; - // unset($parameters[0]['vcf_input']);. - } - // Call the Tripal Galaxy API function to invoke this workflow. tripal_galaxy_invoke_workflow($galaxy, $submission, $parameters, $input_datasets, $history); } diff --git a/includes/views_handler_view_delete_field.inc b/includes/views_handler_view_delete_field.inc old mode 100755 new mode 100644 diff --git a/includes/views_handler_view_rerun_field.inc b/includes/views_handler_view_rerun_field.inc old mode 100755 new mode 100644 diff --git a/includes/views_handler_view_results_field.inc b/includes/views_handler_view_results_field.inc old mode 100755 new mode 100644 diff --git a/includes/views_handler_view_submission_field.inc b/includes/views_handler_view_submission_field.inc old mode 100755 new mode 100644 diff --git a/tripal_galaxy.module b/tripal_galaxy.module index 8b247ba..a4c412f 100755 --- a/tripal_galaxy.module +++ b/tripal_galaxy.module @@ -9,6 +9,7 @@ require 'theme/tripal_galaxy.theme.inc'; require 'api/tripal_galaxy.api.inc'; require 'includes/tripal_galaxy.form_elements.inc'; require 'includes/tripal_galaxy.webform.inc'; +require 'includes/tripal_galaxy.results.inc'; /** * Implements hook_init(). @@ -860,415 +861,6 @@ function tripal_galaxy_webform_submission_presave($node, &$submission) { } } -/** - * The report page for a galaxy workflow submission. - * - * @param int $sid - * The submission ID of the workflow. - */ -function tripal_galaxy_workflow_report(int $sid) { - if (!$sid) { - return FALSE; - } - if (!is_numeric($sid)) { - return FALSE; - } - - // Create a galaxy logo clickable image. - $galaxy_logo = l('', "https://galaxyproject.org/", [ - 'html' => TRUE, - 'attributes' => [ - 'target' => '_blank', - ], - ]); - - // Get the submission details. - $submission = tripal_galaxy_get_submission($sid); - if (!$submission) { - return FALSE; - } - - $title = $submission->workflow_name; - - // If this a webform submission make sure the user has access to the - // node that this workflow belongs to. - if ($submission->nid) { - $node = node_load($submission->nid); - - // Does this user have access to this node? - if (!node_access('view', $node)) { - drupal_access_denied(); - module_invoke_all('exit'); - drupal_exit(); - } - $title = $node->title; - } - - // Get the galaxy server. - $galaxy = db_select('tripal_galaxy', 'tg') - ->fields('tg') - ->condition('galaxy_id', $submission->galaxy_id) - ->execute() - ->fetchObject(); - - // Before doing anything check that the history has not been deleted. - $galaxy_instance = tripal_galaxy_get_connection($submission->galaxy_id); - $history_name = tripal_galaxy_get_history_name($submission); - $error = []; - $history = tripal_galaxy_get_history($galaxy_instance, $history_name); - - if ($history['deleted'] === TRUE) { - $content['deleted'] = [ - '#type' => 'item', - '#title' => t('Results deleted from Galaxy Server'), - '#description' => t('It appears this analysis result has been deleted from the galaxy server on which it was run. Please return to the previous page and delete this from your workflow listing.'), - ]; - db_update('tripal_galaxy_workflow_submission')->fields([ - 'status' => 'deleted', - ]) - ->condition('sid', $submission->sid) - ->execute(); - return $content; - } - - // Get the list of input files so we can exclude them from the results - $files_query = db_select('file_usage', 'fu'); - $files_query->join('file_managed', 'fm', 'fu.fid = fm.fid'); - $files_query->fields('fm', ['filename']); - $files_query->condition('fu.id', $sid); - $files_query->condition('fu.module', 'tripal_galaxy'); - $files_query->condition('fu.type', 'submission'); - $input_files = $files_query->execute()->fetchCol(); - - $headers = []; - $submission_details = []; - $submission_details[] = [ - [ - 'data' => 'Workflow Name', - 'header' => TRUE, - 'width' => '25%', - ], - $title, - ]; - if (user_access('administer galaxy')) { - $submission_details[] = [ - [ - 'data' => 'Submission ID', - 'header' => TRUE, - 'width' => '25%', - ], - $submission->sid, - ]; - $submission_details[] = [ - [ - 'data' => 'Workflow ID', - 'header' => TRUE, - 'width' => '25%', - ], - $submission->workflow_id, - ]; - $submission_details[] = [ - [ - 'data' => 'Invocation ID', - 'header' => TRUE, - 'width' => '25%', - ], - $submission->invocation_id, - ]; - } - $submission_details[] = [ - [ - 'data' => 'Status', - 'header' => TRUE, - ], - $submission->status, - ]; - $submission_details[] = [ - [ - 'data' => 'Submission Date', - 'header' => TRUE, - ], - format_date($submission->submit_date), - ]; - $submission_details[] = [ - [ - 'data' => 'History Name', - 'header' => TRUE, - ], - tripal_galaxy_get_history_name($submission), - ]; - $submission_details[] = [ - [ - 'data' => 'Start Time', - 'header' => TRUE, - ], - $submission->start_time ? format_date($submission->start_time) : '', - ]; - $submission_details[] = [ - [ - 'data' => 'End Time', - 'header' => TRUE, - ], - $submission->end_time ? format_date($submission->end_time) : '', - ]; - - $submission_details[] = [ - [ - 'data' => 'Galaxy Server', - 'header' => TRUE, - ], - $galaxy->servername . '
' . $galaxy_logo, - ]; - - if ($submission->status == 'Error') { - $content['status_message'] = [ - '#type' => 'markup', - '#markup' => '
' . t('This analysis failed. Please view the error logs for more details.') . '
', - ]; - } - - $content['analysis_name'] = [ - '#type' => 'item', - '#title' => 'Analysis Name', - '#markup' => $title, - ]; - - $content['submission_details'] = [ - '#type' => 'fieldset', - '#title' => t('Submission Details'), - '#collapsible' => TRUE, - '#collapsed' => TRUE, - '#attributes' => [ - 'class' => [ - 'collapsible', - 'collapsed', - ], - ], - '#attached' => [ - 'js' => [ - 'misc/collapse.js', - 'misc/form.js', - ], - ], - ]; - - $content['submission_details']['table'] = [ - '#type' => 'markup', - '#markup' => theme_table([ - 'header' => $headers, - 'rows' => $submission_details, - 'attributes' => [ - 'class' => 'tripal-galaxy-submission-table' - ], - 'sticky' => FALSE, - 'caption' => '', - 'colgroups' => [], - 'empty' => '', - ]), - ]; - - - $content['errors'] = [ - '#type' => 'fieldset', - '#title' => t('Errors'), - '#collapsible' => TRUE, - '#collapsed' => TRUE, - '#attributes' => [ - 'class' => [ - 'collapsible', - 'collapsed', - ], - ], - '#attached' => [ - 'js' => [ - 'misc/collapse.js', - 'misc/form.js', - ], - ], - ]; - - - // Get details about the galaxy server and the connection to Galaxy. - $galaxy_server = tripal_galaxy_get_galaxy($submission->galaxy_id); - $galaxy = tripal_galaxy_get_connection($submission->galaxy_id); - - // This is just a placeholder for the results text. It will get fully - // set below. - $content['results'] = [ - '#type' => 'item', - ]; - - $errors = []; - $has_any_results = FALSE; - if (is_array($submission->errors)) { - - // If the workflow status is 'Completed' then there will be a history and - // history contents. We'll get those out and remove them so we - // can more easily iterate through the steps. - if (array_key_exists('history_contents', $submission->errors)) { - $history_contents = $submission->errors['history_contents']; - } - if (array_key_exists('history_info', $submission->errors)) { - $history_info = $submission->errors['history_info']; - } - - if (isset($history_contents) and isset($history_info)) { - foreach ($history_contents as $index => $history_content) { - - // Skip history items that does not have 'ok' or 'error' state. - if (!in_array($history_content['id'], array_merge($history_info['state_ids']['ok'], $history_info['state_ids']['error']))) { - continue; - } - - // If there are any errors on any file creation, then we'll add - // the error message to tour file_errors list. - if ($history_content['state'] == 'error') { - $errors[] = [ - [ - 'data' => $history_content['name'], - 'header' => TRUE, - ], - '
' . $history_content['creating_job']['stderr'] . '
' - ]; - continue; - } - - // Skip history content items that should be hidden. - if ($history_content['visible'] != TRUE) { - continue; - } - - // Don't show input files. - if (in_array($history_content['name'], $input_files)) { - continue; - } - - $has_any_results = TRUE; - - $step_content = []; - $step_content['history_content_' . $history_content['id'] . '_' . $index] = [ - '#type' => 'fieldset', - '#title' => $history_content['name'], - '#collapsed' => TRUE, - '#collapsible' => TRUE, - '#attributes' => [ - 'class' => ['collapsible', 'collapsed'], - ], - '#attached' => [ - 'js' => [ - 'misc/collapse.js', - 'misc/form.js', - ], - ], - ]; - - // If this is a file add viewing and download links - if ($history_content['type'] == 'file') { - if (!isset($history_content['content_link'])) { - break; - } - - // If this is an HTML file then add a view link. - if ($history_content['extension'] == 'html') { - $dataset_id = $history_content['id']; - $dataset = tripal_galaxy_get_dataset($submission, $dataset_id); - $proxy_url = tripal_galaxy_get_proxy_url($submission, $dataset, $node->uid, 'viewer-full'); - $step_content['history_content_' . $history_content['id'] . '_' . $index]['html_view'] = [ - '#type' => 'item', - '#title' => t('View report'), - '#markup' => l($history_content['name'], $proxy_url, ['attributes' => ['target' => '_blank']]), - ]; - } - // If this is not an HTML file then provide link to view the file - // unless it exceeds 1MB. If Galaxy provides a peek then show that. - else { - $link = $history_content['content_link']; - $dataset_id = $history_content['id']; - $dataset = tripal_galaxy_get_dataset($submission, $dataset_id); - $proxy_url = tripal_galaxy_get_proxy_url($submission, $dataset, $node->uid, 'download'); - $file_size = tripal_format_bytes($history_content['file_size']); - $step_content['history_content_' . $history_content['id'] . '_' . $index]['download_link'] = [ - '#type' => 'item', - '#title' => t('Download File'), - '#markup' => l($history_content['name'], $proxy_url) . ' (' . $file_size . ')', - ]; - - // Any files that are smaller than 1MB can be shown in a browser. - if ($history_content['file_size'] < pow(10, 6)) { - // SPF: originally this was $history_content['dataset_id'] but for - // some reason that value seems off for v17.09 as it does not - // point to the correct dataset. Rather the 'id' does. However, - // in v18.01 it seems fixed and both 'id' and 'dataset_id' are the - // same. - $dataset_id = $history_content['id']; - $dataset = tripal_galaxy_get_dataset($submission, $dataset_id); - $proxy_url = tripal_galaxy_get_proxy_url($submission, $dataset, $node->uid, 'viewer-full'); - $step_content['history_content_' . $history_content['id'] . '_' . $index]['html_view'] = [ - '#type' => 'item', - '#title' => t('View File'), - '#markup' => l($history_content['name'], $proxy_url, ['attributes' => ['target' => '_blank']] ), - ]; - } - - // Provide a peek if one is provided. - if ($history_content['peek'] != NULL) { - $step_content['history_content_' . $history_content['id'] . '_' . $index]['peek'] = [ - '#type' => 'item', - '#title' => 'Peek', - '#description' => 'A short view of the first few lines of the output file.', - '#markup' => '
' . $history_content['peek'] . '
', - ]; - } - } - } // End switch ($history_content['extension']) { ... - // end foreach ($history_contents as $index => $history_content) { ... - $content['history_content_' . $history_content['id'] . '_' . $index] = $step_content['history_content_' . $history_content['id'] . '_' . $index]; - } - } - } - - if (count($errors) > 0) { - $content['errors']['table'] = [ - '#type' => 'markup', - '#markup' => theme_table([ - 'header' => $headers, - 'rows' => $errors, - 'attributes' => [ - 'class' => 'tripal-galaxy-error-table' - ], - 'sticky' => FALSE, - 'caption' => '', - 'colgroups' => [], - 'empty' => '', - ]), - ]; - } - else { - unset($content['errors']); - } - - if ($has_any_results) { - $content['results'] = [ - '#type' => 'item', - '#title' => t('Result Files'), - '#markup' => t('The result files are listed below. Click the filename to view or download results. Expand the field for the result below to - view the status, peek or download result files.'), - ]; - } - else { - $content['results'] = [ - '#type' => 'item', - '#title' => t('Results'), - '#markup' => t('Currently, no results exist for this job. The current state of the job is: %state.', [ - '%state' => $submission->status, - ]), - ]; - } - - - - return $content; -} /** * Retrieves the workflow submission report for an admin user. @@ -1780,211 +1372,7 @@ function tripal_galaxy_handle_uploaded_file($file, $type) { list ($id, $form_key) = explode('-', $type); } -/** - * Retrieves content from a Galaxy URL and stream it back. - * - * @param string $proxy_id - * A unique ID that maps to a URL. - */ -function tripal_galaxy_stream_url_proxy(string $proxy_id) { - // Get the current proxy details, so we can map links for download. - $cproxy = $_SESSION['tripal_galaxy_proxy_urls'][$proxy_id]; - $dataset = $cproxy['dataset']; - $uid = $cproxy['uid']; - $sid = $cproxy['sid']; - - // retrieve the pertinents needed to download the file. - $submission = tripal_galaxy_get_submission($sid); - $galaxy_id = $submission->workflow->galaxy_id; - $galaxy = tripal_galaxy_get_connection($galaxy_id); - $dataset_id = $dataset['id']; - - $url = $galaxy->getURL() . $dataset['download_url']; - - return tripal_galaxy_stream_url_proxy_url($url); -} - -/** - * Retrieves content from a Galaxy URL and stream it back. - * - * @param string $url - * A valid URL on the remote Galaxy server. - */ -function tripal_galaxy_stream_url_proxy_url(string $url) { - $headers = get_headers($url); - $ch = curl_init(); - - curl_setopt($ch, CURLOPT_URL, $url); - curl_setopt($ch, CURLOPT_RETURNTRANSFER, TRUE); - $output = curl_exec($ch); - if ($output === FALSE) { - $error_msg = curl_error($ch); - $this->error->setError('HTTP', $error_msg); - return $error_msg; - } - curl_close($ch); - - if (!$output) { - $output = 'The remote Galaxy server returns no display.'; - } - return $output; -} - -/** - * A generic full page for viewing content from Galaxy. - * - * @param string $proxy_id - * A unique proxy ID that maps to a URL. - */ -function tripal_galaxy_stream_link_proxy(string $proxy_id) { - if (array_key_exists($proxy_id, $_SESSION['tripal_galaxy_proxy_urls'])) { - - // Get the current proxy details, so we can map links for download. - $cproxy = $_SESSION['tripal_galaxy_proxy_urls'][$proxy_id]; - $dataset = $cproxy['dataset']; - $uid = $cproxy['uid']; - $sid = $cproxy['sid']; - - // retrieve the pertinents needed to download the file. - $submission = tripal_galaxy_get_submission($sid); - $galaxy_id = $submission->workflow->galaxy_id; - $galaxy = tripal_galaxy_get_connection($galaxy_id); - $dataset_id = $dataset['id']; - - $url = $galaxy->getURL() . $dataset['download_url']; - $headers = get_headers($url); - foreach ($headers as $header) { - $results = preg_split('/:/', $header, 2); - if (count($results) == 2) { - drupal_add_http_header($results[0], $results[1]); - } - } - print tripal_galaxy_stream_url_proxy_url($url); - - exit(); - } - else { - $content['name'] = [ - '#type' => 'markup', - '#markup' => t('This page has expired. Please reload the job results page for uploaded links.'), - ]; - return $content; - } -} - -/** - * A generic full page for viewing content from Galaxy. - * - * @param string $proxy_id - * A unique proxy ID that maps to a URL. - */ -function tripal_galaxy_results_viewer_full_page(string $proxy_id) { - if (array_key_exists($proxy_id, $_SESSION['tripal_galaxy_proxy_urls'])) { - $content = tripal_galaxy_stream_url_proxy($proxy_id); - - // Replace relative URLs to have the proxy. - $url = url('galaxy/link/' . $proxy_id); - $content = preg_replace('/href\s*=\s*[\'"](?!\s*http)(.*?)[\'"]/', 'href=' . $url . '?url=\1', $content); - return $content; - } - else { - $content['name'] = [ - '#type' => 'markup', - '#markup' => t('This link has expired. Please reload the job results page for uploaded links.'), - ]; - return $content; - } -} - -/** - * A generic page for viewing content from Galaxy. - * - * @param string $proxy_id - * A unique proxy ID that maps to a URL. - */ -function tripal_galaxy_results_viewer_page(string $proxy_id) { - if (array_key_exists($proxy_id, $_SESSION['tripal_galaxy_proxy_urls'])) { - - // Get the current proxy details, so we can map links for download. - $cproxy = $_SESSION['tripal_galaxy_proxy_urls'][$proxy_id]; - $dataset = $cproxy['dataset']; - $uid = $cproxy['uid']; - $sid = $cproxy['sid']; - - $user = user_load($uid); - - // Set the breadcrumb. - $breadcrumb = []; - $breadcrumb[] = l(t('Home'), ''); - $breadcrumb[] = l($user->name, 'user/' . $uid); - $breadcrumb[] = l(t('Analyses'), 'user/' . $uid . 'galaxy-jobs'); - $breadcrumb[] = l(t('Analysis Results'), 'user/' . $uid . '/galaxy-jobs/' . $sid); - drupal_set_breadcrumb($breadcrumb); - - // retrieve the pertinents needed to download the file. - $submission = tripal_galaxy_get_submission($sid); - $galaxy_id = $submission->workflow->galaxy_id; - $galaxy = tripal_galaxy_get_connection($galaxy_id); - $dataset_id = $dataset['id']; - $name = $dataset['name']; - - $content['sub_title'] = [ - '#type' => 'markup', - '#markup' => '

Viewing results for ' . $name . '

', - ]; - $content['name'] = [ - '#type' => 'markup', - '#markup' => l(t('View full screen'), 'galaxy/viewer-full/' . $proxy_id), - ]; - $content['viewer'] = [ - '#type' => 'item', - '#markup' => '', - ]; - - return $content; - } - else { - $content['name'] = [ - '#type' => 'markup', - '#markup' => t('This link has expired. Please reload the job results page for uploaded links.'), - ]; - return $content; - } -} - -/** - * A generic callback for downloading content from Galaxy. - * - * @param string $proxy_id - * A unique proxy ID that maps to a URL. - */ -function tripal_galaxy_results_download(string $proxy_id) { - - // Get the current proxy details, so we can map links for download. - $cproxy = $_SESSION['tripal_galaxy_proxy_urls'][$proxy_id]; - $dataset = $cproxy['dataset']; - $uid = $cproxy['uid']; - $sid = $cproxy['sid']; - - // retrieve the pertinents needed to download the file. - $submission = tripal_galaxy_get_submission($sid); - $galaxy_id = $submission->workflow->galaxy_id; - $galaxy = tripal_galaxy_get_connection($galaxy_id); - $dataset_id = $dataset['id']; - - $url = $galaxy->getURL() . $dataset['download_url']; - $headers = get_headers($url); - foreach ($headers as $header) { - $results = preg_split('/:/', $header, 2); - if (count($results) == 2) { - drupal_add_http_header($results[0], $results[1]); - } - } - print tripal_galaxy_stream_url_proxy($proxy_id); - - exit(); -} /** * Exports a Galaxy workflow webform.