Skip to content

Commit

Permalink
Data modifier plugin and behavior enhancements for non-public datasets (
Browse files Browse the repository at this point in the history
  • Loading branch information
thierrydallacroce authored and fmizzell committed Jan 10, 2020
1 parent 649fbc5 commit 8e44495
Show file tree
Hide file tree
Showing 17 changed files with 899 additions and 31 deletions.
11 changes: 7 additions & 4 deletions modules/custom/dkan_common/dkan_common.services.yml
Original file line number Diff line number Diff line change
@@ -1,5 +1,8 @@
services:
dkan.factory:
class: Drupal\dkan_common\Service\Factory
dkan.json_util:
class: Drupal\dkan_common\Service\JsonUtil
dkan.factory:
class: Drupal\dkan_common\Service\Factory
dkan.json_util:
class: Drupal\dkan_common\Service\JsonUtil
plugin.manager.dkan_common.data_modifier:
class: \Drupal\dkan_common\Plugin\DataModifierManager
parent: default_plugin_manager
48 changes: 48 additions & 0 deletions modules/custom/dkan_common/src/Annotation/DataModifier.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,48 @@
<?php

namespace Drupal\dkan_common\Annotation;

use Drupal\Component\Annotation\Plugin;

/**
* Annotation for data modifier plugins.
*
* @see plugin_api
*
* @Annotation
*/
class DataModifier extends Plugin {

/**
* The plugin ID.
*
* @var string
*/
public $id;

/**
* The label of the plugin.
*
* @var \Drupal\Core\Annotation\Translation
*
* @ingroup plugin_translatable
*/
public $label;

/**
* Communicate the plugin's effect on the modified data.
*
* @var \Drupal\Core\Annotation\Translation
*
* @ingroup plugin_translatable
*/
public $result;

/**
* HTTP code to include in response when modification has occured.
*
* @var int
*/
public $resultCode;

}
40 changes: 40 additions & 0 deletions modules/custom/dkan_common/src/DataModifierPluginTrait.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,40 @@
<?php

namespace Drupal\dkan_common;

/**
* Provides common functionality for alls data modifier plugins.
*/
trait DataModifierPluginTrait {

/**
* Data modifier plugin manager service.
*
* @var \Drupal\dkan_common\Plugin\DataModifierManager
*/
private $pluginManager;

/**
* Instances of discovered data modifier plugins.
*
* @var array
*/
private $plugins = [];

/**
* Discover data modifier plugins.
*
* @return array
* A list of discovered data modifier plugins.
*
* @throws \Drupal\Component\Plugin\Exception\PluginException
*/
private function discover() {
$plugins = [];
foreach ($this->pluginManager->getDefinitions() as $definition) {
$plugins[] = $this->pluginManager->createInstance($definition['id']);
}
return $plugins;
}

}
32 changes: 32 additions & 0 deletions modules/custom/dkan_common/src/Plugin/DataModifierBase.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,32 @@
<?php

namespace Drupal\dkan_common\Plugin;

use Drupal\Component\Plugin\PluginBase;

/**
* Defines an abstract base class for Data modifier plugins.
*/
abstract class DataModifierBase extends PluginBase implements DataModifierInterface {

/**
* Translate and render the result annotation.
*
* @return string
* A message explaining the outcome.
*/
public function message() : string {
return $this->getPluginDefinition()['result']->render();
}

/**
* Return the http code annotation.
*
* @return int
* The http code.
*/
public function httpCode() : int {
return (int) $this->getPluginDefinition()['code'];
}

}
60 changes: 60 additions & 0 deletions modules/custom/dkan_common/src/Plugin/DataModifierInterface.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,60 @@
<?php

namespace Drupal\dkan_common\Plugin;

use Drupal\Component\Plugin\PluginInspectionInterface;

/**
* Defines an interface for Data modifier plugins.
*
* Plugins of this type may have different conditions and outcomes, but all act
* on the following publicly accessible API endpoints:
* - The metastore's GET collection and GET item
* - The dataset-specific Api Docs
* - The datastore's SQL query.
*/
interface DataModifierInterface extends PluginInspectionInterface {

/**
* Checks if the schema or data needs modifying.
*
* @param string $schema
* The schema id.
* @param mixed $data
* The data object, json string or identifier.
*
* @return bool
* TRUE if the data requires modification, FALSE otherwise.
*/
public function requiresModification(string $schema, $data);

/**
* Modify data.
*
* @param string $schema
* The schema id.
* @param mixed $data
* The object, json string or identifier whose data needs modifying.
*
* @return mixed
* The modified data object, or FALSE.
*/
public function modify(string $schema, $data);

/**
* Translate and render the result annotation.
*
* @return string
* A message explaining the outcome.
*/
public function message() : string;

/**
* Return the http code annotation.
*
* @return int
* The http code.
*/
public function httpCode() : int;

}
42 changes: 42 additions & 0 deletions modules/custom/dkan_common/src/Plugin/DataModifierManager.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,42 @@
<?php

namespace Drupal\dkan_common\Plugin;

use Drupal\Core\Cache\CacheBackendInterface;
use Drupal\Core\Extension\ModuleHandlerInterface;
use Drupal\Core\Plugin\DefaultPluginManager;

/**
* Manages data modifier plugins.
*/
class DataModifierManager extends DefaultPluginManager {

/**
* Constructs a new DataModifierManager object.
*
* @param \Traversable $namespaces
* An object that implements \Traversable which contains the root paths
* keyed by the corresponding namespace to look for plugin implementations.
* @param \Drupal\Core\Cache\CacheBackendInterface $cache_backend
* Cache backend instance to use.
* @param \Drupal\Core\Extension\ModuleHandlerInterface $module_handler
* The module handler to invoke the alter hook with.
*/
public function __construct(
\Traversable $namespaces,
CacheBackendInterface $cache_backend,
ModuleHandlerInterface $module_handler
) {
parent::__construct(
'Plugin/DataModifier',
$namespaces,
$module_handler,
'Drupal\dkan_common\Plugin\DataModifierInterface',
'Drupal\dkan_common\Annotation\DataModifier'
);

$this->alterInfo('dkan_common_data_modifier_info');
$this->setCacheBackend($cache_backend, 'dkan_common_data_modifier_plugins');
}

}
Original file line number Diff line number Diff line change
@@ -0,0 +1,29 @@
<?php

namespace Drupal\dkan_common\Tests\Unit;

use Drupal\Core\Cache\MemoryBackend;
use Drupal\Core\Extension\ModuleHandler;
use Drupal\dkan_common\Plugin\DataModifierManager;
use PHPUnit\Framework\TestCase;

/**
* Unit tests for class DataModifierManager.
*
* @package Drupal\dkan_common\Tests\Unit
*/
class DataModifierManagerTest extends TestCase {

/**
* Test constructor.
*/
public function testDataModifierManager() {
$traversable = new \ArrayIterator();
$cache = new MemoryBackend();
$module = new ModuleHandler('blah', [], $cache);

$manager = new DataModifierManager($traversable, $cache, $module);
$this->assertTrue(is_object($manager));
}

}
2 changes: 2 additions & 0 deletions modules/custom/dkan_metastore/dkan_metastore.services.yml
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,8 @@ services:
arguments:
- '@dkan_schema.schema_retriever'
- '@dkan_metastore.sae_factory'
calls:
- [setDataModifierPlugins, ['@plugin.manager.dkan_common.data_modifier']]
dkan_metastore.sae_factory:
class: \Drupal\dkan_metastore\Factory\Sae
arguments:
Expand Down
48 changes: 46 additions & 2 deletions modules/custom/dkan_metastore/src/Service.php
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,8 @@

namespace Drupal\dkan_metastore;

use Drupal\dkan_common\DataModifierPluginTrait;
use Drupal\dkan_common\Plugin\DataModifierManager;
use Symfony\Component\DependencyInjection\ContainerInterface;
use Drupal\Core\DependencyInjection\ContainerInjectionInterface;
use Drupal\dkan_metastore\Factory\Sae;
Expand All @@ -14,6 +16,7 @@
* Service.
*/
class Service implements ContainerInjectionInterface {
use DataModifierPluginTrait;

/**
* SAE Factory.
Expand Down Expand Up @@ -49,6 +52,17 @@ public function __construct(SchemaRetriever $schemaRetriever, Sae $saeFactory) {
$this->saeFactory = $saeFactory;
}

/**
* Setter to discover data modifier plugins.
*
* @param \Drupal\dkan_common\Plugin\DataModifierManager $pluginManager
* Injected plugin manager.
*/
public function setDataModifierPlugins(DataModifierManager $pluginManager) {
$this->pluginManager = $pluginManager;
$this->plugins = $this->discover();
}

/**
* Get schemas.
*/
Expand Down Expand Up @@ -86,7 +100,10 @@ public function getAll($schema_id): array {

// $datasets is an array of JSON encoded string. Needs to be unflattened.
$unflattened = array_map(
function ($json_string) {
function ($json_string) use ($schema_id) {
if (!empty($this->plugins)) {
$json_string = $this->modifyData($schema_id, $json_string);
}
return json_decode($json_string);
},
$datasets
Expand All @@ -107,8 +124,35 @@ function ($json_string) {
* The json data.
*/
public function get($schema_id, $identifier): string {
return $this->getEngine($schema_id)
$data = $this->getEngine($schema_id)
->get($identifier);
if (!empty($this->plugins)) {
$data = $this->modifyData($schema_id, $data);
}
return $data;
}

/**
* Provides data modifiers plugins an opportunity to act.
*
* @param string $schema_id
* The {schema_id} slug from the HTTP request.
* @param string $data
* The Json input.
*
* @return string
* The Json, modified by each applicable discovered data modifier plugins.
*/
private function modifyData(string $schema_id, string $data) {
$dataObj = json_decode($data);

foreach ($this->plugins as $plugin) {
if ($plugin->requiresModification($schema_id, $dataObj)) {
$dataObj = $plugin->modify($schema_id, $dataObj);
}
}

return json_encode($dataObj);
}

/**
Expand Down
Loading

0 comments on commit 8e44495

Please sign in to comment.