commerce_pickup-1.0.0-beta2/src/PickupOptionsmanager.php

src/PickupOptionsmanager.php
<?php

namespace Drupal\commerce_pickup;

use Drupal\Core\Entity\EntityTypeManagerInterface;
use Drupal\Core\TempStore\SharedTempStoreFactory;
use Drupal\commerce_pickup\Plugin\Commerce\ShippingMethod\PickupShippingRateInterface;
use Drupal\commerce_pickup\Plugin\Commerce\Condition\PickupConditionInterface;
use Drupal\commerce_pickup\Plugin\Commerce\Condition\PickupAddress;
use Drupal\commerce_pickup\Plugin\Commerce\Condition\PickupHours;
use CommerceGuys\Addressing\Zone\Zone;
use Drupal\Core\Datetime\DrupalDateTime;
use Drupal\commerce_store\Entity\StoreInterface;
use Drupal\commerce_order\Entity\OrderInterface;

/**
 * PickupOptionsmanager service.
 */
class PickupOptionsmanager {

  /**
   * The entity type manager.
   *
   * @var \Drupal\Core\Entity\EntityTypeManagerInterface
   */
  protected $entityTypeManager;

  /**
   * The shared tempstore factory.
   *
   * @var \Drupal\Core\TempStore\SharedTempStoreFactory
   */
  protected $tempStoreFactory;

  /**
   * The pickup tempstore.
   *
   * @var \Drupal\Core\TempStore\SharedTempStore
   */
  protected $tempStore;

  /**
   * The pickup dateTime.
   *
   * @var Drupal\Core\Datetime\DrupalDateTime
   */
  protected $date;

  /**
   * The pickup day.
   *
   * @var int
   */
  protected $day;

  /**
   * The pickup time.
   *
   * @var int
   */
  protected $time;

  /**
   * The pickup timezone.
   *
   * @var int
   */
  protected $timezone;

  /**
   * Constructs a PickupOptionsmanager object.
   *
   * @param \Drupal\Core\Entity\EntityTypeManagerInterface $entity_type_manager
   *   The entity type manager.
   * @param \Drupal\Core\TempStore\SharedTempStoreFactory $temp_store_factory
   *   The shared tempstore factory.
   */
  public function __construct(EntityTypeManagerInterface $entity_type_manager, SharedTempStoreFactory $temp_store_factory) {
    $this->entityTypeManager = $entity_type_manager;
    $this->tempStoreFactory = $temp_store_factory;
    $this->tempStore = $this->tempStoreFactory->get('store_pickup_addresses');
    $this->date = new DrupalDateTime();
    $this->day = $this->date->format('w');
    $this->time = $this->date->format('Hi');
    $timezone = $this->date->format('e');
    $this->timezone = $timezone ?: 'GMT';
  }

  /**
   * {@inheritdoc}
   */
  public function getPickupAddresses(OrderInterface $order, StoreInterface $store, PickupAddress $condition) {
    if (!$pickup_addresses = $this->getOrderPickupAddresses($order, $condition)) {
      if ($pickup_addresses = $this->getPickupAddressAddresses([$store->id()], $condition)) {
        $this->setOrderPickupAddresses($order, $condition, $pickup_addresses);
      }
    }

    return $pickup_addresses;
  }

