Skip to content

Commit

Permalink
Merge pull request #178 from esmero/ISSUE-177
Browse files Browse the repository at this point in the history
ISSUE-177: LoD Autocomplete Fixes and Improvements
  • Loading branch information
DiegoPino committed Jun 24, 2024
2 parents d8b1be2 + c33d2ac commit 1affd7b
Show file tree
Hide file tree
Showing 10 changed files with 184 additions and 16 deletions.
62 changes: 62 additions & 0 deletions js/metadataauth-webform_strawberryfield.js
Original file line number Diff line number Diff line change
Expand Up @@ -64,7 +64,69 @@
return settings;
};

/**
* Overrides Drupal.autocomplete.options.source so we can avoid the opinionated cache
*/

Drupal.autocomplete.options.source = function sourceData(request, response) {
const elementId = this.element.attr('id');
var options = Drupal.autocomplete.options;
const is_sbf = this.element.data('strawberry-autocomplete');

if (!(elementId in Drupal.autocomplete.cache)) {
Drupal.autocomplete.cache[elementId] = {};
}

/**
* Filter through the suggestions removing all terms already tagged and
* display the available terms to the user.
*
* @param {object} suggestions
* Suggestions returned by the server.
*/
function showSuggestions(suggestions) {
const tagged = Drupal.autocomplete.splitValues(request.term);
const il = tagged.length;
for (let i = 0; i < il; i++) {
const index = suggestions.indexOf(tagged[i]);
if (index >= 0) {
suggestions.splice(index, 1);
}
}
response(suggestions);
}

// Get the desired term and construct the autocomplete URL for it.
const term = Drupal.autocomplete.extractLastTerm(request.term);

/**
* Transforms the data object into an array and update autocomplete results.
*
* @param {object} data
* The data sent back from the server.
*/
function sourceCallbackHandler(data) {
if (!is_sbf) {
Drupal.autocomplete.cache[elementId][term] = data;
}

// Send the new string array of terms to the jQuery UI list.
showSuggestions(data);
}

// Check if the term is already cached.
if (Drupal.autocomplete.cache[elementId].hasOwnProperty(term) && !is_sbf) {
showSuggestions(Drupal.autocomplete.cache[elementId][term]);
} else {
const options = $.extend(
{ success: sourceCallbackHandler, data: { q: term } },
Drupal.autocomplete.ajax,
);
$.ajax(this.element.attr('data-autocomplete-path'), options);
}
}

