Open Data Catalog v
DatasetApiDocs.php
Go to the documentation of this file.
1 <?php
2 
3 namespace Drupal\metastore;
4 
7 use Drupal\Core\Site\Settings;
8 
13 
14  const SPEC_PARAMETERS = [
15  'datasetUuid',
16  'showReferenceIds',
17  'datastoreDistributionUuid',
18  'datastoreQueryProperties',
19  'datastoreQueryConditions',
20  'datastoreQueryLimit',
21  'datastoreQueryOffset',
22  'datastoreQuerySorts',
23  'datastoreQueryCount',
24  'datastoreQueryResults',
25  'datastoreQuerySchema',
26  'datastoreQueryKeys',
27  'datastoreQueryFormat',
28  'datastoreQueryRowIds',
29  'datastoreDatasetUuid',
30  'datastoreDistributionIndex',
31  ];
32 
33  const SPEC_SCHEMAS = [
34  'dataset',
35  'errorResponse',
36  'datastoreResourceQuery',
37  'datastoreQueryResource',
38  'datastoreQueryProperty',
39  'datastoreQueryExpression',
40  'datastoreQueryCondition',
41  'datastoreQueryConditionGroup',
42  'datastoreQuerySort',
43  'datastoreQueryResourceProperty',
44  'datastoreQuery',
45 
46  ];
47 
48  const SPEC_RESPONSES = [
49  '404IdNotFound',
50  '200JsonOrCsvQueryOk',
51  '400BadJson',
52  ];
53 
59  private $docsGenerator;
60 
66  private $metastore;
67 
73  private Settings $settings;
74 
85  public function __construct(DkanApiDocsGenerator $docsGenerator, Service $metastore, Settings $settings) {
86  $this->docsGenerator = $docsGenerator;
87  $this->metastore = $metastore;
88  $this->settings = $settings;
89  }
90 
100  public function getDatasetSpecific(string $identifier) {
101  $specs = ['metastore_api_docs', 'datastore_api_docs'];
102  $fullSpec = $this->docsGenerator->buildSpec($specs)->{"$"};
103 
104  $datasetSpec = [
105  'openapi' => $fullSpec['openapi'],
106  'info' => $fullSpec['info'],
107  ];
108 
109  $metastorePath = $fullSpec['paths']['/api/1/metastore/schemas/dataset/items/{identifier}']['get'];
110  unset($metastorePath['parameters'][0]);
111  $metastorePath['parameters'] = array_values($metastorePath['parameters']);
112  $datasetSpec['paths']["/api/1/metastore/schemas/dataset/items/$identifier"]['get'] = $metastorePath;
113 
114  $datasetSpec['paths']["/api/1/datastore/query/$identifier/{index}"]
115  = $this->getDatastoreIndexPath($fullSpec, $identifier);
116 
117  $datasetSpec['paths']['/api/1/datastore/query/{distributionId}'] =
118  $fullSpec['paths']['/api/1/datastore/query/{distributionId}'];
119 
120  $datasetSpec['paths']['/api/1/datastore/sql'] =
121  $fullSpec['paths']['/api/1/datastore/sql'];
122 
123  $datasetSpec['components'] = $this->datasetSpecificComponents($fullSpec, $identifier);
124 
125  $this->alterDatastoreParameters($datasetSpec, $identifier);
126  $this->modifySqlEndpoints($datasetSpec, $identifier);
127  if ($dkanApiBase = $this->settings->get('dkan_api_base')) {
128  $datasetSpec = ApiDocsPathModifier::prepend($datasetSpec, $dkanApiBase);
129  }
130 
131  return $datasetSpec;
132  }
133 
145  private function datasetSpecificComponents($fullSpec, $identifier) {
146  $components = [];
147  $components['parameters'] =
148  $this->datasetSpecificParameters($fullSpec['components']['parameters'], $identifier);
149  $components['schemas'] =
150  $this->datasetSpecificSchemas($fullSpec['components']['schemas']);
151  $components['responses'] =
152  $this->datasetSpecificResponses($fullSpec['components']['responses']);
153 
154  return $components;
155  }
156 
168  private function getDatastoreIndexPath($fullSpec, $identifier) {
169  $datastoreIndexPath = $fullSpec['paths']['/api/1/datastore/query/{datasetId}/{index}'];
170  unset($datastoreIndexPath['get']['parameters'][0]);
171  $datastoreIndexPath['get']['parameters'] = array_values($datastoreIndexPath['get']['parameters']);
172  unset($datastoreIndexPath['post']['parameters'][0]);
173  $datastoreIndexPath['post']['parameters'] = array_values($datastoreIndexPath['post']['parameters']);
174  return $datastoreIndexPath;
175  }
176 
186  private function datasetSpecificSchemas(array $schemas) {
187  $newSchemas = array_filter($schemas, function ($key) {
188  if (in_array($key, self::SPEC_SCHEMAS)) {
189  return TRUE;
190  }
191  return FALSE;
192  }, ARRAY_FILTER_USE_KEY);
193  return $newSchemas;
194  }
195 
207  private function datasetSpecificParameters(array $parameters, $identifier) {
208  $newParameters = array_filter($parameters, function ($key) {
209  if (in_array($key, self::SPEC_PARAMETERS)) {
210  return TRUE;
211  }
212  return FALSE;
213  }, ARRAY_FILTER_USE_KEY);
214  $newParameters['datasetUuid']['example'] = $identifier;
215  return $newParameters;
216  }
217 
227  private function datasetSpecificResponses(array $responses) {
228  $newResponses = array_filter($responses, function ($key) {
229  if (in_array($key, self::SPEC_RESPONSES)) {
230  return TRUE;
231  }
232  return FALSE;
233  }, ARRAY_FILTER_USE_KEY);
234  return $newResponses;
235  }
236 
245  private function alterDatastoreParameters(array &$spec, string $identifier) {
246  $spec['components']['parameters']['datastoreDatasetUuid']['example'] = $identifier;
247  foreach ($this->getDistributions($identifier) as $index => $dist) {
248  unset($spec['components']['parameters']['datastoreDistributionUuid']['example']);
249  $spec['components']['parameters']['datastoreDistributionUuid']['examples'][$dist['identifier']] = [
250  'value' => $dist['identifier'],
251  'summary' => $dist["data"]["title"] ?? $dist['identifier'],
252  ];
253  unset($spec['components']['parameters']['datastoreDistributionIndex']['example']);
254  $spec['components']['parameters']['datastoreDistributionIndex']['examples']["index{$index}"] = [
255  'value' => "$index",
256  'summary' => $dist["data"]["title"] ?? $dist['identifier'],
257  ];
258  }
259  }
260 
269  private function modifySqlEndpoints(array &$spec, string $identifier) {
270 
271  foreach ($this->getSqlPathsAndOperations($spec['paths']) as $path => $operations) {
272  foreach ($this->getDistributions($identifier) as $dist) {
273  $newOperations = $this->modifySqlEndpoint($operations, $dist);
274  $spec['paths'][$path] = $newOperations;
275  }
276  }
277  }
278 
282  private function getSqlPathsAndOperations($pathsAndOperations) {
283  foreach (array_keys($pathsAndOperations) as $path) {
284  if (substr_count($path, 'sql') == 0) {
285  unset($pathsAndOperations[$path]);
286  }
287  }
288  return $pathsAndOperations;
289  }
290 
294  private function modifySqlEndpoint($operations, $distribution) {
295  $distKey = isset($distribution['data']['title']) ? $distribution['data']['title'] : $distribution['identifier'];
296  unset($operations['get']['parameters'][0]['example']);
297  $operations['get']['parameters'][0]['examples'][$distKey] = [
298  "summary" => "Query distribution {$distribution['identifier']}",
299  "value" => "[SELECT * FROM {$distribution['identifier']}][LIMIT 2]",
300  ];
301  return $operations;
302  }
303 
313  private function getDistributions(string $identifier) {
314 
315  $data = $this->metastore->swapReferences($this->metastore->get("dataset", $identifier));
316 
317  return $data->{"$.distribution"} ?? [];
318  }
319 
320 }
Drupal\metastore
Drupal\metastore\Service
Definition: Service.php:21
Drupal\metastore\DatasetApiDocs\SPEC_PARAMETERS
const SPEC_PARAMETERS
Definition: DatasetApiDocs.php:14
Drupal\metastore\DatasetApiDocs\SPEC_SCHEMAS
const SPEC_SCHEMAS
Definition: DatasetApiDocs.php:33
Drupal\metastore\DatasetApiDocs\getDatasetSpecific
getDatasetSpecific(string $identifier)
Definition: DatasetApiDocs.php:100
Drupal\common\Util\ApiDocsPathModifier
Definition: ApiDocsPathModifier.php:8
Drupal\common\DkanApiDocsGenerator
Definition: DkanApiDocsGenerator.php:13
Drupal\common\Util\ApiDocsPathModifier\prepend
static prepend(array $spec, string $pathFragment)
Definition: ApiDocsPathModifier.php:21
Drupal\metastore\DatasetApiDocs\SPEC_RESPONSES
const SPEC_RESPONSES
Definition: DatasetApiDocs.php:48
Drupal\metastore\DatasetApiDocs
Definition: DatasetApiDocs.php:12
Drupal\metastore\DatasetApiDocs\__construct
__construct(DkanApiDocsGenerator $docsGenerator, Service $metastore, Settings $settings)
Definition: DatasetApiDocs.php:85