Skip to content

Commit

Permalink
feat: add field to allow to set the default status of submitted conte…
Browse files Browse the repository at this point in the history
…nt per provider

Refs: RW-831
  • Loading branch information
orakili committed Feb 28, 2024
1 parent dfe9a93 commit 1aa4b9e
Show file tree
Hide file tree
Showing 7 changed files with 187 additions and 1 deletion.
15 changes: 15 additions & 0 deletions html/modules/custom/reliefweb_post_api/src/Entity/Provider.php
Original file line number Diff line number Diff line change
Expand Up @@ -203,6 +203,21 @@ public function getUserId(): int {
return (int) $this->get($field)->target_id;
}

/**
* {@inheritdoc}
*/
public function getDefaultResourceStatus(): string {
$field = 'field_resource_status';
// Draft is the only common status among all RW content entities.
if (!$this->hasField($field)) {
return 'draft';
}
if (empty($this->get($field)->value)) {
return 'draft';
}
return $this->get($field)->value;
}

/**
* {@inheritdoc}
*/
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -46,6 +46,14 @@ public function getEmailsToNotify(): array;
*/
public function getUserId(): int;

/**
* Get the default moderation status for the created/updated entities.
*
* @return string
* Moeration status. Defaults to 'draft'.
*/
public function getDefaultResourceStatus(): string;

/**
* Check if a provider with the given ID exits and its API key is valid.
*
Expand Down
30 changes: 30 additions & 0 deletions html/modules/custom/reliefweb_post_api/src/Form/ProviderForm.php
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,7 @@
use Drupal\Core\Entity\EntityTypeBundleInfoInterface;
use Drupal\Core\Form\FormStateInterface;
use Drupal\Core\Password\PasswordInterface;
use Drupal\reliefweb_moderation\ModerationServiceBase;
use Drupal\reliefweb_post_api\Plugin\ContentProcessorPluginManagerInterface;
use Symfony\Component\DependencyInjection\ContainerInterface;

Expand Down Expand Up @@ -68,6 +69,35 @@ public function form(array $form, FormStateInterface $form_state) {
return $form;
}

/**
* {@inheritdoc}
*/
public function validateForm(array &$form, FormStateInterface $form_state) {
parent::validateForm($form, $form_state);

// No need to do further validation if there is already an error on the
// resource or resource status. For example if one is missing or not a valid
// value.
$errors = $form_state->getErrors();
if (!isset($errors['resource']) && !isset($errors['field_resource_status'])) {
$resource = $form_state->getValue(['resource', 0, 'value']);
$status = $form_state->getValue(['field_resource_status', 0, 'value']);

$plugin = $this->contentProcessorPluginManager->getPluginByResource($resource);
$bundle = $plugin->getBundle();
$service = ModerationServiceBase::getModerationService($bundle);
$statuses = $service->getStatuses();

if (!isset($statuses[$status])) {
$error = $this->t('@status is not supported for this resource, please select one of @statuses', [
'@status' => $form['field_resource_status']['widget']['#options'][$status] ?? $status,
'@statuses' => implode(', ', $statuses),
]);
$form_state->setError($form['field_resource_status']['widget'], $error);
}
}
}

