public function SpecFetcher::fetchSpec in Apigee API Catalog 8.2
Same name and namespace in other branches
- 8 src/SpecFetcher.php \Drupal\apigee_api_catalog\SpecFetcher::fetchSpec()
Fetch OpenAPI specification file from URL.
Takes care of updating an ApiDoc file entity with the updated spec file. If "spec_file_source" uses a URL, it will fetch the specified file and put it in the "spec" file field. If it uses a "file", it won't change it. This method only updates the file entity if it completed without error (if it returns STATUS_UPDATED or STATUS_UNCHANGED), it does not save the ApiDoc entity.
Parameters
\Drupal\node\NodeInterface $apidoc: The ApiDoc entity.
Return value
string Returns the status of the operation. If it is STATUS_UPDATED or STATUS_UNCHANGED, the ApiDoc entity will need to be saved to store the changes.
Overrides SpecFetcherInterface::fetchSpec
File
- src/
SpecFetcher.php, line 102
Class
- SpecFetcher
- Class SpecFetcher.
Namespace
Drupal\apigee_api_catalogCode
public function fetchSpec(NodeInterface $apidoc) : string {
$spec_value = $apidoc
->get('field_apidoc_spec')
->isEmpty() ? [] : $apidoc
->get('field_apidoc_spec')
->getValue()[0];
// If "spec_file_source" uses URL, grab file from "file_link" and save it
// into the "spec" file field. The file_link field should already have
// validated that a valid file exists at that URL.
if ($apidoc
->get('field_apidoc_spec_file_source')->value === static::SPEC_AS_URL) {
// If the file_link field is empty, return without changes.
// TODO: The file link shouldn't be empty. Consider throwing an error.
if ($apidoc
->get('field_apidoc_file_link')
->isEmpty()) {
return FALSE;
}
$source_uri = $apidoc
->get('field_apidoc_file_link')
->getValue()[0]['uri'];
$source_uri = Url::fromUri($source_uri, [
'absolute' => TRUE,
])
->toString();
$request = new Request('GET', $source_uri);
$options = [
'exceptions' => TRUE,
'allow_redirects' => [
'strict' => TRUE,
],
];
// Generate conditional GET header.
if (!$apidoc
->get('field_apidoc_fetched_timestamp')
->isEmpty()) {
$request = $request
->withAddedHeader('If-Modified-Since', gmdate(DateTimePlus::RFC7231, $apidoc
->get('field_apidoc_fetched_timestamp')->value));
}
try {
$response = $this->httpClient
->send($request, $options);
} catch (GuzzleException $e) {
$this
->log(LogLevel::ERROR, 'API Doc %label: Could not retrieve OpenAPI specification file located at %url.', [
'%url' => $source_uri,
'%label' => $apidoc
->label(),
]);
return self::STATUS_ERROR;
}
// In case of a 304 Not Modified there are no changes, but update
// last fetched timestamp.
if ($response
->getStatusCode() === 304) {
$apidoc
->set('field_apidoc_fetched_timestamp', time());
return self::STATUS_UNCHANGED;
}
$data = (string) $response
->getBody();
if (($file_size = $response
->getBody()
->getSize()) && $file_size < 1) {
$this
->log(LogLevel::ERROR, 'API Doc %label: OpenAPI specification file located at %url is empty.', [
'%url' => $source_uri,
'%label' => $apidoc
->label(),
]);
return self::STATUS_ERROR;
}
// Only save file if it hasn't been fetched previously.
$data_md5 = md5($data);
$prev_md5 = $apidoc
->get('field_apidoc_spec_md5')
->isEmpty() ? NULL : $apidoc
->get('field_apidoc_spec_md5')->value;
if ($prev_md5 == $data_md5) {
// Files are the same, only update fetched timestamp.
$apidoc
->set('field_apidoc_fetched_timestamp', time());
return self::STATUS_UNCHANGED;
}
else {
$filename = $this->fileSystem
->basename($source_uri);
$specs_definition = $apidoc
->getFieldDefinition('field_apidoc_spec')
->getItemDefinition();
$target_dir = $specs_definition
->getSetting('file_directory');
$uri_scheme = $specs_definition
->getSetting('uri_scheme');
$destination = "{$uri_scheme}://{$target_dir}/";
try {
$this
->checkRequirements($destination);
$file = file_save_data($data, $destination . $filename, FileSystemInterface::EXISTS_RENAME);
if (empty($file)) {
throw new \Exception('Could not save API Doc specification file.');
}
} catch (\Exception $e) {
$this
->log(LogLevel::ERROR, 'Error while saving API Doc spec file from URL on API Doc ID: %id. Error: %error', [
'%id' => $apidoc
->id(),
'%error' => $e
->getMessage(),
]);
return self::STATUS_ERROR;
}
$spec_value = [
'target_id' => $file
->id(),
] + $spec_value;
$apidoc
->set('field_apidoc_spec', $spec_value);
$apidoc
->set('field_apidoc_spec_md5', $data_md5);
$apidoc
->set('field_apidoc_fetched_timestamp', time());
return self::STATUS_UPDATED;
}
}
return self::STATUS_UNCHANGED;
}