  /**
   * {@inheritdoc}
   */
  public function getPickupHoursAddresses(OrderInterface $order, PickupHours $condition) {
    // @TODO Add support for the pickup point timezone.
    // @see https://stackoverflow.com/a/34329033/3944647
    // @see https://www.drupal.org/node/1962888
    // @see https://drupal.org/node/1925272
    // Get user device timezone:
    // @see https://git.drupalcode.org/project/clock/-/blob/7.x-1.x/clock.js
    // @see http://www.onlineaspect.com/2007/06/08/auto-detect-a-time-zone-with-javascript/
    // @see https://stackoverflow.com/a/2705087/3944647
    $addresses = $original = $this->getOriginalOrderPickupAddresses($order, $condition);
    $config = $condition->getConfiguration();
    $current_day = $config['pickup']['current'] == 'day';
    $day_plus = $config['pickup']['current'] == 'day_plus';
    $days = $config['pickup']['days'];
    $timezones = [];

    foreach ($addresses as $profile_id => $data) {
      $open = FALSE;
      foreach ($data['hours'] as $slot) {
        $start = $slot['starthours'];
        $end = $slot['endhours'];

        $day = $this->day;
        $time = $this->time;
        $next_day = !$current_day && !($day == $slot['day']);
        if ($next_day && ($slot['day']) <= $days) {
          $open = TRUE;
        }
        elseif ($current_day || $day_plus) {
          if ($this->timezone != $data['timezone']) {
            if (!isset($timezones[$data['timezone']])) {
              $remote = new DrupalDateTime('now', $data['timezone']);
              $timezones[$data['timezone']]['day'] = $remote->format('w');
              $timezones[$data['timezone']]['time'] = $remote->format('Hi');
            }
            $day = $timezones[$data['timezone']]['day'];
            $time = $timezones[$data['timezone']]['time'];
          }
          if ($day == $slot['day']) {
            if (($time >= $start && ($time <= $end || !$end)) || (!$start && !$end)) {
              $open = TRUE;
            }
          }
        }
      }

      if (!$open) {
        unset($addresses[$profile_id]);
      }
    }

    if ($addresses != $original) {
      $this->setOrderPickupAddresses($order, $condition, $addresses);
    }

    return $addresses;
  }

  /**
   * {@inheritdoc}
   */
  public function getOriginalOrderPickupAddresses(OrderInterface $order, PickupConditionInterface $condition) {
    $condition_addresses = [];
    $hash = $condition->getConfiguration()['hash'];
    $addresses = (array) $this->tempStore->get('pickup_order-' . $order->id());
    if (isset($addresses["{$hash}-original"])) {
      return $addresses["{$hash}-original"];
    }
    if (isset($addresses[$hash])) {
      $condition_addresses = $addresses["{$hash}-original"] = $addresses[$hash];
      $this->tempStore->set('pickup_order-' . $order->id(), $addresses);
    }

    return $condition_addresses;
  }

  /**
   * {@inheritdoc}
   */
  public function getOrderPickupAddresses(OrderInterface $order, PickupConditionInterface $condition) {
    $condition_addresses = [];
    $hash = $condition->getConfiguration()['hash'];
    $addresses = (array) $this->tempStore->get('pickup_order-' . $order->id());
    if (isset($addresses[$hash])) {
      $condition_addresses = $addresses[$hash];
    }

    return $condition_addresses;
  }

  /**
   * {@inheritdoc}
   */
  public function setOrderPickupAddresses(OrderInterface $order, PickupConditionInterface $condition, array $pickup_addresses) {
    $hash = $condition->getConfiguration()['hash'];
    $addresses = (array) $this->tempStore->get('pickup_order-' . $order->id());
    $addresses[$hash] = $pickup_addresses;
    $this->tempStore->set('pickup_order-' . $order->id(), $addresses);

    return $addresses;
  }

  /**
   * {@inheritdoc}
   */
  public function getPickupAddressAddresses(array $store_ids, PickupAddress $condition) {
    $profile_ids = $vendor_ids = $profiles = $data = $default = [];
    $config = $condition->getConfiguration();
    $pickup = $config['pickup'];
    $storage = $this->entityTypeManager->getStorage('user');

    foreach ($pickup as $key => $value) {
      if (preg_match('/^uid_(\d+)$/', $key, $matches)) {
        $vendor_id = $matches[1];
        if ($vendor = $storage->load($vendor_id)) {
          if (!$vendor->hasRole('pickup_vendor') || $vendor->isBlocked()) {
            $vendor = NULL;
          }
        }
        if (!$vendor || (!$pickup[$key]['all'] && !$pickup[$key]['not_all'])) {
          continue;
        }
        if (!$pickup[$key]['all'] && $pickup[$key]['not_all']) {
          $profile_ids += $pickup[$key]['not_all'];
        }
        elseif ($pickup[$key]['all']) {
          $vendor_ids[] = $vendor_id;
        }
      }
    }

    if (!$profile_ids && !$vendor_ids) {
      return $profiles;
    }

    $storage = $this->entityTypeManager->getStorage('profile');

    if ($profile_ids) {
      $profiles += $storage->loadByProperties([
        'profile_id' => $profile_ids,
        'status' => 1,
        'pickup_stores' => $store_ids,
      ]);
    }
    if ($vendor_ids) {
      $profiles += $storage->loadByProperties([
        'type' => 'pickup',
        'status' => 1,
        'pickup_stores' => $store_ids,
        'uid' => $vendor_ids,
      ]);
    }

    if ($zone = !empty($config['pickup']['zone']['territories'])) {
      $zone = new Zone([
        'id' => 'shipping',
        'label' => 'N/A',
      ] + $config['pickup']['zone']);
    }

    foreach ($profiles as $profile_id => $profile) {
      $address = $profile->pickup_address->first();
      if ($zone) {
        if ($config['pickup']['negate']) {
          if ($zone->match($address)) {
            $address = NULL;
          }
        }
        elseif (!$zone->match($address)) {
          $address = NULL;
        }
      }
      if ($address && $address = $address->getValue()) {
        $hours = $profile->pickup_hours->getValue();
        $timezone = $profile->pickup_timezone;
        $timezone = $timezone ? $timezone->value : $this->timezone;
        if ($profile->isDefault()) {
          $default[$profile_id]['address'] = $address;
          $default[$profile_id]['hours'] = $hours;
          $default[$profile_id]['timezone'] = $timezone;
        }
        else {
          $data[$profile_id]['address'] = $address;
          $data[$profile_id]['hours'] = $hours;
          $data[$profile_id]['timezone'] = $timezone;
        }
      }
    }

    return $default + $data;
  }

