openquestions-1.0.x-dev/src/Form/OqApplicationForm.php
src/Form/OqApplicationForm.php
<?php
namespace Drupal\openquestions\Form;
use Drupal\Core\Entity\ContentEntityForm;
use Drupal\Core\Form\FormStateInterface;
use Drupal\Component\Datetime\TimeInterface;
use Drupal\Core\Entity\Display\EntityFormDisplayInterface;
use Drupal\Core\Entity\EntityTypeBundleInfoInterface;
use Drupal\Core\Entity\EntityFormDisplay;
use Drupal\Core\Entity\EntityRepositoryInterface;
use Drupal\Core\Entity\EntityTypeManager;
use Drupal\Core\Datetime\DateFormatterInterface;
use Symfony\Component\DependencyInjection\ContainerInterface;
use Drupal\openquestions\Service\OQUtilsInterface;
use Drupal\Core\Logger\LoggerChannelInterface;
/**
* Form controller for the oq application entity edit forms.
*/
class OqApplicationForm extends ContentEntityForm {
protected const DISPOSITION_PENDING = 'Pending';
/**
* The date formatter service.
*
* @var \Drupal\Core\Datetime\DateFormatterInterface
*/
protected $dateFormatter;
/**
* Our utils.
*
* @var \Drupal\openquestions\Service\OQUtilsInterface
*/
protected $oqUtils;
/**
* Our logger.
*
* @var \Drupal\Core\Logger\LoggerChannelInterface
*/
protected $logger;
/**
* Constructs a OqApplicationForm object.
*
* @param \Drupal\Core\Entity\EntityRepositoryInterface $entity_repository
* The entity repository service.
* @param \Drupal\Core\Entity\EntityTypeBundleInfoInterface $entity_type_bundle_info
* The entity type bundle service.
* @param \Drupal\Component\Datetime\TimeInterface $time
* The time service.
* @param \Drupal\Core\Entity\EntityTypeManager $entityTypeManager
* The entity type manager.
* @param \Drupal\Core\Datetime\DateFormatterInterface $dateFormatter
* Date formatter.
* @param \Drupal\openquestions\Service\OQUtilsInterface $oqUtils
* Our utils.
* @param \Drupal\Core\Logger\LoggerChannelInterface $logger
* Our logger.
*/
public function __construct(EntityRepositoryInterface $entity_repository,
EntityTypeBundleInfoInterface $entity_type_bundle_info,
TimeInterface $time,
EntityTypeManager $entityTypeManager,
DateFormatterInterface $dateFormatter,
OQUtilsInterface $oqUtils,
LoggerChannelInterface $logger) {
parent::__construct($entity_repository, $entity_type_bundle_info, $time);
$this->entityTypeManager = $entityTypeManager;
$this->dateFormatter = $dateFormatter;
$this->oqUtils = $oqUtils;
$this->logger = $logger;
}
/**
* {@inheritdoc}
*/
public static function create(ContainerInterface $container) {
return new static(
$container->get('entity.repository'),
$container->get('entity_type.bundle.info'),
$container->get('datetime.time'),
$container->get('entity_type.manager'),
$container->get('date.formatter'),
$container->get('openquestions.oq_utils'),
$container->get('openquestions.logger.channel.openquestions')
);
}
/**
* {@inheritdoc}
*/
public function buildForm(array $form, FormStateInterface $form_state) {
$form = parent::buildForm($form, $form_state);
$form['description']['widget'][0]['#allowed_formats'] = ['fully_plain_text'];
$application = $this->getEntity();
$editing = $application && $application->id();
$form_state->set('editing', $editing);
if ($editing) {
$form['uid']['#access'] = FALSE;
$form['status']['#access'] = FALSE;
$form['created']['#access'] = FALSE;
$form['histories']['#access'] = FALSE;
foreach ($form['links']['widget'] as $k => $ignored) {
if (is_numeric($k) && !empty($form['links']['widget'][$k]['value'])) {
$form['links']['widget'][$k]['value']['#attributes']['readonly'] = TRUE;
}
}
$form['label']['widget'][0]['value']['#attributes']['readonly'] = TRUE;
$form['description']['widget'][0]['#attributes']['readonly'] = TRUE;
$account = $this->oqUtils->getFirstReference($application, 'uid');
$form['intro'] = [
'#type' => 'item',
'#markup' => $this->t('This application was submitted by <a href=":user_link">@user_name</a> on @date. Editing is restricted to changing the disposition.', [
':user_link' => $account->toUrl()->toString(),
'@user_name' => $account->get('name')->value,
'@date' => $this->dateFormatter->format($application->get('created')->value),
]),
'#weight' => -1000,
];
$form['disposition_reason'] = [
'#type' => 'textarea',
'#title' => $this->t('Enter the reason for the disposition change'),
'#description' => $this->t('This will be saved with the disposition histories'),
'#required' => TRUE,
];
}
else {
$term = $this->getDispositionTerm(self::DISPOSITION_PENDING);
$form['intro'] = [
'#type' => 'item',
'#markup' => $this->t('<strong>Note that what you enter on this form will become public immediately and cannot be edited later. Double-check that the information is correct before submitting the form.</strong>'),
'#weight' => -1000,
];
$label = t('Application from @username', ['@username' => $this->currentUser()->getDisplayName()]);
$form['label']['widget'][0]['value']['#value'] = $form['label']['widget'][0]['value']['#default_value'] = $label;
$form['label']['widget'][0]['value']['#attributes']['readonly'] = TRUE;
$form['uid']['#access'] = FALSE;
$form['status']['#access'] = FALSE;
$form['created']['#access'] = FALSE;
$form['histories']['#access'] = FALSE;
$form['disposition']['#access'] = FALSE;
$form['disposition']['widget']['#value'] = $form['disposition']['widget']['#default_value'] = $term->id();
}
$term = $this->oqUtils->getFirstReference($application, 'disposition');
$form_state->set('original_disposition_id', $term ? $term->id() : NULL);
return $form;
}
/**
* {@inheritdoc}
*/
public function save(array $form, FormStateInterface $form_state) {
$result = parent::save($form, $form_state);
$editing = $form_state->get('editing');
$entity = $this->getEntity();
if ($editing) {
$ary = $form_state->getValue('disposition');
$disposition = !empty($ary[0]['target_id']) ? $ary[0]['target_id'] : NULL;
$dispositionReason = $form_state->getValue('disposition_reason');
$originalDisposition = $form_state->get('original_disposition_id');
if ($disposition != $originalDisposition) {
$label = $this->t('From @before to @after on @date', [
'@before' => $originalDisposition,
'@after' => $disposition,
'@date' => $this->dateFormatter->format($this->time->getRequestTime()),
]);
$data = [
'label' => $label,
'status' => TRUE,
'description' => $dispositionReason,
'uid' => $this->currentUser()->id(),
'disposition_before' => $originalDisposition,
'disposition_after' => $disposition,
];
$history = $this->entityTypeManager->getStorage('oq_application_history')->create($data);
$history->save();
$entity->histories[] = $history;
$entity->save();
}
}
else {
$term = $this->getDispositionTerm(self::DISPOSITION_PENDING);
$data = [
'label' => $this->t('Initial'),
'status' => TRUE,
'description' => $this->t('Initial'),
'uid' => $this->currentUser()->id(),
'disposition_before' => NULL,
'disposition_after' => $term->id(),
];
$history = $this->entityTypeManager->getStorage('oq_application_history')->create($data);
$history->save();
$entity->histories[] = $history;
$entity->save();
}
$message_arguments = ['%label' => $entity->toLink()->toString()];
$logger_arguments = [
'%label' => $entity->label(),
'link' => $entity->toLink($this->t('View'))->toString(),
];
switch ($result) {
case SAVED_NEW:
$this->messenger()->addStatus($this->t('New oq application %label has been created.', $message_arguments));
$this->logger->notice('Created new oq application %label', $logger_arguments);
break;
case SAVED_UPDATED:
$this->messenger()->addStatus($this->t('The oq application %label has been updated.', $message_arguments));
$this->logger->notice('Updated oq application %label.', $logger_arguments);
break;
}
$form_state->setRedirect('entity.oq_application.canonical', ['oq_application' => $entity->id()]);
return $result;
}
/**
* Get the given term from our vocabulary.
*
* @return object
* A taxonomy term.
*
* @throws \Exception
* If the term isn't found.
*/
protected function getDispositionTerm($name) {
$term = $this->entityTypeManager->getStorage('taxonomy_term')->loadByProperties([
'vid' => 'oq_application_disposition',
'name' => $name,
]);
$term = $term ? reset($term) : NULL;
if (!$term) {
throw new \Exception($this->t('Application could not be completed, please contact an administrator.'));
}
return $term;
}
}
