Skip to content

Commit

Permalink
Fix Drupal 10 compatibility issues.
Browse files Browse the repository at this point in the history
  • Loading branch information
lem-doghouse committed Sep 26, 2023
1 parent cc44ae1 commit 6e7104a
Show file tree
Hide file tree
Showing 6 changed files with 208 additions and 17 deletions.
9 changes: 5 additions & 4 deletions README.md
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
# CKAN Connect

CKAN connect is a [Drupal 8/9](https://www.drupal.org/project/ckan_connect) companion module for the
CKAN connect is a [Drupal 8/9/10](https://www.drupal.org/project/ckan_connect) companion module for the
[Data Visualisation Framework (DVF)](https://github.com/govCMS/dvf) module. Its goal is to provide
[CKAN](https://ckan.org/) connectivity and abstract API calls. Other modules can use CKAN connect
if they need CKAN connectivity from Drupal and it does not require DVF to function.
Expand Down Expand Up @@ -35,7 +35,7 @@ Once installed you must set the Base URL for the CKAN instance.
* Set the API url to match your CKAN instance eg. `https://data.gov.au/api/3`
* If you need write access to CKAN or you need to view private datasets then you can also
add an API key. Note the security implications here, you could potentially expose private
data on your Drupal site when an API key is used
data on your Drupal site when an API key is used.

## CKAN Connect API

Expand Down Expand Up @@ -92,8 +92,9 @@ but we also monitor the [Drupal issue queue](https://www.drupal.org/project/ckan

## Contributing and extending CKAN Connect

We welcome (and appreciate) improvements and fixes to CKAN Connect, so if you have something to add
please submit a [Github pull request](https://github.com/govCMS/ckan_connect/pulls).
We welcome (and appreciate) improvements and fixes to CKAN Connect, so if you
have something to add please submit a
[Github pull request](https://github.com/govCMS/ckan_connect/pulls).

## Supporting organizations

Expand Down
2 changes: 1 addition & 1 deletion ckan_connect.info.yml
Original file line number Diff line number Diff line change
Expand Up @@ -2,4 +2,4 @@ name: CKAN Connect
description: 'Connect to a CKAN endpoint providing a wrapper around the CKAN Action API.'
type: module
package: CKAN
core_version_requirement: ^8 || ^9
core_version_requirement: ^9 || ^10
60 changes: 48 additions & 12 deletions src/Form/CkanConnectSettingsForm.php
Original file line number Diff line number Diff line change
Expand Up @@ -2,16 +2,44 @@

namespace Drupal\ckan_connect\Form;

use Drupal\Core\Config\ConfigFactoryInterface;
use Drupal\Core\Form\ConfigFormBase;
use Drupal\Core\Form\FormStateInterface;
use Drupal\Core\StreamWrapper\StreamWrapperManager;
use GuzzleHttp\Exception\RequestException;
use Symfony\Component\DependencyInjection\ContainerInterface;
use Drupal\ckan_connect\Client\CkanClientInterface;

/**
* Configures CKAN Connect settings for this site.
*/
class CkanConnectSettingsForm extends ConfigFormBase {

/**
* The ckan client.
*
* @var \Drupal\ckan_connect\Client\CkanClientInterface
*/
protected $ckanClient;

/**
* {@inheritdoc}
*/
public function __construct(ConfigFactoryInterface $config_factory, CkanClientInterface $ckanClient) {
parent::__construct($config_factory);
$this->ckanClient = $ckanClient;
}

/**
* {@inheritdoc}
*/
public static function create(ContainerInterface $container) {
return new static(
$container->get('config.factory'),
$container->get('ckan_connect.client')
);
}

/**
* {@inheritdoc}
*/
Expand Down Expand Up @@ -48,8 +76,8 @@ public function buildForm(array $form, FormStateInterface $form_state) {

$form['api']['key'] = [
'#type' => 'textfield',
'#title' => t('API Key'),
'#description' => t('Optionally specify an API key.'),
'#title' => $this->t('API Key'),
'#description' => $this->t('Optionally specify an API key.'),
'#default_value' => $config->get('api.key'),
];

Expand All @@ -73,13 +101,16 @@ public function validateForm(array &$form, FormStateInterface $form_state) {
* @param \Drupal\Core\Form\FormStateInterface $form_state
* The form state.
*/
protected function validateApiUrl(array &$form, FormStateInterface $form_state) {
public function validateApiUrl(array &$form, FormStateInterface $form_state) {
$api_url = $form_state->getValue(['api', 'url']);
$api_key = $form_state->getValue(['api', 'key']);

if (!empty($api_key)) {
if (StreamWrapperManager::getScheme($api_url) !== 'https') {
$form_state->setErrorByName('api_url', $this->t('If using an API key, the API URL must use HTTPS.'));
$message = $this->t('If using an API key, the API URL must use HTTPS.');

$this->logger('ckan_connect')->error($message);
$form_state->setErrorByName('api_url', $message);
}
}
}
Expand All @@ -92,36 +123,41 @@ protected function validateApiUrl(array &$form, FormStateInterface $form_state)
* @param \Drupal\Core\Form\FormStateInterface $form_state
* The form state.
*/
protected function validateApiKey(array &$form, FormStateInterface $form_state) {
public function validateApiKey(array &$form, FormStateInterface $form_state) {
$api_url = $form_state->getValue(['api', 'url']);
$api_key = $form_state->getValue(['api', 'key']);

try {
/** @var \Drupal\ckan_connect\Client\CkanClientInterface $client */
$client = \Drupal::service('ckan_connect.client');
$client->setApiUrl($api_url);
$this->ckanClient->setApiUrl($api_url);

if ($api_key) {
$client
$this->ckanClient
->setApiKey($api_key)
->get('action/dashboard_activity_list', ['limit' => 1]);
}
else {
$client->get('action/site_read');
$this->ckanClient->get('action/site_read');
}
}
catch (RequestException $e) {
$response = $e->getResponse();
$status_code = $response->getStatusCode();
$message = '';

switch ($status_code) {
case 403:
$form_state->setErrorByName('api_url', $this->t('API return "Not Authorised" please check your API key.'));
$message = $this->t('API return "Not Authorised" please check your API key.');
$form_state->setErrorByName('api_url', $message);
break;

default:
$form_state->setErrorByName('api_url', $this->t('Could not establish a connection to the endpoint. Error: @code', ['@code' => $status_code]));
$message = $this->t('Could not establish a connection to the endpoint. Error: @code', ['@code' => $status_code]);
$form_state->setErrorByName('api_url', $message);
}

$this->logger('ckan_connect')->error("$message @message", [
'@message' => $e->getMessage(),
]);
}
}

Expand Down
2 changes: 2 additions & 0 deletions src/Parser/CkanResourceUrlParser.php
Original file line number Diff line number Diff line change
Expand Up @@ -50,6 +50,8 @@ public function __construct(CkanClientInterface $ckan_client, LoggerInterface $l
public function parse($url) {
if (!preg_match(self::CKAN_RESOURCE_PATH_REGEX, $url, $matches)) {
if (empty($matches[1])) {
$this->logger->error("Invalid resource path. The url $url MUST contain either a resource/ or resource_id=.");

return FALSE;
}
}
Expand Down
93 changes: 93 additions & 0 deletions tests/src/Functional/CkanConnectSettingsFormTest.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,93 @@
<?php

namespace Drupal\Tests\ckan_connect\Unit\Form;

use Drupal\Tests\BrowserTestBase;

/**
* Tests the CkanConnectSettingsForm class.
*
* @group ckan_connect
*/
class CkanConnectSettingsFormTest extends BrowserTestBase {

/**
* Modules to enable during test setup.
*
* @var array
*/
protected static $modules = [
'ckan_connect',
'user',
];

/**
* User with proper permissions for module configuration.
*
* @var \Drupal\user\Entity\User|false
*/
protected $adminUser;

/**
* Theme for tests relying on no markup at all or at least no core markup.
*
* @var string
*/
protected $defaultTheme = 'stark';

/**
* The ckan url.
*
* @var string
*/
protected $ckanUrl = 'https://data.gov.au/data/api/3';

/**
* The ckan connect admin config url.
*
* @var string
*/
protected $adminConfigUrl = '/admin/config/services/ckan-connect';

/**
* {@inheritdoc}
*/
public function setUp(): void {
parent::setUp();
$this->adminUser = $this->drupalCreateUser([
'administer site configuration',
'administer ckan connect',
]);

$this->drupalLogin($this->adminUser);
$this->drupalGet($this->adminConfigUrl);
$this->assertSession()->statusCodeEquals(200);
}

/**
* Test that the correct form fields in the admin config exists.
*/
public function testCkanConfigForm() {
// Checked that the config fields exist.
$this->assertSession()->pageTextContains("Optionally specify an API key.");
$this->assertSession()->pageTextContains("Specify the endpoint URL. Example https://data.gov.au/api/3 (please note no trailing slash).");
$this->assertSession()->fieldExists("api[url]");
$this->assertSession()->fieldExists("api[key]");
}

/**
* Test that the config values are saved.
*/
public function testCkanConfigValuesAreSaved() {
$edit = [
'api[url]' => $this->ckanUrl,
'api[key]' => '',
];

$this->submitForm($edit, 'Save configuration');
$config_factory = $this->container->get('config.factory');
$value = $config_factory->get('ckan_connect.settings')->get('api.url');
$this->assertSame($this->ckanUrl, $value);
}

}
59 changes: 59 additions & 0 deletions tests/src/Unit/CkanConnectResourceUrlParserTest.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,59 @@
<?php

namespace Drupal\Tests\ckan_connect\Unit\Form;

use Drupal\ckan_connect\Parser\CkanResourceUrlParser;
use Drupal\Tests\UnitTestCase;

/**
* Tests the CkanConnectSettingsForm class.
*
* @group ckan_connect
*/
class CkanConnectResourceUrlParserTest extends UnitTestCase {
/**
* The Ckan resource parser service.
*
* @var \Drupal\ckan_connect\Parser\CkanResourceUrlParser
*/
protected $ckanResourceUrlParser;

/**
* {@inheritdoc}
*/
public function setUp(): void {
parent::setUp();

$ckanClient = $this->createMock('\Drupal\ckan_connect\Client\CkanClientInterface');
$logger = $this->createMock('\Psr\Log\LoggerInterface');
$this->ckanResourceUrlParser = new ckanResourceUrlParser($ckanClient, $logger);
}

/**
* Test that the ckan parser does not recognize invalid urls.
*/
public function testParserDoesNotRecognizeInvalidUrls() {
$urls = [
'https://data.gov.au/dataset/ds-dga-d667403f-2016-463f-bb0a-3087ae67c57f/resource-not/0e32d958-3796-4dca-8312-489ef7a610f6',
'https://data.gov.au/data/api/3/action/datastore_search?resource=0e32d958-3796-4dca-8312-489ef7a610f6&limit=5',
'data.gov.au/dataset/ds-dga-d667403f-2016-463f-bb0a-3087ae67c57f',
];

foreach ($urls as $url) {
$options = $this->ckanResourceUrlParser->parse($url);
$this->assertFalse($options);
}
}

/**
* Test that the ckan parser recognizes a correct ckan url.
*/
public function testParserRecognizesValidCkanUrl() {
$url = 'https://data.gov.au/dataset/ds-dga-d667403f-2016-463f-bb0a-3087ae67c57f/resource/0e32d958-3796-4dca-8312-489ef7a610f6';
$options = $this->ckanResourceUrlParser->parse($url);
$this->assertIsArray($options);
$this->assertArrayHasKey('resource_id', $options);
$this->assertSame($options['resource_id'], '0e32d958-3796-4dca-8312-489ef7a610f6');
}

}

0 comments on commit 6e7104a

Please sign in to comment.