billwerk_subscriptions-1.x-dev/modules/billwerk_subscriptions_manage/src/Form/ComponentsUnsubscribeForm.php
modules/billwerk_subscriptions_manage/src/Form/ComponentsUnsubscribeForm.php
<?php
declare(strict_types=1);
namespace Drupal\billwerk_subscriptions_manage\Form;
use Drupal\Core\Form\FormStateInterface;
use Drupal\Core\Url;
use Drupal\billwerk_subscriptions\Exception\SubscriberException;
/**
* Provides a Billwerk Subscriptions Manage form.
*/
final class ComponentsUnsubscribeForm extends ChangeFormBase {
/**
* {@inheritdoc}
*/
public function getFormId(): string {
return 'billwerk_subscriptions_manage_components_unsubscribe';
}
/**
* {@inheritdoc}
*/
public function buildSelectionForm(array $form, FormStateInterface $form_state): array {
$this->buildComponentsUnsubscribeFormElement($form, $form_state);
$form['components_unsubscribe']['#required'] = TRUE;
if (empty($form['components_unsubscribe']['#options'])) {
return [
'message' => [
'#type' => 'inline_template',
'#template' => '<div class="messages messages--warning"><div class="message">{{ "No add-ons to cancel in your subscription. Please contact us for individual cases."|t }}</div></div>',
'#context' => [],
],
];
}
$form['actions']['#type'] = 'actions';
$form['actions']['cancel'] = [
'#type' => 'link',
'#title' => $this->t('Cancel'),
'#attributes' => [
'class' => [
'button',
'button--danger',
'button--cancel',
],
],
'#url' => Url::fromRoute('billwerk_subscriptions_manage.current_user_subscription'),
// Adjust the weight to change the position of the button.
'#weight' => -1,
];
$form['actions']['proceed'] = [
'#type' => 'submit',
'#value' => $this->t('Next'),
'#validate' => ['::validateSelectionForm'],
'#submit' => ['::proceedToConfirm'],
'#button_type' => 'primary',
];
return $form;
}
/**
* Validates the selection form.
*
* @param array $form
* The form.
* @param \Drupal\Core\Form\FormStateInterface $form_state
* The form state.
*/
public function validateSelectionForm(array &$form, FormStateInterface $form_state) {
$activeComponents = $this->subscriberBillwerkEntitiesHelper->getActiveBillwerkComponents();
$selectedComponents = array_filter($form_state->getValue('components_unsubscribe'));
if (!empty(array_diff_key($selectedComponents, $this->billwerkEntitiesHelper->getComponentsUnsubscribeSelectOptions(array_keys($activeComponents))))) {
$form_state->setErrorByName('components_unsubscribe', $this->t('Invalid component selected'));
}
}
/**
* Build the confirm form.
*
* @param array $form
* The form.
* @param \Drupal\Core\Form\FormStateInterface $form_state
* The form state.
*/
protected function buildConfirmForm(array $form, FormStateInterface $form_state): array {
$endComponentSubscriptionIds = $this->valueGetComponentsUnsubscribe($form_state);
$billwerkOrderObj = $this->subscriber->billwerkChangeSubscription(
NULL,
[],
$endComponentSubscriptionIds,
// No coupon:
'',
// Cancellation should happen at the end of the contract period:
FALSE,
// We need a committable (non-preview) order:
FALSE,
// We commit this order after confirmation:
FALSE,
);
// This is a special case!
// While $billwerkOrderObj->AllowWithoutPaymentData is returned as FALSE
// The component unsubscribe IS actually allowed without
// payment data and wouldn't make any sense to collect it.
$billwerkOrderObj->AllowWithoutPaymentData = TRUE;
$form_state->set('billwerkOrder', $billwerkOrderObj);
$form_state->set('step', 'confirm');
$this->buildOrderTableFormElement(
$form,
$form_state,
$billwerkOrderObj, [
'hideSubsequentBilling' => TRUE,
]
);
$this->buildDowngradeOrderTermsFormElement($form, $form_state);
if (!$billwerkOrderObj->AllowWithoutPaymentData) {
// There are edge-cases where even for a downgrade
// payment data is requested:
$this->buildOrderPaymentFormElement($form, $form_state, $billwerkOrderObj);
$this->buildOrderAddressFormElement($form, $form_state, $billwerkOrderObj);
// There are edge-cases where even for a downgrade
// payment data is requested:
// Here we use the fake submit, as payment and submit need to be
// client-side:
$this->buildOrderActionsFakeFormElement($form, $form_state, $this->t('Confirm add-on cancellation'));
}
else {
$this->buildOrderActionsFormElement($form, $form_state, $this->t('Confirm add-on cancellation'));
}
return $form;
}
/**
* {@inheritdoc}
*/
public function submitForm(array &$form, FormStateInterface $form_state): void {
$billwerkOrderObj = $form_state->get('billwerkOrder');
if (!empty($billwerkOrderObj) && !empty($billwerkOrderObj->Id)) {
// We can commit the order server-side here, because no payment data is
// needed!
$this->api->commitOrder($billwerkOrderObj->Id, []);
$confirmationMessage = $this->config('billwerk_subscriptions_manage.settings')->get('subscription_changed_message');
$this->messenger()->addStatus($this->t('The selected add-ons have been canceled.') . "\n" . ($confirmationMessage['value'] ?? ''));
$form_state->setRedirect('billwerk_subscriptions_manage.current_user_subscription');
}
else {
throw new SubscriberException('Order was not committed, because order id could not be determined.');
}
}
}