  /**
   * Flush tempstorage for pickup addresses.
   */
  public function flushPickupAddresses(array $profiles) {
    if (!$profiles) {
      return;
    }
    $stores = [];
    foreach ($profiles as $profile) {
      foreach ($profile->pickup_stores as $store) {
        $stores[$store->target_id] = $store->target_id;
      }
      if ($profile->original) {
        foreach ($profile->original->pickup_stores as $store) {
          $stores[$store->target_id] = $store->target_id;
        }
      }
    }

    $vendor_id = $profile->getOwnerId();
    $method_storage = $this->entityTypeManager->getStorage('commerce_shipping_method');
    $order_storage = $this->entityTypeManager->getStorage('commerce_order');
    $methods = $method_storage->loadMultiple();
    $week_ago = time() - 604800;
    static $ids;

    foreach ($methods as $method_id => $method) {
      $method_stores = array_intersect($stores, $method->getStoreIds());
      if ($method_stores && $method->getPlugin() instanceof PickupShippingRateInterface) {
        $condition = current(array_filter($method->getConditions(), function ($obj) {
          return $obj instanceof PickupAddress;
        }));
        $pickup = $condition->getConfiguration()['pickup'];

        foreach ($pickup as $key => $value) {
          if ($key != "uid_{$vendor_id}"
            || (!$pickup[$key]['all'] && !$pickup[$key]['not_all'])) {
            continue;
          }

          foreach ($method_stores as $store_id) {
            if (isset($ids['stores'][$store_id])) {
              continue;
            }
            $ids['stores'][$store_id] = TRUE;
            $order_ids = $order_storage->getQuery()
              ->accessCheck(FALSE)
              ->condition('cart', '1', '=')
              ->condition('store_id', $store_id, '=')
              ->condition('changed', $week_ago, '>')
              ->execute();

            foreach ($order_ids as $order_id) {
              if (!isset($ids['carts'][$order_id])) {
                $ids['carts'][$order_id] = TRUE;
                $this->flushOrderPickupAddresses($order_id);
              }
            }
          }
        }
      }
    }
  }

  /**
   * {@inheritdoc}
   */
  public function flushOrderPickupAddresses(int $order_id) {
    return $this->tempStore->delete('pickup_order-' . $order_id);
  }

  /**
   * {@inheritdoc}
   */
  public function getUserTimezoneOffset(string $any_timezone) {
    $user_date = $this->date->getPhpDateTime();
    $user_timezone = $user_date->getTimezone();
    $any = new DrupalDateTime('now', $any_timezone);
    $any_date = $any->getPhpDateTime();
    $any_timezone = $any->getTimezone();
    $offset = $user_timezone->getOffset($user_date) - $any_timezone->getOffset($any_date);

    return [
      'date' => $any_date,
      'day' => $any->format('w'),
      'time' => $any->format('Hi'),
      'offset' => $offset / 3600,
    ];
  }

}

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

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