contacts_subscriptions-1.x-dev/src/Controller/SubscriptionController.php

src/Controller/SubscriptionController.php
<?php

namespace Drupal\contacts_subscriptions\Controller;

use CommerceGuys\Intl\Formatter\CurrencyFormatterInterface;
use Drupal\contacts_subscriptions\InvoiceManager;
use Drupal\contacts_subscriptions\SubscriptionsHelper;
use Drupal\Core\Access\CsrfTokenGenerator;
use Drupal\Core\Controller\ControllerBase;
use Drupal\Core\Datetime\DateFormatterInterface;
use Drupal\Core\Entity\EntityTypeManagerInterface;
use Drupal\Core\Form\FormBuilderInterface;
use Drupal\Core\Link;
use Drupal\user\UserInterface;
use Symfony\Component\DependencyInjection\ContainerInterface;

/**
 * Returns responses for Contacts Jobs Subscriptions routes.
 */
class SubscriptionController extends ControllerBase {

  /**
   * The date formatter.
   *
   * @var \Drupal\Core\Datetime\DateFormatterInterface
   */
  protected DateFormatterInterface $dateFormatter;

  /**
   * The currency formatter.
   *
   * @var \CommerceGuys\Intl\Formatter\CurrencyFormatterInterface
   */
  protected CurrencyFormatterInterface $currencyFormatter;

  /**
   * The CSRF token generator.
   *
   * @var \Drupal\Core\Access\CsrfTokenGenerator
   */
  protected CsrfTokenGenerator $csrf;

  /**
   * The invoice manager.
   *
   * @var \Drupal\contacts_subscriptions\InvoiceManager
   */
  protected InvoiceManager $invoiceManager;

  /**
   * The Subscriptions helper service.
   *
   * @var \Drupal\contacts_subscriptions\SubscriptionsHelper
   */
  protected SubscriptionsHelper $subscriptionsHelper;

  /**
   * The controller constructor.
   *
   * @param \Drupal\Core\Entity\EntityTypeManagerInterface $entity_type_manager
   *   The entity type manager.
   * @param \Drupal\Core\Datetime\DateFormatterInterface $date_formatter
   *   The date formatter.
   * @param \CommerceGuys\Intl\Formatter\CurrencyFormatterInterface $currency_formatter
   *   The currency formatter.
   * @param \Drupal\Core\Form\FormBuilderInterface $form_builder
   *   The form builder.
   * @param \Drupal\Core\Access\CsrfTokenGenerator $csrf
   *   The CSRF token generator.
   * @param \Drupal\contacts_subscriptions\InvoiceManager $invoice_manager
   *   The invoice manager.
   * @param \Drupal\contacts_subscriptions\SubscriptionsHelper $subscriptions_helper
   *   The subscriptions helper.
   */
  public function __construct(
    EntityTypeManagerInterface $entity_type_manager,
    DateFormatterInterface $date_formatter,
    CurrencyFormatterInterface $currency_formatter,
    FormBuilderInterface $form_builder,
    CsrfTokenGenerator $csrf,
    InvoiceManager $invoice_manager,
    SubscriptionsHelper $subscriptions_helper,
  ) {
    $this->entityTypeManager = $entity_type_manager;
    $this->dateFormatter = $date_formatter;
    $this->currencyFormatter = $currency_formatter;
    $this->formBuilder = $form_builder;
    $this->csrf = $csrf;
    $this->invoiceManager = $invoice_manager;
    $this->subscriptionsHelper = $subscriptions_helper;
  }

  /**
   * {@inheritdoc}
   */
  public static function create(ContainerInterface $container) {
    $controller = new static(
      $container->get('entity_type.manager'),
      $container->get('date.formatter'),
      $container->get('commerce_price.currency_formatter'),
      $container->get('form_builder'),
      $container->get('csrf_token'),
      $container->get('contacts_subscriptions.invoice_manager'),
      $container->get('contacts_subscriptions.helper')
    );
    $controller->setMessenger($container->get('messenger'));
    return $controller;
  }

