contacts_subscriptions-1.x-dev/contacts_subscriptions.module

contacts_subscriptions.module
<?php

/**
 * @file
 * Primary module hooks for Contacts Jobs Subscriptions module.
 */

use Drupal\contacts_subscriptions\Entity\SubscriptionInterface;
use Drupal\Core\Access\AccessResult;
use Drupal\Core\Datetime\DrupalDateTime;
use Drupal\Core\Entity\ContentEntityForm;
use Drupal\Core\Entity\EntityInterface;
use Drupal\Core\Entity\EntityTypeInterface;
use Drupal\Core\Form\FormStateInterface;
use Drupal\Core\Link;
use Drupal\Core\Session\AccountInterface;
use Drupal\Core\Template\Attribute;
use Drupal\datetime\Plugin\Field\FieldType\DateTimeItemInterface;
use Drupal\entity\BundleFieldDefinition;

/**
 * Implements hook_cron().
 */
function contacts_subscriptions_cron() {
  $last_run_timestamp = \Drupal::state()->get('contacts_subscriptions_last_run', 0);
  $now_timestamp = time();

  // Run check every 6 hours.
  $six_hours = (60 * 60 * 6);
  if ($now_timestamp > ($last_run_timestamp + $six_hours)) {
    $renewing = [];
    /** @var \Drupal\contacts_subscriptions\Entity\SubscriptionType $type */
    foreach (\Drupal::entityTypeManager()->getStorage('contacts_subscription_type')->loadMultiple() as $type) {
      $renewal = new DrupalDateTime();
      $renewal->format(DateTimeItemInterface::DATE_STORAGE_FORMAT);

      if ($type->getAutomaticRenewals()) {
        $queue = \Drupal::queue('contacts_subscription_generate_renewals');

        foreach ($type->getRenewable($renewal) as $id) {
          $renewing[$id] = $id;
          $queue->createItem($id);
        }
      }

      if ($type->getAutomaticCancellations()) {
        $queue = \Drupal::queue('contacts_subscription_cancel_expired');
        foreach ($type->getCancellable($renewal) as $id) {

          // We don't want to cancel any subscriptions that might generate a
          // successful renewal, so just to be safe we'll exclude those we've
          // added to that queue.
          if (!in_array($id, $renewing)) {
            $queue->createItem($id);
          }
        }
      }
    }

    \Drupal::state()->set('contacts_subscriptions_last_run', time());
  }
}

/**
 * Implements hook_entity_field_storage_info().
 */
function contacts_subscriptions_entity_field_storage_info(EntityTypeInterface $entity_type) {
  switch ($entity_type->id()) {
    case 'commerce_order':
      $fields['subscription'] = BundleFieldDefinition::create('entity_reference')
        ->setName('subscription')
        ->setLabel('Subscription')
        ->setTargetEntityTypeId('commerce_order')
        ->setTargetBundle('contacts_subscription')
        ->setSetting('target_type', 'contacts_subscription')
        ->setCardinality(1)
        ->setTranslatable(FALSE);
      return $fields;

    case 'commerce_product':
      $fields['subscription_type'] = BundleFieldDefinition::create('entity_reference')
        ->setName('subscription_type')
        ->setLabel('Subscription type')
        ->setTargetEntityTypeId('commerce_product')
        ->setTargetBundle('subscription')
        ->setRequired(TRUE)
        ->setTranslatable(FALSE)
        ->setSetting('target_type', 'contacts_subscription_type')
        ->setCardinality(1);

      return $fields;

    case 'commerce_product_variation':
      $fields['subscription_length'] = BundleFieldDefinition::create('integer')
        ->setName('subscription_length')
        ->setLabel('Subscription length')
        ->setTargetEntityTypeId('commerce_product_variation')
        ->setTargetBundle('subscription')
        ->setRequired(TRUE)
        ->setTranslatable(FALSE)
        ->setSetting('unsigned', FALSE)
        ->setSetting('size', 'normal')
        ->setCardinality(1);

      return $fields;
  }
}

/**
 * Implements hook_entity_bundle_field_info().
 */
