billwerk_subscriptions-1.x-dev/modules/billwerk_subscriptions_manage/src/Form/ChangeFormBase.php
modules/billwerk_subscriptions_manage/src/Form/ChangeFormBase.php
<?php
declare(strict_types=1);
namespace Drupal\billwerk_subscriptions_manage\Form;
use Drupal\Core\Entity\EntityTypeManagerInterface;
use Drupal\Core\Form\FormBase;
use Drupal\Core\Form\FormStateInterface;
use Drupal\Core\Language\LanguageManagerInterface;
use Drupal\Core\StringTranslation\TranslatableMarkup;
use Drupal\Core\Url;
use Drupal\billwerk_subscriptions\Api;
use Drupal\billwerk_subscriptions\Environment;
use Drupal\billwerk_subscriptions\Subscriber;
use Drupal\billwerk_subscriptions_entities\BillwerkEntitiesHelper;
use Drupal\billwerk_subscriptions_entities\SubscriberBillwerkEntitiesHelper;
use Symfony\Component\DependencyInjection\ContainerInterface;
/**
* Provides a Billwerk Subscriptions Manage form.
*/
abstract class ChangeFormBase extends FormBase {
/**
* The subscriber billwerk entities helper.
*
* @var \Drupal\billwerk_subscriptions_entities\SubscriberBillwerkEntitiesHelper
*/
protected SubscriberBillwerkEntitiesHelper $subscriberBillwerkEntitiesHelper;
/**
* The subscriber.
*
* @var \Drupal\billwerk_subscriptions\Subscriber
*/
protected Subscriber $subscriber;
/**
* The language manager.
*
* @var \Drupal\Core\Language\LanguageManagerInterface
*/
protected LanguageManagerInterface $languageManager;
/**
* Constructs a new ChangeFormBase object.
*
* @param \Drupal\billwerk_subscriptions_entities\BillwerkEntitiesHelper $billwerkEntitiesHelper
* The billwerk entities helper.
* @param \Drupal\billwerk_subscriptions\Environment $environment
* The environment.
* @param \Drupal\billwerk_subscriptions\Api $api
* The API.
* @param \Drupal\Core\Entity\EntityTypeManagerInterface $entityTypeManager
* The entity type manager.
* @param \Drupal\Core\Language\LanguageManagerInterface $language_manager
* The language manager.
*/
public function __construct(
// @improve:
// These should be "readonly", but that's currently not possible on
// multi-page forms due to a dependency injection bug leading to an error:
// Error: Cannot initialize readonly property Drupal\billwerk_subscriptions_manage\Form\BillwerkSubscriptionjsFormAbstract::$account from scope Drupal\Core\Form\FormBase in Drupal\Core\Form\FormBase->__wakeup() (line 89 of core/lib/Drupal/Core/DependencyInjection/DependencySerializationTrait.php).
protected BillwerkEntitiesHelper $billwerkEntitiesHelper,
protected Environment $environment,
protected Api $api,
protected EntityTypeManagerInterface $entityTypeManager,
protected LanguageManagerInterface $language_manager,
) {
$currentUserId = (int) $this->currentUser()->id();
$this->subscriberBillwerkEntitiesHelper = SubscriberBillwerkEntitiesHelper::create(Subscriber::loadByDrupalUid($currentUserId), $billwerkEntitiesHelper, $environment);
$this->subscriber = Subscriber::loadByDrupalUid($currentUserId);
$this->languageManager = $language_manager;
}
/**
* {@inheritdoc}
*/
public static function create(ContainerInterface $container) {
return new static(
$container->get('billwerk_subscriptions_entities.billwerk_entities_helper'),
$container->get('billwerk_subscriptions.environment'),
$container->get('billwerk_subscriptions.api'),
$container->get('entity_type.manager'),
$container->get('language_manager'),
);
}
/**
* {@inheritdoc}
*/
public function buildForm(array $form, FormStateInterface $form_state): array {
$form['current_user'] = [
'#type' => 'item',
'#title' => '<strong>' . $this->t('Your username:') . '</strong>',
'#markup' => $this->currentUser()->getDisplayName(),
'#wrapper_attributes' => ['class' => ['container-inline']],
];
$activeBillwerkPlanVariant = $this->subscriberBillwerkEntitiesHelper->getActiveBillwerkPlanVariant();
if (empty($activeBillwerkPlanVariant)) {
$form['no_active_subscription'] = [
'#type' => 'item',
'#title' => '<strong>' . $this->t('Your current plan:') . '</strong>',
'#markup' => $this->t('No active subscription'),
'#attributes' => [
'class' => 'nobillwerk-subscriptions--no-active-subscription',
],
'#wrapper_attributes' => ['class' => ['container-inline']],
];
return $form;
}
$form['current_plan_variant'] = [
'#type' => 'item',
'#title' => '<strong>' . $this->t('Your current plan:') . '</strong>',
'#markup' => $activeBillwerkPlanVariant->label(),
// Render as card:
// 'content' => $this->entityTypeManager->getViewBuilder('billwerk_plan_variant')->view($activeBillwerkPlanVariant, 'card'),. // @codingStandardsIgnoreLine
'#wrapper_attributes' => ['class' => ['container-inline']],
];
switch ($form_state->get('step')) {
case 'confirm':
$form = $this->buildConfirmForm($form, $form_state);
break;
default:
$form = $this->buildSelectionForm($form, $form_state);
break;
}
// Add this library to prevent duplicate form submits:
$form['#attached']['library'][] = 'core/drupal.form';
// Add a class to the form to identify it:
$form['#attributes']['class'][] = 'billwerk-subscriptions-change-form';
return $form;
}
/**
* Builds the selection form.
*
* @param array $form
* The form.
* @param \Drupal\Core\Form\FormStateInterface $form_state
* The form state.
*/
abstract protected function buildSelectionForm(array $form, FormStateInterface $form_state): array;
/**
* Builds a plan variant change form element.
*
* @param array $form
* The form.
* @param \Drupal\Core\Form\FormStateInterface $form_state
* The form state.
*/
protected function buildPlanVariantChangeFormElement(array &$form, FormStateInterface $form_state) {
$activePlanVariant = $this->subscriberBillwerkEntitiesHelper->getActiveBillwerkPlanVariant();
$activePlanVariantMachineName = $activePlanVariant->getMachineName();
$planVariantOptions = $this->billwerkEntitiesHelper->getPlanVariantsAllSelectOptions('card');
if (!empty($planVariantOptions)) {
$planVariantGet = $this->getRequest()->query->get('planvariant');
$preselectedPlanVariant = !empty($planVariantGet) && in_array($planVariantGet, $planVariantOptions) ? $planVariantGet : $activePlanVariantMachineName;
$form['planvariant'] = [
'#type' => 'radios',
'#title' => $this->t('Change subscription plan:'),
'#options' => self::optionsArrayRender($planVariantOptions),
'#default_value' => $form_state->getValue('planvariant', $preselectedPlanVariant),
'#required' => TRUE,
// Disable the current plan:
$activePlanVariantMachineName => ['#disabled' => TRUE],
];
// Mark the currently active plan variant:
$form['planvariant'][$activePlanVariantMachineName]['#wrapper_attributes']['class'][] = 'form-item--active';
$form['planvariant'][$activePlanVariantMachineName]['#attributes']['class'][] = 'active';
}
}
/**
* Build the components subscribe form element.
*
* @param array $form
* The form.
* @param \Drupal\Core\Form\FormStateInterface $form_state
* The form state.
*/
protected function buildComponentsSubscribeFormElement(array &$form, FormStateInterface $form_state) {
// Components:
$activeComponents = $this->subscriberBillwerkEntitiesHelper->getActiveBillwerkComponents();
$componentSubscribeOptions = $this->billwerkEntitiesHelper->getComponentsSubscribeSelectOptions(array_keys($activeComponents), 'card');
if (!empty($componentSubscribeOptions)) {
$componentGet = $this->getRequest()->query->get('component');
// We're using the machine names as keys to not expose the Billwerk IDs:
$form['components_subscribe'] = [
'#type' => 'checkboxes',
'#title' => $this->t('Extend your subscription with add-ons'),
'#options' => self::optionsArrayRender($componentSubscribeOptions),
'#default_value' => $form_state->getValue('components_subscribe', in_array($componentGet, array_keys($componentSubscribeOptions)) ? [$componentGet] : []),
'#multiple' => TRUE,
'#description' => $this->t('Add these add-ons to your subscription'),
];
}
}
/**
* Build the components unsubscribe form element.
*
* @param array $form
* The form.
* @param \Drupal\Core\Form\FormStateInterface $form_state
* The form state.
*/
protected function buildComponentsUnsubscribeFormElement(array &$form, FormStateInterface $form_state) {
$activeComponents = $this->subscriberBillwerkEntitiesHelper->getActiveBillwerkComponents(TRUE);
$componentUnsubscribeOptions = $this->billwerkEntitiesHelper->getComponentsUnsubscribeSelectOptions(array_keys($activeComponents), 'card');
if (!empty($componentUnsubscribeOptions)) {
$componentGet = $this->getRequest()->query->get('component');
// We're using the machine names as keys to not expose the Billwerk IDs:
$form['components_unsubscribe'] = [
'#type' => 'checkboxes',
'#title' => $this->t('Cancel add-ons'),
'#options' => self::optionsArrayRender($componentUnsubscribeOptions),
'#default_value' => $form_state->getValue('components_unsubscribe', in_array($componentGet, array_keys($componentUnsubscribeOptions)) ? [$componentGet] : []),
'#multiple' => TRUE,
'#description' => $this->t('The selected add-ons will be canceled from your subscription at the end of the contract period'),
];
}
}
/**
* Build the coupon form element.
*
* @param array $form
* The form.
* @param \Drupal\Core\Form\FormStateInterface $form_state
* The form state.
*/
protected function buildCouponFormElement(array &$form, FormStateInterface $form_state) {
$form['coupon'] = [
'#type' => 'details',
'#title' => $this->t('Coupon'),
'#open' => FALSE,
];
$form['coupon']['couponcode'] = [
'#type' => 'textfield',
'#title' => $this->t('Coupon code'),
'#description' => $this->t('If you have a coupon code, enter it here'),
'#default_value' => $form_state->getValue('couponcode', ''),
'#required' => FALSE,
];
}
/**
* Build the order table form element.
*
* @param array $form
* The form.
* @param \Drupal\Core\Form\FormStateInterface $form_state
* The form state.
* @param \stdClass $billwerkOrderObj
* The Billwerk order object.
* @param array $displayOptions
* The display options to pass.
*/
protected function buildOrderTableFormElement(array &$form, FormStateInterface $form_state, \stdClass $billwerkOrderObj, array $displayOptions = []) {
if (!empty($billwerkOrderObj)) {
$form['order_table'] = self::billwerkOrderDtoToRenderArray($billwerkOrderObj, $displayOptions);
}
}
/**
* Build the order address form element.
*
* @param array $form
* The form.
* @param \Drupal\Core\Form\FormStateInterface $form_state
* The form state.
* @param \stdClass $billwerkOrderObj
* The Billwerk order object.
*/
protected function buildOrderAddressFormElement(array &$form, FormStateInterface $form_state, \stdClass $billwerkOrderObj) {
$form['order_address'] = [
'#type' => 'fieldset',
'#title' => $this->t('Billing address'),
'#description' => $this->t("The values entered here will be used for this and future orders.") . ' ' . $this->t('You can edit your address and payment information in your <a href="@user_profile_url" target="_blank">user profile</a> at any time.', ['@user_profile_url' => Url::fromRoute('billwerk_subscriptions_manage.user_subscription_selfservice', ['user' => $this->currentUser()->id()])->toString()]),
];
$form['order_address']['CompanyName'] = [
'#type' => 'textfield',
'#title' => $this->t('Company'),
'#required' => TRUE,
'#size' => 30,
'#default_value' => $form_state->getValue('CompanyName', $billwerkOrderObj->Customer->CompanyName ?? NULL),
];
$form['order_address']['FirstName'] = [
'#type' => 'textfield',
'#title' => $this->t('First name'),
// Billwerk returns an error if not filled even though we wouldn't need
// this value:
'#required' => TRUE,
'#size' => 30,
'#default_value' => $form_state->getValue('FirstName', $billwerkOrderObj->Customer->FirstName ?? NULL),
];
$form['order_address']['LastName'] = [
'#type' => 'textfield',
'#title' => $this->t('Last name'),
// Billwerk returns an error if not filled even though we wouldn't need
// this value:
'#required' => TRUE,
'#size' => 30,
'#default_value' => $form_state->getValue('LastName', $billwerkOrderObj->Customer->LastName ?? NULL),
];
// @codingStandardsIgnoreStart
// $form['order_address']['AddressLine1'] = [
// '#type' => 'textfield',
// '#title' => $this->t('Address line 1'),
// '#required' => TRUE,
// '#size' => 30,
// '#default_value' => $billwerkOrderObj->Customer->AddressLine1 ?? NULL,
// ];
// $form['order_address']['AddressLine2'] = [
// '#type' => 'textfield',
// '#title' => $this->t('Address line 2'),
// '#size' => 30,
// '#default_value' => $billwerkOrderObj->Customer->AddressLine2 ?? NULL,
// ];
// @codingStandardsIgnoreEnd
$form['order_address']['Street'] = [
'#type' => 'textfield',
'#title' => $this->t('Street'),
'#required' => TRUE,
'#size' => 30,
'#default_value' => $form_state->getValue('Street', $billwerkOrderObj->Customer->Address->Street ?? NULL),
];
$form['order_address']['HouseNumber'] = [
'#type' => 'textfield',
'#title' => $this->t('House number'),
'#required' => TRUE,
'#size' => 5,
'#default_value' => $form_state->getValue('HouseNumber', $billwerkOrderObj->Customer->Address->HouseNumber ?? NULL),
];
$form['order_address']['PostalCode'] = [
'#type' => 'textfield',
'#title' => $this->t('Postal code'),
'#size' => 5,
'#required' => TRUE,
'#default_value' => $form_state->getValue('PostalCode', $billwerkOrderObj->Customer->Address->PostalCode ?? NULL),
];
$form['order_address']['City'] = [
'#type' => 'textfield',
'#title' => $this->t('City'),
'#required' => TRUE,
'#size' => 30,
'#default_value' => $form_state->getValue('City', $billwerkOrderObj->Customer->Address->City ?? NULL),
];
$form['order_address']['Country'] = [
'#type' => 'address_country',
// '#available_countries' => ['DE', 'FR'],
'#title' => $this->t('Country'),
'#required' => TRUE,
'#default_value' => $form_state->getValue('Country', strtoupper($billwerkOrderObj->Customer->Address->Country ?? '') ?: 'DE'),
];
$form['order_address']['VatId'] = [
'#type' => 'textfield',
'#title' => $this->t('VAT ID'),
'#size' => 15,
'#default_value' => $form_state->getValue('VatId', $billwerkOrderObj->Customer->VatId ?? NULL),
];
}
/**
* Build the order payment form element.
*
* @param array $form
* The form.
* @param \Drupal\Core\Form\FormStateInterface $form_state
* The form state.
* @param \stdClass $billwerkOrderObj
* The Billwerk order object.
*/
protected function buildOrderPaymentFormElement(array &$form, FormStateInterface $form_state, \stdClass $billwerkOrderObj) {
$paymentFormWrapperId = 'subscriptionjs-wrapper';
$subscriberContractDetails = $this->subscriber->billwerkGetContractDetails();
$form['payment'] = [
'#type' => 'fieldset',
'#title' => $this->t('Payment'),
'#description' => $this->t('You can edit your address and payment information in your <a href="@user_profile_url" target="_blank">user profile</a> at any time.', ['@user_profile_url' => Url::fromRoute('billwerk_subscriptions_manage.user_subscription_selfservice', ['user' => $this->currentUser()->id()])->toString()]),
];
$form['payment']['subscriptionjs_payment_wrapper'] = [
'#type' => 'html_tag',
'#tag' => 'div',
'#value' => $this->t('Your configured payment method will be used.'),
'#attributes' => [
'id' => $paymentFormWrapperId,
],
];
$form['#attached']['library'][] = 'billwerk_subscriptions_manage/billwerk_subscriptions_manage';
$form['#attached']['drupalSettings']['billwerk_context'] = 'form';
$form['#attached']['drupalSettings']['billwerk']['selfserviceToken'] = $this->subscriber->billwerkGetSelfserviceToken();
$form['#attached']['drupalSettings']['billwerk']['selfservicePublicApiKey'] = $this->environment->getSelfservicePublicApiKey();
$form['#attached']['drupalSettings']['billwerk']['userLocale'] = $this->languageManager->getCurrentLanguage()->getId();
$form['#attached']['drupalSettings']['billwerk']['providerReturnUrl'] = $this->getProviderReturnUrl();
$form['#attached']['drupalSettings']['billwerk']['currentContractPaymentProvider'] = $subscriberContractDetails['PaymentProvider'];
$form['#attached']['drupalSettings']['billwerk']['paymentFormWrapperId'] = $paymentFormWrapperId;
$form['#attached']['drupalSettings']['billwerk']['order'] = [
// @see: https://billwerk.readme.io/reference/subscriptionjsportal
// The order object to be paid for. This object should have been created
// by one of the following methods: SubscriptionJS.Signup.createOrder(), a
// backend API call, or through the Billwerk+ Premium & Enterprise user
// interface. It is expected to be structured as follows:
// {"OrderId" : "order_id_value", "GrossTotal" : numeric_value,
// "Currency" : "currency_code" }.
'OrderId' => $billwerkOrderObj->Id,
'GrossTotal' => $billwerkOrderObj->TotalGross,
'Currency' => $billwerkOrderObj->Currency,
];
}
/**
* Returns the provider return URL after the subscription has been changed.
*
* @return string
* The absolute URL.
*/
protected function getProviderReturnUrl(): string {
// Improve: If this is ONLY called for CHANGES and not even for cancel, we
// can remove this method and put the callback URL directly into the values
// above, where called, perhaps.
return Url::fromRoute('billwerk_subscriptions_manage.current_user_subscription_finished_change')->setAbsolute(TRUE)->toString();
}
/**
* Build the general order terms form element.
*
* @param array $form
* The form.
* @param \Drupal\Core\Form\FormStateInterface $form_state
* The form state.
*/
protected function buildGeneralOrderTermsFormElement(array &$form, FormStateInterface $form_state) {
$orderTerms = $this->config('billwerk_subscriptions_manage.settings')->get('order_terms');
if (!empty($orderTerms)) {
$form['order_terms'] = [
'#type' => 'processed_text',
'#text' => $orderTerms['value'],
'#format' => $orderTerms['format'],
];
}
}
/**
* Build the upgrade order terms form element.
*
* @param array $form
* The form.
* @param \Drupal\Core\Form\FormStateInterface $form_state
* The form state.
*/
protected function buildUpgradeOrderTermsFormElement(array &$form, FormStateInterface $form_state) {
$orderTerms = $this->config('billwerk_subscriptions_manage.settings')->get('order_terms_upgrade');
if (!empty($orderTerms)) {
$form['order_terms_upgrade'] = [
'#type' => 'processed_text',
'#text' => $orderTerms['value'],
'#format' => $orderTerms['format'],
];
}
}
/**
* Build the downgrade order terms form element.
*
* @param array $form
* The form.
* @param \Drupal\Core\Form\FormStateInterface $form_state
* The form state.
*/
protected function buildDowngradeOrderTermsFormElement(array &$form, FormStateInterface $form_state) {
$orderTerms = $this->config('billwerk_subscriptions_manage.settings')->get('order_terms_downgrade');
if (!empty($orderTerms)) {
$form['order_terms_downgrade'] = [
'#type' => 'processed_text',
'#text' => $orderTerms['value'],
'#format' => $orderTerms['format'],
];
}
}
/**
* Build the order actions form element.
*
* @param array $form
* The form.
* @param \Drupal\Core\Form\FormStateInterface $form_state
* The form state.
* @param \Drupal\Core\StringTranslation\TranslatableMarkup $submitLabel
* The submit label.
*/
protected function buildOrderActionsFormElement(array &$form, FormStateInterface $form_state, TranslatableMarkup $submitLabel) {
$form['actions']['#type'] = 'actions';
$form['actions']['back'] = [
'#type' => 'link',
'#title' => $this->t('Back'),
// Back to the first page (current route):
'#url' => Url::fromRoute($this->getRouteMatch()->getRouteName()),
'#attributes' => [
'class' => [
'button',
'button--back',
],
],
];
$form['actions']['submit'] = [
'#type' => 'submit',
// '#submit' => ['::submitConfirmForm'],
// '#validate' => ['::validateConfirmForm'],
'#value' => $submitLabel,
'#button_type' => 'primary',
];
}
/**
* Build the order actions fake form element.
*
* @param array $form
* The form.
* @param \Drupal\Core\Form\FormStateInterface $form_state
* The form state.
* @param \Drupal\Core\StringTranslation\TranslatableMarkup $submitLabel
* The submit label.
*/
protected function buildOrderActionsFakeFormElement(array &$form, FormStateInterface $form_state, TranslatableMarkup $submitLabel) {
$form['actions']['#type'] = 'actions';
$form['actions']['back'] = [
'#type' => 'link',
'#title' => $this->t('Back'),
// Back to the first page (current route):
'#url' => Url::fromRoute($this->getRouteMatch()->getRouteName()),
'#attributes' => [
'class' => [
'button',
'button--back',
],
],
];
// For the JS payment we may not use a real submit button, but a fake submit
// form element. The submit steps are all client-side:
$form['actions']['submit'] = [
'#type' => 'submit',
// '#submit' => ['::submitConfirmForm'],
// '#validate' => ['::validateConfirmForm'],
'#value' => $submitLabel,
'#id' => 'buy',
'#attributes' => [
'onclick' => 'event.preventDefault();',
],
'#button_type' => 'primary',
];
}
/**
* Build the confirm form element.
*
* @param array $form
* The form.
* @param \Drupal\Core\Form\FormStateInterface $form_state
* The form state.
*/
abstract protected function buildConfirmForm(array $form, FormStateInterface $form_state);
/**
* Get the new plan variant id.
*
* @param \Drupal\Core\Form\FormStateInterface $form_state
* The form state.
*/
protected function valueGetPlanvariant(FormStateInterface $form_state): string {
$selectedPlanVariantMachineName = $form_state->getValue('planvariant');
if (!empty($selectedPlanVariantMachineName)) {
$newPlanVariantEntity = $this->billwerkEntitiesHelper->getBillwerkPlanVariantByMachineName($selectedPlanVariantMachineName);
$newPlanVariantId = $newPlanVariantEntity->getBillwerkId($this->environment->getEnvironmentName());
}
else {
// No changed plan variant given. Keep the old one.
$newPlanVariantId = $this->subscriberBillwerkEntitiesHelper->getActiveBillwerkPlanVariant()->getBillwerkId($this->environment->getEnvironmentName());
}
return $newPlanVariantId;
}
/**
* Get the new component subscription ids array.
*
* @param \Drupal\Core\Form\FormStateInterface $form_state
* The form state.
*/
protected function valueGetComponentsSubscribe(FormStateInterface $form_state): array {
$newComponentSubscriptionIds = [];
$selectedBookComponentsMachineNames = $form_state->getValue('components_subscribe');
if (!empty($selectedBookComponentsMachineNames)) {
foreach ($selectedBookComponentsMachineNames as $selectedComponentsMachineName => $value) {
$componentEntity = $this->billwerkEntitiesHelper->getBillwerkComponentByMachineName($selectedComponentsMachineName);
$componentBillwerkId = $componentEntity->getBillwerkId($this->environment->getEnvironmentName());
// Drupal FAPI sets the array value to "0" for unchecked checkboxes:
if (!empty($value)) {
// Add the component which the user selected and wasn't subscribed to
// yet:
$newComponentSubscriptionIds[$componentBillwerkId] = $componentBillwerkId;
}
}
}
return $newComponentSubscriptionIds;
}
/**
* Get the new component unsubscribe ids array.
*
* @param \Drupal\Core\Form\FormStateInterface $form_state
* The form state.
*/
protected function valueGetComponentsUnsubscribe(FormStateInterface $form_state): array {
$endComponentSubscriptionIds = [];
$selectedEndComponentsMachineNames = $form_state->getValue('components_unsubscribe');
if (!empty($selectedEndComponentsMachineNames)) {
foreach ($selectedEndComponentsMachineNames as $selectedComponentsMachineName => $value) {
$componentEntity = $this->billwerkEntitiesHelper->getBillwerkComponentByMachineName($selectedComponentsMachineName);
$componentBillwerkId = $componentEntity->getBillwerkId($this->environment->getEnvironmentName());
// Drupal FAPI sets the array value to "0" for unchecked checkboxes:
if (!empty($value)) {
// The user is currently subscribed, so this may be ended:
$endComponentSubscriptionIds[$componentBillwerkId] = $componentBillwerkId;
}
}
}
return $endComponentSubscriptionIds;
}
/**
* Get the coupon code.
*
* @param \Drupal\Core\Form\FormStateInterface $form_state
* The form state.
*/
protected function valueGetCouponcode(FormStateInterface $form_state) {
return (string) $form_state->getValue('couponcode');
}
/**
* Converts the billwerk Order DTO object to a render array.
*
* @param \stdClass $billwerkOrderObj
* The Billwerk order object.
* @param array $displayOptions
* Optional array of display options to pass to the template.
*/
protected static function billwerkOrderDtoToRenderArray(\stdClass $billwerkOrderObj, $displayOptions = []): array {
$userLocale = \Drupal::languageManager()->getCurrentLanguage()->getId();
return [
'#theme' => 'billwerk_order',
'#id' => $billwerkOrderObj->Id,
'#planVariantId' => $billwerkOrderObj->PlanVariantId ?? NULL,
'#planId' => $billwerkOrderObj->PlanId ?? NULL,
'#allowWithoutPaymentData' => $billwerkOrderObj->AllowWithoutPaymentData ?? NULL,
'#lineitems' => $billwerkOrderObj->LineItems ?? [],
'#coupon' => $billwerkOrderObj->Coupon ?? [],
'#currency' => $billwerkOrderObj->Currency ?? NULL,
'#total' => $billwerkOrderObj->Total ?? NULL,
'#totalVat' => $billwerkOrderObj->TotalVat ?? NULL,
'#totalGross' => $billwerkOrderObj->TotalGross ?? NULL,
'#nextTotalGross' => $billwerkOrderObj->NextTotalGross ?? NULL,
'#nextTotalGrossDate' => $billwerkOrderObj->NextTotalGrossDate ?? NULL,
'#isTrial' => $billwerkOrderObj->IsTrial ?? NULL,
'#planName' => $billwerkOrderObj->PlanName ?? NULL,
'#planVariantName' => $billwerkOrderObj->PlanVariantName ?? NULL,
'#orderType' => $billwerkOrderObj->OrderType ?? NULL,
'#contractCustomFields' => [],
'#userLocale' => $userLocale,
'#customer' => [
'#theme' => 'billwerk_customer',
'#companyName' => $billwerkOrderObj->Customer->CompanyName ?? NULL,
'#firstName' => $billwerkOrderObj->Customer->FirstName ?? NULL,
'#lastName' => $billwerkOrderObj->Customer->LastName ?? NULL,
'#addressLine1' => $billwerkOrderObj->Customer->AddressLine1 ?? NULL,
'#addressLine2' => $billwerkOrderObj->Customer->AddressLine2 ?? NULL,
'#street' => $billwerkOrderObj->Customer->Street ?? NULL,
'#houseNumber' => $billwerkOrderObj->Customer->HouseNumber ?? NULL,
'#country' => $billwerkOrderObj->Customer->Country ?? NULL,
'#postalCode' => $billwerkOrderObj->Customer->PostalCode ?? NULL,
'#city' => $billwerkOrderObj->Customer->City ?? NULL,
'#state' => $billwerkOrderObj->Customer->State ?? NULL,
'#formattedStreetAddressLine' => $billwerkOrderObj->Customer->FormattedStreetAddressLine ?? NULL,
'#formattedCityAddressLine' => $billwerkOrderObj->Customer->FormattedCityAddressLine ?? NULL,
'#vatId' => $billwerkOrderObj->Customer->VatId ?? NULL,
'#emailAddress' => $billwerkOrderObj->Customer->EmailAddress ?? NULL,
'#attributes' => [],
],
'#attributes' => [],
'#displayOptions' => $displayOptions ?? [],
];
}
/**
* Proceed to the confirm form.
*/
public static function proceedToConfirm(array &$form, FormStateInterface $form_state) {
$form_state->set('step', 'confirm')->setRebuild(TRUE);
}
/**
* Validate the confirm form.
*/
public static function validateConfirmForm(array &$form, FormStateInterface $form_state) {
// @todo Implement this:
// dsm('validateConfirmForm()');
throw new \Exception('This was not expected to be called!');
}
/**
* Submit the confirm form.
*/
public static function submitConfirmForm(array &$form, FormStateInterface $form_state) {
// @todo What needs to be done here?
// $form_state->set('step', NULL);
// $form_state->setUserInput([]);
// $form_state->setRebuild();
// dsm('submitConfirmForm()');
throw new \Exception('This was not expected to be called!');
}
/**
* Render the options array.
*/
protected static function optionsArrayRender(array $optionsArray): array {
array_walk($optionsArray, function (&$value, $key) {
if (is_array($value)) {
$value = \Drupal::service('renderer')->renderRoot($value);
}
});
return $optionsArray;
}
}