  /**
   * Builds the overview page.
   *
   * @return array
   *   The render array.
   */
  public function overview(UserInterface $user) {
    $build = [
      '#cache' => [
        'tags' => ['contacts_subscription_list'],
        'contexts' => ['url.query_args'],
      ],
    ];

    /** @var \Drupal\contacts_subscriptions\Entity\SubscriptionInterface $subscription */
    $groups = [
      [
        'user' => $user,
        'subscriptions' => $this->entityTypeManager
          ->getStorage('contacts_subscription')
          ->loadByUser($user),
      ],
    ];

    if ($user->hasPermission('manage my organisation membership')) {
      if ($user->hasField('organisations')) {
        foreach ($user->organisations as $item) {
          if ($group = $item->membership->getGroup()) {
            $groups[] = [
              'user' => $group->contacts_org->entity,
              'subscriptions' => $this->entityTypeManager
                ->getStorage('contacts_subscription')
                ->loadByUser($group->contacts_org->entity),
            ];
          }
        }
      }
    }

    foreach ($groups as $data) {
      $group_name = 'group_' . $data['user']->id();
      $build[$group_name] = [
        '#type' => 'container',
        'title' => [
          '#type' => 'html_tag',
          '#tag' => 'h3',
          '#value' => $this->t('Memberships for :user', [
            ':user' => $data['user']->getDisplayName(),
          ]),
        ],
      ];
      $common_route_params = [
        'user' => $data['user']->id(),
      ];

      foreach ($data['subscriptions'] as $subscription) {
        // Get the activation route depending on whether payment details need to
        // be collected/ve-validated.
        $activate_route = $subscription->needsPaymentDetails() ?
          'contacts_subscriptions.subscription_payment' :
          'contacts_subscriptions.subscription_activate';

        $show_intro_offer = FALSE;
        $intro_offer_products = [];

        // Will renew means an ongoing subscription.
        if ($subscription->willRenew()) {
          $this->messenger->addMessage($this->t(':user %subname membership is due for renewal on %renewal.', [
            '%renewal' => $this->dateFormatter->format($subscription->getRenewalDate()
              ->getTimestamp(), 'short_date'),
            '%subname' => $subscription->bundle(),
            ':user' => $data['user']->getDisplayName() . "'s",
          ]));

          if (!$subscription->canChangeProduct()) {
            $this->messenger->addMessage($this->t(':user has changed their membership to %product. The next renewal will be at the new price. You cannot change again this billing cycle.', [
              '%product' => $subscription->getProduct(FALSE, FALSE)->label(),
              ':user' => $data['user']->getDisplayName(),
            ]));
          }
        }
        // Flag payment issues.
        elseif ($subscription->needsPaymentDetails()) {
          if ($expiry = $this->invoiceManager->getExpiry($subscription)) {
            $this->messenger->addError($this->t(':user membership payment failed. Please @link to check the payment details. :user membership will end on %end.', [
              '@link' => Link::createFromRoute('click here', $activate_route, $common_route_params)
                ->toString(),
              '%end' => $this->dateFormatter->format($expiry->getTimestamp(), 'short_date'),
              ':user' => $data['user']->getDisplayName() . "'s",
            ]));
          }
          else {
            $this->messenger->addError($this->t(':user membership payment failed. Please @link to check the payment details.', [
              '@link' => Link::createFromRoute('click here', $activate_route, $common_route_params)
                ->toString(),
              ':user' => $data['user']->getDisplayName() . "'s",
            ]));
          }
        }
        // Any other currently active status means the subscription is pending
        // cancellation.
        elseif ($subscription->isActive()) {
          $this->messenger->addWarning($this->t(':user has cancelled their membership and it will end on %end. Please @link to re-activate.', [
            '@link' => Link::createFromRoute('click here', $activate_route, $common_route_params)
              ->toString(),
            '%end' => $this->dateFormatter->format($subscription->getExpiryDate()
              ->getTimestamp(), 'short_date'),
            ':user' => $data['user']->getDisplayName(),
          ]));
        }
        // Inform if they have expired due to now payment.
        elseif ($subscription->getStatusId() === 'expired_payment') {
          $this->messenger->addError($this->t(':user membership has expired due to no payment.', [
            ':user' => $data['user']->getDisplayName() . "'s",
          ]));
        }
        // If there has never been a subscription, show introductory offers.
        elseif ($subscription->getStatusId() === 'none') {
          $show_intro_offer = TRUE;
          $intro_offer_products = $this->subscriptionsHelper->getProducts($data['user'], 'INTRO');
        }
      }

      $build[$group_name]['products'] = [
        '#theme' => 'contacts_subscription_options',
        '#show_intro_offer' => $show_intro_offer ?? FALSE,
      ];

      /** @var \Drupal\contacts_subscriptions\Entity\SubscriptionType $subscription_type */
      $types = $this->entityTypeManager->getStorage('contacts_subscription_type')->loadMultiple();
      $types = array_reverse($types);
      foreach ($types as $subscription_type) {
        $current_subscription = array_filter($data['subscriptions'], function ($value) use ($subscription_type) {
          return $value->bundle() === $subscription_type->id();
        });
        if (count($current_subscription) === 1) {
          $current_subscription = reset($current_subscription);
        }
        foreach ($this->subscriptionsHelper->getProductsOfType($data['user'], $subscription_type) as $product_id => $variation) {
          $standard_variation_id = NULL;
          $product = $variation->getProduct();

          $build[$group_name]['products']['#options'][$product_id] = [
            '#variation' => $variation,
            'title' => $product->label(),
            'description' => $product->get('body')->view(['label' => 'hidden']),
          ];

          $build[$group_name]['products']['#cache']['tags'][] = $variation->getEntityTypeId() . ':' . $variation->id();
          $option = &$build[$group_name]['products']['#options'][$product_id];

          // Work out any price text.
          $price = $variation->getPrice();
          if ($price && $price->isPositive()) {
            $option['price'] = $this->currencyFormatter->format($price->getNumber(), $price->getCurrencyCode());
          }

          // If we have an introductory offer, store the standard variation ID
          // for links, swap out the working variation and set the intro price
          // text.
          if (isset($intro_offer_products[$product_id]) && $intro_offer_products[$product_id]->id() !== $variation->id()) {
            $standard_variation_id = $variation->id();
            $variation = $intro_offer_products[$product_id];

            // If we have a price, show it.
            $intro_price = $variation->getPrice();
            if ($intro_price && $intro_price->isPositive()) {
              $option['price_intro'] = $this->t('Initially @price', [
                '@price' => $this->currencyFormatter->format($intro_price->getNumber(), $intro_price->getCurrencyCode()),
              ]);
            }
            // Otherwise, use free text.
            else {
              $option['price_intro'] = $this->t('Initially free');
            }
          }

          // Work out the correct links.
          if ($current_subscription && $product_id === $current_subscription->getProductId(TRUE, TRUE)) {
            $option['is_active'] = TRUE;

            if ($current_subscription->willRenew()) {
              if ($current_subscription->canChangeProduct()) {
                $route_parameters = [
                  'subscription' => $current_subscription->id(),
                ] + $common_route_params;
                $option['link'] = Link::createFromRoute($this->t('Cancel renewal'), 'contacts_subscriptions.subscription_cancel', $route_parameters);
                $option['link_is_cancel'] = TRUE;
              }
            }
            else {
              // @todo Handle multiple variations.
              $option['link'] = Link::createFromRoute($this->t('Re-activate'), $activate_route, [
                'commerce_product_variation' => $variation->id(),
                'token' => $this->csrf->get($current_subscription->getCsrfValue($variation)),
              ] + $common_route_params);
            }
          }
          elseif ($current_subscription && $current_subscription->isActive()) {
            if ($current_subscription->canChangeProduct()) {
              $route_parameters = [
                'commerce_product_variation' => $variation->id(),
                'token' => $this->csrf->get($current_subscription->getCsrfValue($variation)),
              ] + $common_route_params;

              if ($current_subscription->willRenew()) {
                $option['link'] = Link::createFromRoute($this->t('Switch'), 'contacts_subscriptions.subscription_activate', $route_parameters);
              }
              // Only show the re-activate and switch link if we don't need
              // payment  details.
              elseif (!$current_subscription->needsPaymentDetails()) {
                $option['link'] = Link::createFromRoute($this->t('Re-activate & switch'), 'contacts_subscriptions.subscription_payment', $route_parameters);
              }
            }
          }
          else {

            // Only show the create option if the subscription can be created
            // for that kind of user.
            $who_can = $subscription_type->getWhoCanPurchase();
            $roles = ($who_can == 'both') ? ['crm_org', 'crm_indiv'] : [$who_can];

            if (array_intersect($roles, $data['user']->getRoles())) {
              $values = [
                'uid' => $data['user']->id(),
                'bundle' => $variation->getProduct()->subscription_type->target_id,
              ];
              $new_subscription = $this->entityTypeManager()->getStorage('contacts_subscription')->create($values);
              $route_parameters = [
                'commerce_product_variation' => $variation->id(),
                'token' => $this->csrf->get($new_subscription->getCsrfValue($variation)),
              ] + $common_route_params;
              $options = [];
              if ($standard_variation_id) {
                $options['query']['vid'] = $standard_variation_id;
              }

              $option['link'] = Link::createFromRoute($this->t('Get started'), 'contacts_subscriptions.subscription_payment', $route_parameters, $options);
            }
            else {

              // This product is not available for these users, so remove it.
              unset($build[$group_name]['products']['#options'][$product_id]);
            }
          }
        }
      }
    }

    return $build;
  }

}

Главная | Обратная связь

drupal hosting | друпал хостинг | it patrol .inc