/**
* {@inheritdoc}
*/
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -110,7 +110,7 @@ public function process(array $data): ?ContentEntityInterface {
$node->field_ocha_product->setValue(NULL);

// Set the new status.
$node->moderation_status = 'pending';
$node->moderation_status = $provider->getDefaultResourceStatus();

// Set the log message based on whether it was updated or created.
$message = $node->isNew() ? 'Automatic creation from POST API.' : 'Automatic update from POST API.';
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,7 @@ public function buildHeader(): array {
$header['name'] = $this->t('Name');
$header['uuid'] = $this->t('UUID');
$header['resource'] = $this->t('Resource');
$header['resource_status'] = $this->t('Default status');
$header['source'] = $this->t('Sources');
$header['status'] = $this->t('Active');
return $header + parent::buildHeader();
Expand All @@ -41,6 +42,10 @@ public function buildRow(EntityInterface $entity): array {
'label' => 'hidden',
]);

$row['resource_status']['data'] = $entity->field_resource_status->view([
'label' => 'hidden',
]);

$sources = [];
foreach ($entity->field_source as $item) {
$source = $item->entity;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -25,12 +25,14 @@ class ProviderTest extends ExistingSiteBase {
protected $data = [
'name' => 'test-provider',
'key' => 'test-provider-key',
'resource' => 'reports',
'field_document_url' => ['https://test.test/', 'https://test1.test/'],
'field_file_url' => ['https://test.test/'],
'field_image_url' => ['https://test.test/'],
'field_notify' => ['test@test.test'],
'field_source' => [1503],
'field_user' => 12,
'field_resource_status' => 'pending',
];

/**
Expand Down Expand Up @@ -145,6 +147,30 @@ public function testGetUserId(): void {
$this->assertEquals(2, $provider->getUserId());
}

/**
* @covers ::getDefaultResourceStatus
*/
public function testGetDefaultResourceStatus(): void {
$data = $this->data;

$provider = $this->createProvider($data);
$this->assertEquals($this->data['field_resource_status'], $provider->getDefaultResourceStatus());

$data['field_resource_status'] = [];
$provider = $this->createProvider($data);
$this->assertEquals('draft', $provider->getDefaultResourceStatus());

// The default value is "pending" when the field is initialized.
unset($data['field_resource_status']);
$provider = $this->createProvider($data);
$this->assertEquals('pending', $provider->getDefaultResourceStatus());

// Missing field.
$provider = $this->createNoFieldProvider();
$this->assertFalse($provider->hasField('field_resource_status'));
$this->assertEquals('draft', $provider->getDefaultResourceStatus());
}

/**
* @covers ::validateKey
*/
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -61,6 +61,108 @@ public function testForm(): void {
$this->assertArrayHasKey('data-with-autocomplete', $form['field_source']['#attributes']);
}

/**
* @covers ::validateForm()
*/
public function testValidateForm(): void {
$provider = $this->createDummyProvider();

$form_object = \Drupal::entityTypeManager()
->getFormObject('reliefweb_post_api_provider', 'default')
->setEntity($provider);

$form_state = new FormState();

$form = \Drupal::service('form_builder')
->buildForm($form_object, $form_state);

// Missing resource.
$form_state->clearErrors();
$form_state->unsetValue(['resource', 0, 'value']);
$form_object->validateForm($form, $form_state);
$errors = $form_state->getErrors();
$this->assertArrayHasKey('resource', $errors);
$this->assertEquals('This value should not be null.', (string) $errors['resource']);

// Invalid resource.
$form_state->clearErrors();
$form_state->setValue(['resource', 0, 'value'], 'test');
$form_object->validateForm($form, $form_state);
$errors = $form_state->getErrors();
$this->assertArrayHasKey('resource', $errors);
$this->assertEquals('The value you selected is not a valid choice.', (string) $errors['resource']);

// Missing resource status.
$form_state->clearErrors();
$form_state->setValue(['resource', 0, 'value'], 'reports');
$form_object->validateForm($form, $form_state);
$errors = $form_state->getErrors();
$this->assertArrayHasKey('field_resource_status', $errors);
$this->assertEquals('This value should not be null.', (string) $errors['field_resource_status']);

// Invalid resource status.
$form_state->clearErrors();
$form_state->setValue(['field_resource_status', 0, 'value'], 'test');
$form_object->validateForm($form, $form_state);
$errors = $form_state->getErrors();
$this->assertArrayHasKey('field_resource_status', $errors);
$this->assertEquals('The value you selected is not a valid choice.', (string) $errors['field_resource_status']);

// Valid resouce and resource status.
$form_state->clearErrors();
$form_state->setValue(['resource', 0, 'value'], 'reports');
$form_state->setValue(['field_resource_status', 0, 'value'], 'pending');
$form_object->validateForm($form, $form_state);
$errors = $form_state->getErrors();
$this->assertArrayNotHasKey('resource', $errors);
$this->assertArrayNotHasKey('field_resource_status', $errors);
}

/**
* @covers ::validateForm()
*/
public function testValidateFormUnallowedStatus(): void {
$provider = $this->createDummyProvider();

$form_object = \Drupal::entityTypeManager()
->getFormObject('reliefweb_post_api_provider', 'default')
->setEntity($provider);

// Skip errors due to unallowed values for the resource and resource status
// fields so we can test unallowed statuses.
$form_state = new class() extends FormState {

/**
* {@inheritdoc}
*/
public function getErrors() {
$errors = $this->errors;
foreach ($errors as $key => $error) {
if ($key === 'resource' || $key === 'field_resource_status') {
if ((string) $error === 'The value you selected is not a valid choice.') {
unset($errors[$key]);
}
}
}
return $errors;
}

};

$form = \Drupal::service('form_builder')
->buildForm($form_object, $form_state);

// Test invalid choice of status.
$form_state->clearErrors();
$form_state->setValue(['resource', 0, 'value'], 'reports');
$form_state->setValue(['field_resource_status', 0, 'value'], 'test');
$form_object->validateForm($form, $form_state);
$errors = $form_state->getErrors();
$this->assertArrayNotHasKey('resource', $errors);
$this->assertArrayHasKey('field_resource_status', $errors);
$this->assertStringContainsString('is not supported for this resource, please select one of', (string) $errors['field_resource_status']);
}

/**
* @covers ::save()
*/
Expand Down

0 comments on commit 1aa4b9e

Please sign in to comment.