Open Data Catalog v2.0.0
WebServiceApiDocs.php
Go to the documentation of this file.
1 <?php
2 
3 namespace Drupal\dkan_metastore;
4 
7 use Symfony\Component\DependencyInjection\ContainerInterface;
8 use Drupal\Core\DependencyInjection\ContainerInjectionInterface;
9 use Drupal\dkan_common\JsonResponseTrait;
12 
16 class WebServiceApiDocs implements ContainerInjectionInterface {
17  use JsonResponseTrait;
19 
28  private $endpointsToKeep = [
29  'metastore/schemas/dataset/items/{identifier}' => ['get'],
30  'datastore/sql' => ['get'],
31  ];
32 
38  private $docsController;
39 
45  private $metastoreService;
46 
50  public static function create(ContainerInterface $container) {
51  return new WebServiceApiDocs(
52  $container->get("dkan_api.docs"),
53  $container->get("dkan_metastore.service"),
54  $container->get('plugin.manager.dkan_common.data_modifier')
55  );
56  }
57 
68  public function __construct(Docs $docsController, Service $metastoreService, DataModifierManager $pluginManager) {
69  $this->docsController = $docsController;
70  $this->metastoreService = $metastoreService;
71  $this->pluginManager = $pluginManager;
72 
73  $this->plugins = $this->discover();
74  }
75 
85  public function getDatasetSpecific(string $identifier) {
86  $fullSpec = $this->docsController->getJsonFromYmlFile();
87 
88  // Remove the security schemes.
89  unset($fullSpec['components']['securitySchemes']);
90 
91  // Tags can be added later when needed, remove them for now.
92  $fullSpec['tags'] = [];
93 
94  $pathsAndOperations = $fullSpec['paths'];
95  $pathsAndOperations = $this->keepDatasetSpecificEndpoints($pathsAndOperations);
96  $pathsAndOperations = $this->modifyDatasetEndpoints($pathsAndOperations, $identifier);
97  $pathsAndOperations = $this->modifySqlEndpoints($pathsAndOperations, $identifier, $fullSpec['components']['parameters']);
98 
99  $fullSpec['paths'] = $pathsAndOperations;
100  return $this->getResponse($fullSpec);
101  }
102 
112  private function keepDatasetSpecificEndpoints(array $pathsAndOperations) {
113  $keepPaths = array_keys($this->endpointsToKeep);
114 
115  $paths = array_keys($pathsAndOperations);
116 
117  $pathsToKeepPaths = array_combine($paths, array_map(function ($path) use ($keepPaths) {
118  foreach ($keepPaths as $keepPath) {
119  if (substr_count($path, $keepPath) > 0 && substr_count($path, $keepPath . "/") == 0) {
120  return $keepPath;
121  }
122  }
123  return NULL;
124  }, $paths));
125 
126  foreach ($pathsAndOperations as $path => $operations) {
127  if (is_null($pathsToKeepPaths[$path])) {
128  unset($pathsAndOperations[$path]);
129  }
130  else {
131  $pathsAndOperations[$path] = array_filter($operations, function ($operation) use ($path, $pathsToKeepPaths) {
132  return in_array($operation, $this->endpointsToKeep[$pathsToKeepPaths[$path]]);
133  }, ARRAY_FILTER_USE_KEY);
134  }
135  }
136 
137  return $pathsAndOperations;
138  }
139 
151  private function modifyDatasetEndpoints(array $pathsAndOperations, string $identifier) {
152 
153  foreach ($pathsAndOperations as $path => $operations) {
154  $newPath = $path;
155  $newOperations = $operations;
156  unset($pathsAndOperations[$path]);
157  [$newPath, $newOperations] = $this->modifyDatasetEndpoint($newPath, $newOperations, $identifier);
158  $pathsAndOperations[$newPath] = $newOperations;
159  }
160 
161  return $pathsAndOperations;
162  }
163 
167  private function modifyDatasetEndpoint($path, $operations, $identifier) {
168  $newOperations = $this->getModifyDatasetEndpointNewOperations($operations, $identifier);
169 
170  if (!isset($newOperations)) {
171  return [$path, $operations];
172  }
173 
174  $newPath = str_replace("{identifier}", $identifier, $path);;
175 
176  return [$newPath, $newOperations];
177  }
178 
182  private function getModifyDatasetEndpointNewOperations($operations, $identifier) {
183  $modified = FALSE;
184  foreach ($operations as $operation => $info) {
185  $newParameters = $this->getModifyDatasetEndpointNewParameters($info['parameters'], $identifier);
186  if ($newParameters) {
187  $operations[$operation]['parameters'] = $newParameters;
188  $modified = TRUE;
189  }
190  }
191 
192  return ($modified) ? $operations : NULL;
193  }
194 
198  private function getModifyDatasetEndpointNewParameters(array $parameters, $identifier): ?array {
199  $modified = FALSE;
200  foreach ($parameters as $key => $parameter) {
201  if (isset($parameter['name']) && $parameter['name'] == "identifier" && isset($parameter['example'])) {
202  $parameters[$key]['example'] = $identifier;
203  $modified = TRUE;
204  }
205  }
206  return ($modified) ? $parameters : NULL;
207  }
208 
222  private function modifySqlEndpoints(array $pathsAndOperations, string $identifier, array $parameters) {
223  if ($this->modifyData($identifier)) {
224  return $this->removeSqlEndpointPaths($pathsAndOperations);
225  }
226 
227  $query = $parameters['query'];
228 
229  foreach ($this->getSqlPathsAndOperations($pathsAndOperations) as $path => $operations) {
230 
231  foreach ($this->getDistributions($identifier) as $dist) {
232  list($newPath, $newOperations) = $this->modifySqlEndpoint($path, $operations, $dist, $query);
233  $pathsAndOperations[$newPath] = $newOperations;
234  }
235 
236  unset($pathsAndOperations[$path]);
237  }
238 
239  return $pathsAndOperations;
240  }
241 
245  private function getSqlPathsAndOperations($pathsAndOperations) {
246  foreach ($pathsAndOperations as $path => $operations) {
247  if (substr_count($path, 'sql') == 0) {
248  unset($pathsAndOperations[$path]);
249  }
250  }
251  return $pathsAndOperations;
252  }
253 
257  private function removeSqlEndpointPaths($pathsAndOperations) {
258  foreach ($pathsAndOperations as $path => $operations) {
259  if (substr_count($path, 'sql') > 0) {
260 
261  unset($pathsAndOperations[$path]);
262  }
263  }
264  return $pathsAndOperations;
265  }
266 
270  private function modifySqlEndpoint($path, $operations, $distribution, $query) {
271  $newPath = "{$path}?query=[SELECT * FROM {$distribution->identifier}];";
272 
273  $query['example'] = "[SELECT * FROM {$distribution->identifier}];";
274  $operations['get']['parameters'] = [$query];
275 
276  return [$newPath, $operations];
277  }
278 
290  private function modifyData(string $identifier) {
291  foreach ($this->plugins as $plugin) {
292  if ($plugin->requiresModification('distribution', $identifier)) {
293  return TRUE;
294  }
295  }
296  return FALSE;
297  }
298 
308  private function getDistributions(string $identifier) {
309  // Load this dataset's metadata with both data and identifiers.
310  if (function_exists('drupal_static')) {
311  drupal_static('dkan_data_dereference_method', Dereferencer::DEREFERENCE_OUTPUT_REFERENCE_IDS);
312  }
313 
314  $data = json_decode($this->metastoreService->get("dataset", $identifier));
315 
316  // Create and customize a path for each dataset distribution/resource.
317  if (isset($data->distribution)) {
318  return $data->distribution;
319  }
320  return [];
321  }
322 
323 }
Drupal\dkan_metastore
Drupal\dkan_data\Reference\Dereferencer\DEREFERENCE_OUTPUT_REFERENCE_IDS
const DEREFERENCE_OUTPUT_REFERENCE_IDS
Definition: Dereferencer.php:29
Drupal\dkan_common\DataModifierPluginTrait
trait DataModifierPluginTrait
Definition: DataModifierPluginTrait.php:8
Drupal\dkan_metastore\WebServiceApiDocs\__construct
__construct(Docs $docsController, Service $metastoreService, DataModifierManager $pluginManager)
Definition: WebServiceApiDocs.php:68
Drupal\dkan_api\Controller\Docs
Definition: Docs.php:17
Drupal\dkan_metastore\WebServiceApiDocs\create
static create(ContainerInterface $container)
Definition: WebServiceApiDocs.php:50
Drupal\dkan_common\Plugin\DataModifierManager
Definition: DataModifierManager.php:12
Drupal\dkan_metastore\Service
Definition: Service.php:20
Drupal\dkan_metastore\WebServiceApiDocs
Definition: WebServiceApiDocs.php:16
Drupal\dkan_metastore\WebServiceApiDocs\getDatasetSpecific
getDatasetSpecific(string $identifier)
Definition: WebServiceApiDocs.php:85
Drupal\dkan_data\Reference\Dereferencer
Definition: Dereferencer.php:13