function contacts_subscriptions_entity_bundle_field_info(EntityTypeInterface $entity_type, $bundle, array $base_field_definitions) {
  switch ($entity_type->id()) {
    case 'commerce_order':
      if ($bundle === 'contacts_subscription') {
        $fields = [];
        $storage_definitions = contacts_subscriptions_entity_field_storage_info($entity_type);
        $fields['subscription'] = BundleFieldDefinition::createFromFieldStorageDefinition($storage_definitions['subscription'])
          ->setDisplayConfigurable('form', TRUE)
          ->setDisplayConfigurable('view', TRUE);
        return $fields;
      }
      break;

    case 'commerce_product':
      if ($bundle === 'subscription') {
        $fields = [];
        $storage_definitions = contacts_subscriptions_entity_field_storage_info($entity_type);
        $fields['subscription_type'] = BundleFieldDefinition::createFromFieldStorageDefinition($storage_definitions['subscription_type'])
          ->setDisplayConfigurable('form', TRUE)
          ->setDisplayConfigurable('view', TRUE)
          ->setSetting('handler', 'default:contacts_subscription_type');
        return $fields;
      }
      break;

    case 'commerce_product_variation':
      if ($bundle === 'subscription') {
        $fields = [];
        $storage_definitions = contacts_subscriptions_entity_field_storage_info($entity_type);
        $fields['subscription_length'] = BundleFieldDefinition::createFromFieldStorageDefinition($storage_definitions['subscription_length'])
          ->setDescription('How long this purchase will make the subscription active for, in months.')
          ->setSetting('min', 1)
          ->setSetting('max', NULL)
          ->setSetting('prefix', '')
          ->setSetting('suffix', 'months')
          ->setDisplayConfigurable('form', TRUE)
          ->setDisplayConfigurable('view', TRUE);
        return $fields;
      }
      break;
  }
}

/**
 * Implements hook_theme().
 */
function contacts_subscriptions_theme($existing, $type, $theme, $path) {
  return [
    'contacts_subscription_options' => [
      'variables' => [
        'options' => [],
        'wrapper_attributes' => [],
        'show_links' => TRUE,
        'show_intro_offer' => TRUE,
      ],
    ],
    'contacts_subscription_mail_payment_success' => [
      'variables' => [
        'order_entity' => NULL,
        'subscription_entity' => NULL,
        'subscription' => NULL,
        'billing_information' => NULL,
        'payment_method' => NULL,
        'totals' => NULL,
      ],
    ],
    'contacts_subscription_mail_payment_failure' => [
      'variables' => [
        'order_entity' => NULL,
        'subscription_entity' => NULL,
        'subscription' => NULL,
        'billing_information' => NULL,
        'payment_method' => NULL,
      ],
    ],
  ];
}

/**
 * Implements hook_contacts_user_dashboard_local_tasks_allowed_alter().
 */
function contacts_subscriptions_contacts_user_dashboard_local_tasks_allowed_alter(&$allowed_items) {
  $allowed_items[] = 'contacts_subscriptions.manage';
}

/**
 * Implements hook_workflows_alter().
 */
function contacts_subscriptions_workflows_alter(array &$workflows) {
  // Add failed states to the payment default workflow.
  $workflows['payment_default']['states']['cs_failed_declined'] = [
    'label' => 'Failed (Declined)',
  ];
  $workflows['payment_default']['transitions']['cs_failed_declined'] = [
    'label' => 'Declined',
    'from' => ['new'],
    'to' => 'cs_failed_declined',
  ];

  $workflows['payment_default']['states']['cs_failed_error'] = [
    'label' => 'Failed (Error)',
  ];
  $workflows['payment_default']['transitions']['cs_failed_error'] = [
    'label' => 'Declined',
    'from' => ['new'],
    'to' => 'cs_failed_error',
  ];
}

/**
 * Implements hook_mail().
 */
function contacts_subscriptions_mail($key, &$message, $params) {
  $mailer = \Drupal::service('contacts_subscriptions.mail');
  if (method_exists($mailer, $key)) {
    $mailer->{$key}($message, $params);
  }
}

/**
 * Template process for the subcription options theme.
 *
 * @param array $variables
 *   The variable array containing:
 *   - wrapper_attributes: An array of attributes for the wrapper.
 *   - options: An array of options. Each option is an array containing:
 *     - is_active: Whether this is the active option.
 *     - title: The title.
 *     - price: Optionally the price text.
 *     - description: Optionally the description.
 *     - link: Optionally an action link.
 *     - attributes: Optionally an array of attributes.
 */