/**
* Overrides Drupal.autocomplete.options.search for no splitting of terms
*
* This is the only function where even is present, means we can decide per instance
Expand Down
56 changes: 41 additions & 15 deletions src/Controller/RowAutocompleteController.php
Original file line number Diff line number Diff line change
Expand Up @@ -67,23 +67,30 @@ public static function create(ContainerInterface $container) {
* Filters against Labels
*
*/
public function handleAutocomplete(Request $request, ContentEntityInterface $node, $label_header, $url_header) {
public function handleAutocomplete(Request $request, ContentEntityInterface $node, $label_header, $url_header, $match = 'STARTS_WITH', $limit = 10, $min = 2, $desc_headers = NULL) {
$results = [];
$input = $request->query->get('q');
$input = Xss::filter($input);
$label_header = strtolower($label_header);
$url_header = strtolower($url_header);

$desc_headers = strtolower($desc_headers);
$desc_headers_exploded = [];
$desc_headers_indexes = [];
// Find a CSV file in this ADO.
// Get the typed string from the URL, if it exists.
if (!$input) {
if (!$input && strlen(trim($input)) < $min) {
return new JsonResponse($results);
}
if (is_string($desc_headers)) {
$desc_headers_exploded = explode(',', $desc_headers);
$desc_headers_exploded = array_slice($desc_headers_exploded, 0, 2);
}

$file = null;
if ($sbf_fields = \Drupal::service('strawberryfield.utility')->bearsStrawberryfield($node)) {
$files = $node->get('field_file_drop')->getValue();
foreach($files as $offset => $fileinfo) {
/** @var \Drupal\file\FileInterface $file|null */
foreach ($files as $offset => $fileinfo) {
/** @var \Drupal\file\FileInterface $file |null */
$file = $this->entityTypeManager
->getStorage('file')
->load($fileinfo['target_id']);
Expand All @@ -97,18 +104,37 @@ public function handleAutocomplete(Request $request, ContentEntityInterface $nod
$column_keys = $file_data_all['headers'] ?? [];
$label_original_index = array_search($label_header, $column_keys);
$url_original_index = array_search($url_header, $column_keys);
foreach ($desc_headers_exploded as $desc_header) {
$index = array_search($desc_header, $column_keys);
if ($index!== FALSE) {
$desc_headers_indexes[] = $index;
}
}

$i = 0;
if ($label_original_index !== FALSE && $url_original_index !== FALSE ) {
if ($label_original_index !== FALSE && $url_original_index !== FALSE) {
foreach ($file_data_all['data'] as $id => &$row) {
if (isset($row[$label_original_index]) && stripos($row[$label_original_index], $input) === 0) {
$i++;

$results[] = [
'value' => $row[$url_original_index],
'label' => $row[$label_original_index],
];
if ($i == 10) {
break;
if (isset($row[$label_original_index])) {
if (($match == 'STARTS_WITH' && stripos($row[$label_original_index], $input) === 0) || ($match == 'CONTAINS' && stripos($row[$label_original_index], $input) !== FALSE)) {
$i++;
$desc = [];
$desc_string = '';
foreach ($desc_headers_indexes as $desc_header_index) {
$desc[] = $row[$desc_header_index];
}
$desc = array_filter($desc);
if (count($desc)) {
$desc_string = implode('|', $desc);
}
$desc_string = ($desc_string !== '') ? '(' . $desc_string . ')' : NULL;
$results[] = [
'value' => $row[$url_original_index],
'label' => $row[$label_original_index].' '.$desc_string,
'desc' => $desc_string
];
if ($i == $limit) {
break;
}
}
}
}
Expand Down
9 changes: 9 additions & 0 deletions src/Plugin/WebformElement/WebformEuropeana.php
Original file line number Diff line number Diff line change
Expand Up @@ -84,6 +84,15 @@ protected function prepareMultipleWrapper(array &$element) {
'count' => 10
];
}
elseif (isset($element['#webform_multiple']) && $element['#webform_multiple'] == FALSE && isset($element['#webform_composite_elements']['label'])) {
$element['#webform_composite_elements']['label']["#autocomplete_route_parameters"] =
[
'auth_type' => 'europeana',
'vocab' => $vocab,
'rdftype' => $rdftype,
'count' => 10
];
}
// For some reason i can not understand, when multiples are using
// Tables, the #webform_composite_elements -> 'label' is not used...
if (isset($element["#multiple__header"]) && $element["#multiple__header"] == true) {
Expand Down
10 changes: 10 additions & 0 deletions src/Plugin/WebformElement/WebformGetty.php
Original file line number Diff line number Diff line change
Expand Up @@ -78,6 +78,16 @@ protected function prepareMultipleWrapper(array &$element) {
'count' => 10
];
}
elseif (isset($element['#webform_multiple']) && $element['#webform_multiple'] == FALSE && isset($element['#webform_composite_elements']['label'])) {
$element['#webform_composite_elements']['label']["#autocomplete_route_parameters"] =
[
'auth_type' => 'getty',
'vocab' => $vocab,
'rdftype' => $matchtype,
'count' => 10
];
}

// For some reason i can not understand, when multiples are using
// Tables, the #webform_composite_elements -> 'label' is not used...
if (isset($element["#multiple__header"]) && $element["#multiple__header"] == true) {
Expand Down
9 changes: 9 additions & 0 deletions src/Plugin/WebformElement/WebformLoC.php
Original file line number Diff line number Diff line change
Expand Up @@ -90,6 +90,15 @@ protected function prepareMultipleWrapper(array &$element) {
'count' => 10
];
}
elseif (isset($element['#webform_multiple']) && $element['#webform_multiple'] == FALSE && isset($element['#webform_composite_elements']['label'])) {
$element['#webform_composite_elements']['label']["#autocomplete_route_parameters"] =
[
'auth_type' => 'loc',
'vocab' => $vocab,
'rdftype' => $rdftype,
'count' => 10
];
}
// For some reason i can not understand, when multiples are using
// Tables, the #webform_composite_elements -> 'label' is not used...
if (isset($element["#multiple__header"]) && $element["#multiple__header"] == true) {
Expand Down
25 changes: 25 additions & 0 deletions src/Plugin/WebformElement/WebformLoDfromCSV.php
Original file line number Diff line number Diff line change
Expand Up @@ -41,6 +41,7 @@ protected function defineDefaultProperties() {
'autocomplete_match' => 3,
'autocomplete_label_header' => 'label',
'autocomplete_url_header' => 'url',
'autocomplete_desc_headers' => '',
'autocomplete_match_operator' => 'CONTAINS',
] + parent::defineDefaultProperties()
+ $this->defineDefaultMultipleProperties();
Expand All @@ -62,10 +63,24 @@ public function prepare(

if (isset($element['#webform_key'])) {
$element['#autocomplete_route_name'] = 'webform_strawberryfield.rowsbylabel.autocomplete';
$desc = $element['#autocomplete_desc_headers'] ?? $properties['autocomplete_desc_headers'];
if (is_string($desc) && strlen(trim($desc)) > 0 ) {
$desc = explode(',', $desc);
$desc = array_slice($desc, 0, 2);
$desc = array_map('trim', $desc);
$desc = implode(',', $desc);
}
else {
$desc = '';
}
$element['#autocomplete_route_parameters'] = [
'node' => $element['#autocomplete_items'],
'label_header' => $element['#autocomplete_label_header'] ?? $properties['autocomplete_label_header'],
'url_header' => $element['#autocomplete_url_header'] ?? $properties['autocomplete_url_header'],
'match' => $element['#autocomplete_match_operator'] ?? $properties['autocomplete_match_operator'],
'limit' => $element['#autocomplete_limit'] ?? $properties['autocomplete_limit'],
'min' => $element['#autocomplete_match'] ?? $properties['autocomplete_match'],
'desc_headers' => $desc,
];
}
}
Expand All @@ -85,6 +100,11 @@ protected function prepareMultipleWrapper(array &$element) {
$element['#element']['#webform_composite_elements']['label']['#autocomplete_route_name'] = $autocomplete_route;
$element['#element']['#webform_composite_elements']['label']['#autocomplete_route_parameters'] = $autocomplete_route_params;
}
elseif (isset($element['#webform_multiple']) && $element['#webform_multiple'] == FALSE && isset($element['#webform_composite_elements']['label'])) {
// Not a multiple one. So assign the Autocomplete route directly to the composite children.
$element['#webform_composite_elements']['label']['#autocomplete_route_name'] = $autocomplete_route;
$element['#webform_composite_elements']['label']['#autocomplete_route_parameters'] = $autocomplete_route_params;
}

// For some reason i can not understand, when multiples are using
// Tables, the #webform_composite_elements -> 'label' is not used...
Expand Down Expand Up @@ -153,6 +173,11 @@ public function form(array $form, FormStateInterface $form_state) {
'#title' => $this->t('The CSV column(header name) that will be used for the URL value'),
'#required' => TRUE,
];
$form['autocomplete']['autocomplete_desc_headers'] = [
'#type' => 'textfield',
'#title' => $this->t('The CSV columns(header names), separated by a comma, that will be used for additional context/description. Leave empty if not used. It has a limited of 2 headers. Any extra ones will be ignored.'),
'#required' => FALSE,
];
$form['autocomplete']['autocomplete_limit'] = [
'#type' => 'number',
'#title' => $this->t('Autocomplete limit'),
Expand Down
5 changes: 5 additions & 0 deletions src/Plugin/WebformElement/WebformLoDfromOptions.php
Original file line number Diff line number Diff line change
Expand Up @@ -80,6 +80,11 @@ protected function prepareMultipleWrapper(array &$element) {
$element['#element']['#webform_composite_elements']['label']['#autocomplete_route_name'] = $autocomplete_route;
$element['#element']['#webform_composite_elements']['label']['#autocomplete_route_parameters'] = $autocomplete_route_params;
}
elseif (isset($element['#webform_multiple']) && $element['#webform_multiple'] == FALSE && isset($element['#webform_composite_elements']['label'])) {
// Not a multiple one. So assign the Autocomplete route directly to the composite children.
$element['#webform_composite_elements']['label']['#autocomplete_route_name'] = $autocomplete_route;
$element['#webform_composite_elements']['label']['#autocomplete_route_parameters'] = $autocomplete_route_params;
}

// For some reason i can not understand, when multiples are using
// Tables, the #webform_composite_elements -> 'label' is not used...
Expand Down
9 changes: 9 additions & 0 deletions src/Plugin/WebformElement/WebformMesh.php
Original file line number Diff line number Diff line change
Expand Up @@ -84,6 +84,15 @@ protected function prepareMultipleWrapper(array &$element) {
'count' => 10
];
}
elseif (isset($element['#webform_multiple']) && $element['#webform_multiple'] == FALSE && isset($element['#webform_composite_elements']['label'])) {
$element['#webform_composite_elements']['label']["#autocomplete_route_parameters"] =
[
'auth_type' => 'mesh',
'vocab' => $vocab,
'rdftype' => $matchtype,
'count' => 10
];
}
// For some reason i can not understand, when multiples are using
// Tables, the #webform_composite_elements -> 'label' is not used...
if (isset($element["#multiple__header"]) && $element["#multiple__header"] == true) {
Expand Down
9 changes: 9 additions & 0 deletions src/Plugin/WebformElement/WebformSnac.php
Original file line number Diff line number Diff line change
Expand Up @@ -90,6 +90,15 @@ protected function prepareMultipleWrapper(array &$element) {
'count' => 10
];
}
elseif (isset($element['#webform_multiple']) && $element['#webform_multiple'] == FALSE && isset($element['#webform_composite_elements']['label'])) {
$element['#webform_composite_elements']['label']["#autocomplete_route_parameters"] =
[
'auth_type' => 'snac',
'vocab' => $vocab,
'rdftype' => $rdftype,
'count' => 10
];
}
// For some reason i can not understand, when multiples are using
// Tables, the #webform_composite_elements -> 'label' is not used...
if (isset($element["#multiple__header"]) && $element["#multiple__header"] == true) {
Expand Down
6 changes: 5 additions & 1 deletion webform_strawberryfield.routing.yml
Original file line number Diff line number Diff line change
Expand Up @@ -60,7 +60,7 @@ webform_strawberryfield.element.autocomplete:
_entity_access: 'webform.submission_create'

webform_strawberryfield.rowsbylabel.autocomplete:
path: '/webform_strawberry/csv_autocomplete/{node}/{label_header}/{url_header}'
path: '/webform_strawberry/csv_autocomplete/{node}/{label_header}/{url_header}/{match}/{limit}/{min}/{desc_headers}'
options:
parameters:
node:
Expand All @@ -70,6 +70,10 @@ webform_strawberryfield.rowsbylabel.autocomplete:
defaults:
label_header: 'label'
url_header: 'url'
match: 'STARTS_WITH'
limit: 10
min: 2
desc_headers: ''
_controller: '\Drupal\webform_strawberryfield\Controller\RowAutocompleteController::handleAutocomplete'
_format: json
requirements:
Expand Down

0 comments on commit 1affd7b

Please sign in to comment.