Skip to content

Commit

Permalink
Merge pull request #129 from esmero/ISSUE-124
Browse files Browse the repository at this point in the history
ISSUE-127 and ISSUE-128: adds snac + better draft session management when editing/cloning
  • Loading branch information
DiegoPino authored Aug 23, 2021
2 parents 0cf60f0 + 0786dc8 commit 2d498fe
Show file tree
Hide file tree
Showing 11 changed files with 824 additions and 45 deletions.
1 change: 1 addition & 0 deletions .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -16,3 +16,4 @@
src/Tools/Iiif/IiifHelper.php
.idea/webform_strawberryfield.iml
src/.DS_Store
.idea/runConfigurations/archipelago.xml
1 change: 1 addition & 0 deletions composer.json
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,7 @@
],
"require": {
"php": ">=7.2",
"ext-json": "*",
"ml/json-ld": "^1.2",
"mtdowling/jmespath.php":"^2.5",
"strawberryfield/strawberryfield":"dev-1.0.0-RC3",
Expand Down
221 changes: 208 additions & 13 deletions src/Controller/AuthAutocompleteController.php
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,7 @@
use GuzzleHttp\Client;
use GuzzleHttp\Exception\ClientException;
use GuzzleHttp\Exception\ServerException;
use GuzzleHttp\RequestOptions;
use Drupal\Component\Utility\UrlHelper;
use Drupal\Core\Url;
use Drupal\Component\Datetime\TimeInterface;
Expand Down Expand Up @@ -163,6 +164,9 @@ public function handleAutocomplete(Request $request, $auth_type, $vocab = 'subje
if (is_string($csrf_token)) {
$request_base = $request->getSchemeAndHttpHost().':'.$request->getPort();
$is_internal = $_SERVER['REQUEST_SCHEME'].'://'.$_SERVER['SERVER_ADDR'].':'.$_SERVER['SERVER_PORT'] == $request_base;
if (!$is_internal) {
$is_internal = $_SERVER['HTTP_HOST'] == $_SERVER['SERVER_NAME'];
}
}

if ($input) {
Expand All @@ -173,10 +177,9 @@ public function handleAutocomplete(Request $request, $auth_type, $vocab = 'subje
$cache_id = 'webform_strawberry:auth_lod:' . $cache_var;
$cached = $this->cacheGet($cache_id);
if ($cached) {
error_log('cached');
return new JsonResponse($cached->data);
}
if ($this->currentUser->isAnonymous() && !$is_internal) {
if ($this->currentUser->isAnonymous() && !$is_internal) {
sleep(1);
}

Expand All @@ -197,9 +200,15 @@ public function handleAutocomplete(Request $request, $auth_type, $vocab = 'subje
case 'viaf':
$results = $this->viaf($input);
break;
case 'mesh':
$results = $this->mesh($input, $vocab, $rdftype);
break;
case 'snac':
$results = $this->snac($input, $vocab, $rdftype);
break;
case 'europeana':
if ($apikey) {
$results = $this->europeana($input, $vocab, $apikey);
$results = $this->europeana($input, $vocab, $apikey);
}
else {
$this->messenger()->addError(
Expand Down Expand Up @@ -273,7 +282,7 @@ protected function loc($input, $vocab, $rdftype) {
];
$path = $endpoint[$vocab];

$input = urlencode($input);
$input = rawurlencode($input);

if ($vocab == 'rdftype') {
$urlindex = "/suggest/?q=" . $input . "&rdftype=" . $rdftype;
Expand Down Expand Up @@ -327,7 +336,7 @@ protected function loc($input, $vocab, $rdftype) {
* @return array
*/
protected function wikidata($input) {
$input = urlencode($input);
$input = rawurlencode($input);
$urlindex = '&language=en&format=json&search=' . $input;
$baseurl = 'https://www.wikidata.org/w/api.php?action=wbsearchentities';
$remoteUrl = $baseurl . $urlindex;
Expand Down Expand Up @@ -602,7 +611,7 @@ protected function getty($input, $vocab = 'aat', $mode = 'fuzzy') {
* @return array
*/
protected function viaf($input) {
$input = urlencode($input);
$input = rawurlencode($input);
$urlindex = '&query=' . $input;
$baseurl = 'https://viaf.org/viaf/AutoSuggest?';
$remoteUrl = $baseurl . $urlindex;
Expand All @@ -612,12 +621,12 @@ protected function viaf($input) {

$jsondata = [];
$results = [];
$jsondata = json_decode($body, TRUE);
$jsondata = json_decode($body, TRUE) ?? [];
$json_error = json_last_error();
if ($json_error == JSON_ERROR_NONE) {
//WIKIdata will give is an success key will always return at least one, the query string
if (count($jsondata) > 1) {
if (count($jsondata['result']) >= 1) {
if (isset($jsondata['result']) && is_array($jsondata['result']) && count($jsondata['result']) >= 1) {
foreach ($jsondata['result'] as $key => $item) {
$desc = (isset($item['nametype'])) ? '(' . $item['nametype'] . ')' : NULL;
$results[] = [
Expand Down Expand Up @@ -681,7 +690,7 @@ protected function europeana($input, $vocab, string $apikey) {
return $results;
}

$input = urlencode($input);
$input = rawurlencode($input);

$urlindex = "/suggest?text=" . $input . "&type=" . $vocab ."&wskey=". $apikey ;

Expand Down Expand Up @@ -729,7 +738,7 @@ protected function europeana($input, $vocab, string $apikey) {
}

if (($vocab == 'agent') && isset($result['dateOfBirth'])) {
$desc[] = $result['dateOfBirth'] . '/' . $result['dateOfDeath'] ?? '?';
$desc[] = $result['dateOfBirth'] . '/' . $result['dateOfDeath'] ?? '?';
}

$desc = !empty($desc) ? ' (' . implode(', ', $desc) . ')' : NULL;
Expand Down Expand Up @@ -761,14 +770,189 @@ protected function europeana($input, $vocab, string $apikey) {
return [];
}

/**
* @param $input
* The query
* @param $vocab
* The 'suggest' enabled endpoint at LoC
*
* @return array
*/
protected function snac($input, $vocab, $rdftype) {
//@TODO make the following allowed list a constant since we use it in
// \Drupal\webform_strawberryfield\Plugin\WebformElement\WebformLoC
if (!in_array($vocab, [
'Constellation',
'rdftype',
])) {
// Drop before tryin to hit non existing vocab
$this->messenger()->addError(
$this->t('@vocab for SNAC autocomplete is not in in our allowed list.',
[
'@vocab' => $vocab,
]
)
);
$results[] = [
'value' => NULL,
'label' => "Wrong Vocabulary {$vocab} in SNAC Query",
];
return $results;
}


$input = urlencode($input);


$remoteUrl = "https://api.snaccooperative.org";
$options = [
'body' => json_encode([
"command" => "search",
"term" => $input,
"entity_type" => $rdftype != "thing" ? $rdftype : NULL,
"start" => 0,
"count" => 10,
"search_type" => "autocomplete",
]),
RequestOptions::HEADERS => [
'Content-Type' => 'application/json'
]
];
$body = $this->getRemoteJsonData($remoteUrl, $options, 'PUT');

$jsondata = [];
$results = [];
$jsondata = json_decode($body, TRUE);
$json_error = json_last_error();
if ($json_error == JSON_ERROR_NONE) {
if (!empty($jsondata['results']) && ($jsondata['total'] ?? 0) >= 1) {
foreach ($jsondata['results'] as $key => $entry) {
$nameEntry = reset($entry['nameEntries']);
$results[] = [
'value' => $entry['ark'] ?? $entry['entityType']['uri'],
'label' => $nameEntry['original'],
];
}
}
else {
$results[] = [
'value' => NULL,
'label' => "Sorry no match from SNAC {$vocab}",
];
}
return $results;
}
$this->messenger()->addError(
$this->t('Looks like data fetched from @url is not in JSON format.<br> JSON says: @jsonerror <br>Please check your URL!',
[
'@url' => $remoteUrl,
'@jsonerror' => $json_error,
]
)
);
return [];
}



/**
* @param $input
* The query
* @param $vocab
* The 'suggest' enabled endpoint at LoC
*
* @return array
*/
protected function mesh($input, $vocab, $rdftype) {

//@TODO make the following allowed list a constant since we use it in
// \Drupal\webform_strawberryfield\Plugin\WebformElement\WebformMesh
if (!in_array($vocab, [
'descriptor',
'term',
])) {
// Drop before tryin to hit non existing vocab
$this->messenger()->addError(
$this->t('@vocab for MeSH autocomplete is not in in our allowed list.',
[
'@vocab' => $vocab,
]
)
);
$results[] = [
'value' => NULL,
'label' => "Wrong Vocabulary {$vocab} in MeSH API Query",
];
return $results;
}

// Here $rdftype acts as match
if (!in_array($rdftype, [
'startswith',
'contains',
'exact',
])) {
// Drop before tryin to hit non existing vocab
$this->messenger()->addError(
$this->t('@rdftype Match type for MeSH autocomplete is not valid. It may be "exact","startswith" or "contains"',
[
'@rdftype' => $rdftype,
]
)
);
$results[] = [
'value' => NULL,
'label' => "Wrong Match type for {$vocab} in MeSH API Query",
];
return $results;
}

$input = rawurlencode($input);
$urlindex = "/mesh/lookup/{$vocab}?label=" . $input .'&limit=10&match=' . $rdftype;
$baseurl = 'https://id.nlm.nih.gov';
$remoteUrl = $baseurl . $urlindex;
$options['headers'] = ['Accept' => 'application/json'];
$body = $this->getRemoteJsonData($remoteUrl, $options);

$results = [];
$jsondata = json_decode($body, TRUE);
$json_error = json_last_error();
if ($json_error == JSON_ERROR_NONE) {
if (count($jsondata) > 1) {
foreach ($jsondata as $entry) {
$results[] = [
'value' => $entry['resource'],
'label' => $entry['label'],
];
}
}
else {
$results[] = [
'value' => NULL,
'label' => "Sorry no match from MeSH for {$vocab}",
];
}
return $results;
}
$this->messenger()->addError(
$this->t('Looks like data fetched from @url is not in JSON format.<br> JSON says: @jsonerror <br>Please check your URL!',
[
'@url' => $remoteUrl,
'@jsonerror' => $json_error,
]
)
);
return [];
}

/**
* @param $remoteUrl
* @param $options
*
* @return string
* A string that may be JSON (hopefully)
*/
protected function getRemoteJsonData($remoteUrl, $options) {
protected function getRemoteJsonData($remoteUrl, $options, $method = 'GET') {
// This is expensive, reason why we process and store in cache
if (empty($remoteUrl)) {
// No need to alarm. all good. If not URL just return.
Expand All @@ -783,7 +967,18 @@ protected function getRemoteJsonData($remoteUrl, $options) {
return NULL;
}
try {
$request = $this->httpClient->get($remoteUrl, $options);
if ($method == 'GET') {
$request = $this->httpClient->get($remoteUrl, $options);
}
elseif ($method == 'POST') {
$request = $this->httpClient->post($remoteUrl, $options);
}
elseif ($method == 'PUT') {
$request = $this->httpClient->put($remoteUrl, $options);
}
else {
return NULL;
}
// Do not cache if things go bad.
if ($request->getStatusCode() == '401') {
$this->setNotAllowed(TRUE);
Expand Down Expand Up @@ -816,7 +1011,7 @@ protected function getRemoteJsonData($remoteUrl, $options) {
catch (ServerException $exception) {
$this->useCaches = FALSE;
$responseMessage = $exception->getMessage();
$this->loggerFactory->get('webform_strawberryfield')
$this->getLogger('webform_strawberryfield')
->error('We tried to contact @url but we could not. <br> The Remote server says: @response. <br> Check your query',
[
'@url' => $remoteUrl,
Expand Down
7 changes: 4 additions & 3 deletions src/Controller/StrawberryRunnerModalController.php
Original file line number Diff line number Diff line change
Expand Up @@ -138,17 +138,18 @@ public function openModalForm(WebformInterface $webform = NULL, Request $request
// In case we are editing an existing entity, this one gets the
// Strawberryfield value
$alldata = $source_entity->get($field_name)->getValue();
$fielddata['value'] = !empty($alldata) ? $alldata[$delta]['value']: "{}";
$fielddata['value'] = $alldata[$delta]['value'] ?? "{}";
$entityid = $source_entity->id();
}

$stored_value = (isset($fielddata['value']) && !empty($fielddata['value'])) ? $fielddata['value'] : "{}";
$stored_value = $fielddata['value'] ?? "{}";

$data_defaults = [
'strawberry_field_widget_state_id' => $widgetid,
// Can't remember why, but seems useful to pass around
'strawberry_field_widget_source_entity_uuid' => $source_uuid,
'strawberry_field_widget_source_entity_id' => $entityid,
'strawberry_field_widget_autosave' => $entityid ? FALSE : TRUE,
'strawberry_field_stored_values' => json_decode($stored_value,true)
];

Expand Down Expand Up @@ -247,7 +248,7 @@ public function openModalForm(WebformInterface $webform = NULL, Request $request
// We delete both, the session and the accumulated errors.
/** @var \Drupal\Core\TempStore\PrivateTempStore $tempstore */
$tempstore = \Drupal::service('tempstore.private')->get('archipel');
$tempstore->delete($clear_saved);
$tempstore->delete($clear_saved.'-draft');
$tempstore->delete($clear_saved.'-errors');
// Selector us built using the field name and the delta.
$response->addCommand(new \Drupal\Core\Ajax\HtmlCommand('#' . $selector .' > .fieldset-wrapper',
Expand Down
Loading

0 comments on commit 2d498fe

Please sign in to comment.