3

I am trying to change the content moderation state from draft to submitted programatically. The Content Moderation module adds a field to content types with a dropdown to change the state, but I want to hide this field from users and instead show a custom submit handler that changes the form state.

I can change the default value of the moderation field with code like this:

  $form['moderation_state']['widget'][0]['state']['#default_value'] = "submitted";

But, how do I change the value for the content moderation field using $form_state in the submit handler?

  $form_state->setValue('moderation_state', 'submitted');`

does not work like it does for fields.

Here is the debug output for kint($form['moderation_state']['widget'][0]):

kint debug output

  • Debug $form_state, not $form. If the form uses #tree, then the values in form_state are in arrays: $form_state->setValue(['foo', 'bar'], $value); see api.drupal.org/api/drupal/… – 4k4 Oct 4 '17 at 19:56
3

To change the moderation state you need first to get the entity:

$entity = $form_state->getFormObject()->getEntity();

and then change the state:

$entity->set('moderation_state', 'submitted');

and save:

$entity->save();

All the code:

/**
 * Submit callback to submit for approval
 */
function draft2submit_callback(array &$form, FormStateInterface &$form_state) {
  // Getting the entity.
  $entity = $form_state->getFormObject()->getEntity();
  // Changing the moderation state.
  $entity->set('moderation_state', 'submitted');
  // Saving the entity.
  $entity->save();
}
| improve this answer | |
2

I had to solve this problem too, and found two ways to do it:

Option 1:

Set the widget type to value, and set the default value to submitted. I also removed the current state message showing on the form

/**
 * Implements hook_form_alter().
 */
function your_module_form_alter(&$form, \Drupal\Core\Form\FormStateInterface $form_state, $form_id) {

  // may want to do some checks here ...

  $form['moderation_state']['widget'][0]['current']['#access'] = false;
  $form['moderation_state']['widget'][0]['state']['#type'] = 'value';
  $form['moderation_state']['widget'][0]['state']['#default_value'] = 'submitted';
}

Using Option 1 this could fail validation if the current moderation state doesn't have a transition to submitted for the current user.

Option 2:

Add a validation callback function, and set the value in there:

/**
 * Implements hook_form_alter().
 */
function your_module_form_alter(&$form, \Drupal\Core\Form\FormStateInterface $form_state, $form_id) {

  // may want to do some checks here ...

  $form['moderation_state']['#access'] = false;

  if (isset($form['#validate'])) {
    array_unshift($form['#validate'], '_your_module_set_moderation_state_to_submitted');
  } else {
    $form['#validate'][] = '_your_module_set_moderation_state_to_submitted';
  }
}

/**
 * @param $form
 *   Nested array of form elements that comprise the form.
 * @param $form_state
 *   The current state of the form.
 */
function _your_module_set_moderation_state_to_submitted(array &$form, \Drupal\Core\Form\FormStateInterface $form_state) {
  $form_state->setValue(['moderation_state', '0', 'value'], 'submitted');
}

I found I needed to use a validation callback, as otherwise it would run the validation before attempting to set the value, this would fail the validation if I didn't have a transition configured for it to remain at the same moderation state.

The other thing to note with Option 2 is that by using setValue you add a validated value. Therefore depending on how you've configured your workflows that may not be a transition that is otherwise allowed.

| improve this answer | |

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.