'default_value',
];
/**
* @see TripalFieldFormatter::view()
*/
public function view(&$element, $entity_type, $entity, $langcode, $items, $display) {
$content = '';
// Get the settings
$settings = $display['settings'];
$field_name = $this->field['field_name'];
// Get any subfields and the header label. Shift the array because the
// results should already be the value of the first entry.
$rd_field_name = $this->instance['settings']['data_info']['rd_field_name'];
$subfields = explode(',', $rd_field_name);
$header_label = $this->getHeaderLabel($subfields);
$flabel = array_shift($subfields);
// Get the site logo if one is provided
$site_logo = $this->instance['settings']['data_info']['site_logo'];
if ($site_logo) {
$site_logo = file_load($site_logo);
}
// Get the site name where the data came from.
$site_id_ws = $this->instance['settings']['data_info']['remote_site'];
$site = db_select('tripal_sites', 'ts')
->fields('ts', ['name', 'url'])
->condition('ts.id', $site_id_ws)
->execute()
->fetchObject();
// Iterate through the results and create a generic table.
$rows = [];
$headers = [''];
foreach ($items as $index => $item) {
if (!$item['value'] or empty($item['value'])) {
continue;
}
$value = $item['value'];
$error = $item['error'];
$warning = $item['warning'];
// If there is an error or warning then clear the cache for this field
// so that next time the page is loaded it will try to reload again.
if ($error or $warning) {
$cid = "field:TripalEntity:" . $entity->id . ':' . $field_name;
cache_clear_all($cid, 'cache_field');
if ($item['admin_message']) {
$severity = TRIPAL_ERROR;
if ($warning) {
$severity = TRIPAL_WARNING;
}
$value .= tripal_set_message($item['admin_message'] . 'The query URL was: ' . l($item['query_str'], $item['query_str'], ['attributes' => ['target' => '_blank']]),
$severity, ['return_html' => TRUE]);
}
$rows[] = [$value];
continue;
}
$remote_entity_label = array_key_exists('label', $item) ? $item['remote_entity']['label'] : '';
$remote_entity_page = $item['remote_entity']['ItemPage'];
$remote_entity_link = t('View !data on %site',
[
'!data' => l('this data', $remote_entity_page, ['attributes' => ['target' => '_blank']]),
'%site' => $site->name,
]);
// If this is a collection then handle it as a list of members.
if (array_key_exists('members', $value)) {
foreach ($value['members'] as $subvalue) {
$subvalue = $this->refineSubValue($subvalue, $subfields, $header_label);
$rows[] = [$subvalue];
}
}
else {
if (count($subfields) > 0) {
$subvalue = $this->refineSubValue($value, $subfields, $header_label);
$rows[] = [$subvalue];
}
else {
if (array_key_exists($flabel, $value)) {
$rows[] = [$value[$flabel]];
}
else {
$value['Link'] = l('View content on ' . $site->name, $remote_entity_page, ['attributes' => ['target' => '_blank']]);
$rows[] = [$value];
}
}
}
}
// TODO: we need to handle paged elements.
$has_sub_tables = FALSE;
for ($i = 0; $i < count($rows); $i++) {
if (is_array($rows[$i][0])) {
$rows[$i][0] = $this->createTable($rows[$i]);
$has_sub_tables = TRUE;
}
else {
$rows[$i] = [
'colspan' => 2,
'data' => $rows[$i],
];
}
}
// If we don't have tables for each row then we'll put everything into
// a table.
if (!$has_sub_tables) {
$headers = [$header_label . '(s)'];
$content .= theme_table([
'header' => $headers,
'rows' => $rows,
'attributes' => [
'class' => 'tripal-remote--data-field-table',
],
'sticky' => FALSE,
'caption' => "",
'colgroups' => [],
'empty' => 'There are no results.',
]);
}
else {
for ($i = 0; $i < count($rows); $i++) {
if (count($rows) > 1) {
$content .= '' . $header_label . ' ' . ($i + 1) . '';
}
$content .= $rows[$i][0];
}
}
$content .= '
';
if ($site) {
$content .= t('This content provided by !site.', [
'!site' => l($site->name, $site->url,
['attributes' => ["target" => '_blank']]),
]);
}
else {
tripal_report_error('tripal_ws', TRIPAL_ERROR, 'Unable to find remote site while attempting to format results.');
}
if (is_object($site_logo)) {
$content .= '
';
}
if (count($items) == 1) {
$content .= isset($remote_entity_link) ? $remote_entity_link : '';
}
$content .= '
';
// Return the content for this field.
$element[0] = [
'#type' => 'markup',
'#markup' => '' . $content . '
',
];
}
/**
* Retrieves the header label given the subfields criteria.
*
* @param $subfields
* An array of the sequence of subfields.
*/
private function getHeaderLabel($subfields) {
$subfield = array_shift($subfields);
$header_label = ucwords(preg_replace('/_/', ' ', $subfield));
if (count($subfields) > 0) {
$header_label .= ' ' . $this->getHeaderLabel($subfields);
}
return $header_label;
}
/**
* Adjusts the items array to contain only the section/subsection desired.
*
* The field settings can indicate a field with sub fields that should
* be displayed (e.g. organism,genus or relationship,clause). We want
* to adjust the item to only include what the user requested.
*
* @param $values
* @param $subfields
*/
private function refineSubValue($values, $subfields) {
// Remove unwanted elements.
unset($values['@id']);
unset($values['@context']);
unset($values['@type']);
unset($values['remote_entity']);
$subfield = array_shift($subfields);
if (array_key_exists($subfield, $values)) {
if (is_array($values[$subfield]) and count($subfields) > 0) {
return $this->refineSubvalue($values[$subfield], $subfields);
}
else {
return $values[$subfield];
}
}
else {
return $values;
}
}
/**
* A recursive function for displaying an item in a table.
*
* @param $item
* An item from the $items array passed to the view() function.
*
* @return
* An HTML formatted Table.
*/
private function createTable($item, &$pkey = '', &$rows = [], $depth = 0) {
foreach ($item as $key => $value) {
// Skip JSON-LD keys.
if (preg_match('/^\@/', $key)) {
continue;
}
$key = preg_replace('/_/', ' ', $key);
$key = ucwords($key);
if ($pkey) {
$key = $pkey . ' ' . $key;
}
if (is_array($value)) {
$this->createTable($value, $key, $rows, $depth + 1);
}
else {
$rows[] = [
'data' => [
$key,
$value,
],
'no_striping' => TRUE,
];
}
}
if ($depth == 0) {
$headers = ['Data Type', 'Value'];
return theme_table([
'header' => $headers,
'rows' => $rows,
'attributes' => [
'class' => 'tripal-remote--data-field-table',
],
'sticky' => FALSE,
'caption' => "",
'colgroups' => [],
'empty' => 'There are no results.',
]);
}
}
/**
* A recursive function for creating an HTML dictionary list from
* the results for the item provided.
*
* @param $item
* An item from the $items array passed to the view() function.
*
* @return
* An HTML formatted DL.
*/
private function createDL($item, &$pkey = '', &$content = '', $depth = 0) {
if ($depth == 0) {
$content = '';
}
foreach ($item as $key => $value) {
// Skip JSON-LD keys.
if (preg_match('/^\@/', $key)) {
continue;
}
$key = preg_replace('/_/', ' ', $key);
$key = ucwords($key);
if ($pkey) {
$key = $pkey . ' ' . $key;
}
if (is_array($value)) {
$this->createDL($value, $key, $content, $depth + 1);
}
else {
$content .= '- ' . $key . ' :
- ' . $value . '
';
}
}
if ($depth == 0) {
$content .= '
';
return $content;
}
}
/**
* A recursive function for creating an HTML dictionary list from
* the results for the item provided.
*
* @param $item
* An item from the $items array passed to the view() function.
*
* @return
* An HTML formatted DL.
*/
private function createNestedDL($item) {
$content = '';
foreach ($item as $key => $value) {
// Skip JSON-LD keys.
if (preg_match('/^\@/', $key)) {
continue;
}
$key = preg_replace('/_/', ' ', $key);
$key = ucwords($key);
if (is_array($value)) {
$value = $this->createDL($value);
}
$content .= '- ' . $key . '
- ' . $value . '
';
}
$content .= '
';
return $content;
}
/**
* Provides a summary of the formatter settings.
*
* This function corresponds to the hook_field_formatter_settings_summary()
* function of the Drupal Field API.
*
* On the 'Manage Display' page of the content type administration page,
* fields are allowed to provide a settings form. This settings form can
* be used to allow the site admin to define how the field should be
* formatted. The settings are then available for the formatter()
* function of this class. This function provides a text-based description
* of the settings for the site developer to see. It appears on the manage
* display page inline with the field. A field must always return a
* value in this function if the settings form gear button is to appear.
*
* See the hook_field_formatter_settings_summary() function for more
* information.
*
* @param $field
* @param $instance
* @param $view_mode
*
* @return string
* A string that provides a very brief summary of the field settings
* to the user.
*
*/
public function settingsSummary($view_mode) {
}
}