danse_moderation_notifications-1.0.x-dev/src/Form/DanseModerationNotificationsFormBase.php
src/Form/DanseModerationNotificationsFormBase.php
<?php
namespace Drupal\danse_moderation_notifications\Form;
use Drupal\Core\Entity\EntityForm;
use Drupal\Core\Form\FormStateInterface;
use Drupal\Core\Url;
use Drupal\group\Entity\GroupRoleInterface;
use Drupal\group\Entity\GroupTypeInterface;
/**
* Class ContentModerationNotificationFormBase.
*
* Typically, we need to build the same form for both adding a new entity,
* and editing an existing entity. Instead of duplicating our form code,
* we create a base class. Drupal never routes to this class directly,
* but instead through the child classes of ContentModerationNotificationAddForm
* and ContentModerationNotificationEditForm.
*
* @package Drupal\danse_moderation_notifications\Form
*
* @ingroup danse_moderation_notifications
*/
class DanseModerationNotificationsFormBase extends EntityForm {
/**
* Update options.
*
* @param array $form
* Form.
* @param \Drupal\Core\Form\FormStateInterface $form_state
* Formstate.
*
* @return mixed
* Returns the updated options.
*/
public static function updateWorkflowTransitions(array $form, FormStateInterface &$form_state) {
return $form['transitions_wrapper'];
}
/**
* Update options.
*
* @param array $form
* Form.
* @param \Drupal\Core\Form\FormStateInterface $form_state
* Formstate.
*
* @return mixed
* Returns the updated options.
*/
public static function updateGroupRoles(array $form, FormStateInterface &$form_state) {
return $form['group_roles_wrapper'];
}
/**
* Overrides Drupal\Core\Entity\EntityFormController::form().
*
* Builds the entity add/edit form.
*
* @param array $form
* An associative array containing the structure of the form.
* @param \Drupal\Core\Form\FormStateInterface $form_state
* An associative array containing the current state of the form.
*
* @return array
* An associative array containing the danse_moderation_notifications
* add/edit form.
*/
public function buildForm(array $form, FormStateInterface $form_state) {
// Retrieve a list of all possible workflows.
/** @var \Drupal\workflows\WorkflowInterface[] $workflows */
$workflows = $this->entityTypeManager->getStorage('workflow')->loadMultiple();
// Return early if there are no available workflows.
if (empty($workflows)) {
$form['no_workflows'] = [
'#type' => 'markup',
'#markup' => $this->t('No workflows available. <a href=":url">Manage workflows</a>.', [':url' => Url::fromRoute('entity.workflow.collection')->toString()]),
];
return $form;
}
// Get anything we need from the base class.
$form = parent::buildForm($form, $form_state);
// Drupal provides the entity to us as a class variable. If this is an
// existing entity, it will be populated with existing values as class
// variables. If this is a new entity, it will be a new object with the
// class of our entity. Drupal knows which class to call from the
// annotation on our ContentModerationNotification class.
/** @var \Drupal\danse_moderation_notifications\ContentModerationNotificationInterface $danse_moderation_notifications */
$danse_moderation_notifications = $this->entity;
// Build the options array of workflows.
$workflow_options = [];
foreach ($workflows as $workflow_id => $workflow) {
$workflow_options[$workflow_id] = $workflow->label();
}
// Default to the first workflow in the list.
$workflow_keys = array_keys($workflow_options);
if ($form_state->getValue('workflow')) {
$selected_workflow = $form_state->getValue('workflow');
}
elseif (isset($danse_moderation_notifications->workflow)) {
$selected_workflow = $danse_moderation_notifications->workflow;
}
else {
$selected_workflow = array_shift($workflow_keys);
}
$form['label'] = [
'#title' => $this->t('Label'),
'#type' => 'textfield',
'#default_value' => $danse_moderation_notifications->label(),
'#description' => $this->t('The label for this notification.'),
'#required' => TRUE,
'#size' => 30,
];
$form['id'] = [
'#type' => 'machine_name',
'#title' => $this->t('Machine name'),
'#default_value' => $danse_moderation_notifications->id(),
'#machine_name' => [
'exists' => [$this, 'exists'],
'source' => ['label'],
],
'#disabled' => !$danse_moderation_notifications->isNew(),
];
// Allow the workflow to be selected, this will dynamically update the
// available transition lists.
$form['workflow'] = [
'#type' => 'select',
'#title' => $this->t('Workflow'),
'#options' => $workflow_options,
'#default_value' => $selected_workflow,
'#required' => TRUE,
'#description' => $this->t('Select a workflow'),
'#ajax' => [
'wrapper' => 'workflow_transitions_wrapper',
'callback' => static::class . '::updateWorkflowTransitions',
],
];
// Ajax replaceable fieldset.
$form['transitions_wrapper'] = [
'#type' => 'container',
'#prefix' => '<div id="workflow_transitions_wrapper">',
'#suffix' => '</div>',
];
// Transitions.
$state_transitions_options = [];
$state_transitions = $workflows[$selected_workflow]->getTypePlugin()->getTransitions();
foreach ($state_transitions as $key => $transition) {
$state_transitions_options[$key] = $transition->label();
}
$form['transitions_wrapper']['transitions'] = [
'#type' => 'checkboxes',
'#title' => $this->t('Transitions'),
'#options' => $state_transitions_options,
'#default_value' => isset($danse_moderation_notifications->transitions) ? $danse_moderation_notifications->transitions : [],
'#required' => TRUE,
'#description' => $this->t('Select which transitions triggers this notification.'),
];
// Role selection.
$roles_options = user_role_names(TRUE);
$form['roles'] = [
'#type' => 'checkboxes',
'#title' => $this->t('Roles'),
'#options' => $roles_options,
'#default_value' => $danse_moderation_notifications->getRoleIds(),
'#description' => $this->t('Send notifications to all users with these roles.'),
];
// Group module notification functionality.
if ($this->moduleHandler->moduleExists('group')) {
/** @var \Drupal\Core\Entity\EntityStorageInterface $group_type_storage */
$group_type_storage = $this->entityTypeManager->getStorage('group_type');
$form['group_use'] = [
'#type' => 'checkbox',
'#title' => $this->t('Use group membership'),
'#default_value' => $danse_moderation_notifications->isGroupUse(),
'#description' => $this->t('Send notifications to members of any related group.'),
];
// Build the options array of group types.
$group_type_options = array_map(static function (GroupTypeInterface $group_type) {
return $group_type->label();
}, $group_type_storage->loadMultiple());
// Default to the first group in the list.
$group_type_keys = array_keys($group_type_options);
$selected_group_type = array_shift($group_type_keys);
if ($form_state->getValue('group_type')) {
$selected_group_type = $form_state->getValue('group_type');
}
elseif (isset($danse_moderation_notifications->group_type)) {
$selected_group_type = $danse_moderation_notifications->group_type;
}
// Allow the group type to be selected, this will dynamically update the
// available group role lists.
$form['group_type'] = [
'#type' => 'select',
'#title' => $this->t('Group Types'),
'#options' => $group_type_options,
'#default_value' => $selected_group_type,
'#description' => $this->t('Select a group type'),
'#ajax' => [
'wrapper' => 'group_roles_wrapper',
'callback' => static::class . '::updateGroupRoles',
],
'#states' => [
'visible' => [
"input[name='group_use']" => ['checked' => TRUE],
],
],
];
// Ajax replaceable fieldset.
$form['group_roles_wrapper'] = [
'#type' => 'container',
'#prefix' => '<div id="group_roles_wrapper">',
'#suffix' => '</div>',
'#states' => [
'visible' => [
"input[name='group_use']" => ['checked' => TRUE],
],
],
];
// Group Role.
$state_group_roles = [];
if ($selected_group_type) {
$state_group_roles = $this->entityTypeManager
->getStorage('group_role')
->loadByProperties(['group_type' => $selected_group_type]);
// Remove internal roles except the member role.
$state_group_roles = array_filter($state_group_roles, static function (GroupRoleInterface $group_role) {
return ($group_role->id() == $group_role->getGroupTypeId() . '-member') || !$group_role->isInternal();
});
}
$state_group_role_options = [];
if (!empty($state_group_roles)) {
// Build the options array of group types.
$state_group_role_options = array_map(static function (GroupRoleInterface $role) {
return $role->label();
}, $state_group_roles);
}
$form['group_roles_wrapper']['group_roles'] = [
'#type' => 'checkboxes',
'#title' => $this->t('Group Role'),
'#options' => $state_group_role_options,
'#default_value' => isset($danse_moderation_notifications->group_roles) ? $danse_moderation_notifications->group_roles : [],
'#description' => $this->t('Send notifications to all users with these roles.'),
'#states' => [
'required' => [
"input[name='group_use']" => ['checked' => TRUE],
],
],
];
}
// Send email to the original author?
// Flag module notification modifications.
if ($this->moduleHandler->moduleExists('flag')) {
$form['flag_wrapper'] = [
'#type' => 'container',
'#prefix' => '<div id="flag_wrapper">',
'#suffix' => '</div>',
];
/** @var \Drupal\flag\Entity\Flag[] $flags */
$flags = $this->entityTypeManager
->getStorage('flag')
->loadMultiple();
$flag_options = [];
foreach ($flags as $flag) {
$flag_options[$flag->id()] = $flag->label();
}
$form['flag_wrapper']['flags'] = [
'#type' => 'checkboxes',
'#title' => $this->t('Flag types'),
'#options' => $flag_options,
'#default_value' => isset($danse_moderation_notifications->flags) ? $danse_moderation_notifications->flags : [],
'#description' => $this->t('Send notifications to all users who have flagged with these flags.'),
];
}
// Send email to author?
$form['author'] = [
'#type' => 'checkbox',
'#title' => $this->t('Email the original content author?'),
'#default_value' => $danse_moderation_notifications->sendToAuthor(),
'#description' => $this->t('Send notifications to the current author of the content.'),
];
// Send email to the revision author?
$form['revision_author'] = [
'#type' => 'checkbox',
'#title' => $this->t('Email the revision author?'),
'#default_value' => $danse_moderation_notifications->sendToRevisionAuthor(),
'#description' => $this->t('Send notifications to the current author of the content.'),
];
$form['site_mail'] = [
'#type' => 'checkbox',
'#title' => $this->t('Disable the site email address'),
'#default_value' => $danse_moderation_notifications->disableSiteMail(),
'#description' => $this->t('Do not send notifications to the site email address.'),
];
$form['emails'] = [
'#type' => 'textarea',
'#rows' => 3,
'#title' => $this->t('Adhoc email addresses'),
'#default_value' => $danse_moderation_notifications->getEmails(),
'#description' => $this->t('Send notifications to these email addresses. Separate emails with commas or newlines. You may use Twig templating code in this field.'),
];
// Email subject line.
$form['subject'] = [
'#type' => 'textarea',
'#rows' => 1,
'#title' => $this->t('Email Subject'),
'#default_value' => $danse_moderation_notifications->getSubject(),
'#required' => TRUE,
'#description' => $this->t('You may use Twig templating code in this field.'),
];
// Email body content.
$form['body'] = [
'#type' => 'text_format',
'#format' => $danse_moderation_notifications->getMessageFormat() ?: filter_default_format(),
'#title' => $this->t('Email Body'),
'#default_value' => $danse_moderation_notifications->getMessage(),
'#description' => $this->t('You may use Twig templating code in this field.'),
];
// Add token tree link if module exists.
if ($this->moduleHandler->moduleExists('token')) {
$form['body']['token_tree_link'] = [
'#theme' => 'token_tree_link',
'#token_types' => array_unique(['user', $selected_workflow, 'node']),
'#weight' => 10,
];
}
// Return the form.
return $form;
}
/**
* Checks for an existing danse_moderation_notifications.
*
* @param string|int $entity_id
* The entity ID.
* @param array $element
* The form element.
* @param \Drupal\Core\Form\FormStateInterface $form_state
* The form state.
*
* @return bool
* TRUE if this format already exists, FALSE otherwise.
*/
public function exists($entity_id, array $element, FormStateInterface $form_state) {
// Use the query factory to build a new entity query.
$query = $this->entityTypeManager->getStorage('danse_moderation_notifications')->getQuery();
// Query the entity ID to see if its in use.
$result = $query->condition('id', $element['#field_prefix'] . $entity_id)
->execute();
// We don't need to return the ID, only if it exists or not.
return (bool) $result;
}
/**
* Overrides Drupal\Core\Entity\EntityFormController::actions().
*
* To set the submit button text, we need to override actions().
*
* @param array $form
* An associative array containing the structure of the form.
* @param \Drupal\Core\Form\FormStateInterface $form_state
* An associative array containing the current state of the form.
*
* @return array
* An array of supported actions for the current entity form.
*/
protected function actions(array $form, FormStateInterface $form_state) {
// Get the basic actins from the base class.
$actions = parent::actions($form, $form_state);
// Change the submit button text.
$actions['submit']['#value'] = $this->t('Save');
// Return the result.
return $actions;
}
/**
* Overrides Drupal\Core\Entity\EntityFormController::save().
*
* Saves the entity. This is called after submit() has built the entity from
* the form values. Do not override submit() as save() is the preferred
* method for entity form controllers.
*
* @param array $form
* An associative array containing the structure of the form.
* @param \Drupal\Core\Form\FormStateInterface $form_state
* An associative array containing the current state of the form.
*/
public function save(array $form, FormStateInterface $form_state) {
// EntityForm provides us with the entity we're working on.
$danse_moderation_notifications = $this->getEntity();
// Drupal already populated the form values in the entity object. Each
// form field was saved as a public variable in the entity class. PHP
// allows Drupal to do this even if the method is not defined ahead of
// time.
$status = $danse_moderation_notifications->save();
if ($status == SAVED_UPDATED) {
// If we edited an existing entity...
$this->messenger()->addMessage($this->t('Notification <a href=":url">%label</a> has been updated.',
[
'%label' => $danse_moderation_notifications->label(),
':url' => $danse_moderation_notifications->toUrl('edit-form')->toString(),
]
));
$this->logger('danse_moderation_notifications')->notice('Notification has been updated.', ['%label' => $danse_moderation_notifications->label()]);
}
else {
// If we created a new entity...
$this->messenger()->addMessage($this->t('Notification <a href=":url">%label</a> has been added.',
[
'%label' => $danse_moderation_notifications->label(),
':url' => $danse_moderation_notifications->toUrl('edit-form')->toString(),
]
));
$this->logger('danse_moderation_notifications')->notice('Notification has been added.', ['%label' => $danse_moderation_notifications->label()]);
}
// Redirect the user back to the listing route after the save operation.
$form_state->setRedirect('entity.danse_moderation_notifications.collection');
}
}