function template_preprocess_contacts_subscription_options(array &$variables) {
  $variables['wrapper_attributes'] = new Attribute($variables['wrapper_attributes']);

  $variables['has_links'] = FALSE;
  foreach ($variables['options'] as &$option) {
    $option += [
      'is_active' => FALSE,
      'title' => NULL,
      'price' => NULL,
      'description' => NULL,
      'link' => NULL,
      'link_is_cancel' => FALSE,
      'attributes' => [],
    ];
    $option['attributes'] = new Attribute($option['attributes']);

    // Clear links if we're not showing them.
    if (!$variables['show_links']) {
      $option['link'] = NULL;
    }

    if ($option['link']) {
      $variables['has_links'] = TRUE;
      if ($option['link'] instanceof Link) {
        $option['link'] = $option['link']->toRenderable();
      }

      $option['link']['#attributes']['class'][] = 'btn';
      if ($option['is_active']) {
        $option['link']['#attributes']['class'][] =
          $option['link_is_cancel'] ? 'btn-danger' : 'btn-secondary';
      }
      else {
        $option['link']['#attributes']['class'][] = 'btn-primary';
      }
    }
  }
}

/**
 * Implements hook_field_widget_form_alter().
 */
function contacts_subscriptions_field_widget_form_alter(&$element, FormStateInterface $form_state, $context) {
  if ($context['items']->getName() == 'uid') {
    $form = $form_state->getFormObject();

    if ($form instanceof ContentEntityForm) {
      if ($entity = $form->getEntity()) {
        if ($entity instanceof SubscriptionInterface) {
          $role = $entity->bundle->entity->getWhoCanPurchase();

          // If the subscription type is locked to either individuals or
          // organisations, we can improve the functionality by making the
          // entity reference field only search for these. If both are allowed,
          // we don't need to do anything.
          switch ($role) {
            case 'crm_org':
            case 'crm_indiv':
              $element['target_id']['#selection_settings']['conditions'] = [
                [
                  'roles',
                  $role,
                ],
              ];
              break;

          }
        }
      }
    }
  }
}

/**
 * Implements hook_ENTITY_TYPE_access().
 */
function contacts_subscriptions_commerce_order_access(EntityInterface $entity, $operation, AccountInterface $account) {
  $return = AccessResult::neutral();

  /** @var \Drupal\commerce_order\Entity\OrderInterface $entity */
  if ($entity->getCustomerId() !== $account->id()) {
    // If the user has the permission to manage their organisation's membership
    // we should let them access the organisation's orders.
    if ($account->hasPermission('manage my organisation membership')) {

      // Ensure we have a fully loaded user.
      $account = \Drupal::entityTypeManager()->getStorage('user')->load($account->id());
      if ($account->hasField('organisations')) {
        foreach ($account->organisations as $item) {
          if ($group = $item->membership->getGroup()) {
            if ($group->contacts_org->target_id == $entity->getCustomerId()) {
              $return = AccessResult::allowed();
            }
          }
        }
      }
    }
  }

  return $return;
}

/**
 * Implements hook_preprocess_HOOK().
 */
function contacts_subscriptions_preprocess_input(&$variables) {

  // Some themes remove the button--primary class from inputs in favour of
  // btn-primary, but Stripe's JS relies on the submit button having this class
  // so we'll put it back.
  if ($variables['element']['#type'] == 'submit') {
    if (in_array('btn-primary', $variables['attributes']['class'])) {
      $variables['attributes']['class'][] = 'button--primary';
    }
  }
}

/**
 * Implements hook_theme_registry_alter().
 */
function contacts_subscriptions_theme_registry_alter(&$theme_registry) {

  // Ensure our preprocess runs after any others.
  if (isset($theme_registry['input']['preprocess functions'])) {
    $preprocesses = $theme_registry['input']['preprocess functions'];

    if ($key = array_search('contacts_subscriptions_preprocess_input', $preprocesses)) {
      unset($preprocesses[$key]);
      $preprocesses[] = 'contacts_subscriptions_preprocess_input';
      $theme_registry['input']['preprocess functions'] = array_values($preprocesses);
    }
  }
}

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

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