apigee_m10n-8.x-1.7/src/Entity/PurchasedPlan.php

src/Entity/PurchasedPlan.php
<?php

/*
 * Copyright 2018 Google Inc.
 *
 * This program is free software; you can redistribute it and/or modify it under
 * the terms of the GNU General Public License version 2 as published by the
 * Free Software Foundation.
 *
 * This program is distributed in the hope that it will be useful, but WITHOUT
 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
 * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public
 * License for more details.
 *
 * You should have received a copy of the GNU General Public License along
 * with this program; if not, write to the Free Software Foundation, Inc., 51
 * Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
 */

namespace Drupal\apigee_m10n\Entity;

use Apigee\Edge\Api\Monetization\Entity\AcceptedRatePlan;
use Apigee\Edge\Api\Monetization\Entity\DeveloperAcceptedRatePlan;
use Apigee\Edge\Api\Monetization\Entity\DeveloperInterface;
use Apigee\Edge\Api\Monetization\Entity\RatePlanInterface;
use Apigee\Edge\Entity\EntityInterface as EdgeEntityInterface;
use Drupal\Core\Entity\EntityTypeInterface;
use Drupal\apigee_edge\Entity\FieldableEdgeEntityBase;
use Drupal\apigee_m10n\Entity\Property\EndDatePropertyAwareDecoratorTrait;
use Drupal\apigee_m10n\Entity\Property\StartDatePropertyAwareDecoratorTrait;
use Drupal\apigee_m10n\Entity\RatePlanInterface as DrupalRatePlanInterface;
use Drupal\user\EntityOwnerInterface;
use Drupal\user\UserInterface;

/**
 * Defines the `purchased_plan` entity class.
 *
 * The label was changed to purchased plan after the entity was created because
 * it was decided it was a better match.
 *
 * @\Drupal\apigee_edge\Annotation\EdgeEntityType(
 *   id             = "purchased_plan",
 *   label          = @Translation("Purchased Plan"),
 *   label_singular = @Translation("Purchased Plan"),
 *   label_plural   = @Translation("Purchased Plans"),
 *   label_count = @PluralTranslation(
 *     singular = "@count Purchased Plan",
 *     plural   = "@count Purchased Plans",
 *   ),
 *   handlers = {
 *     "storage"             = "Drupal\apigee_m10n\Entity\Storage\PurchasedPlanStorage",
 *     "access"              = "Drupal\entity\UncacheableEntityAccessControlHandler",
 *     "permission_provider" = "Drupal\apigee_m10n\Entity\Permissions\PurchasedPlanPermissionProvider",
 *     "list_builder"        = "Drupal\apigee_m10n\Entity\ListBuilder\PurchasedPlanListBuilder",
 *     "form" = {
 *       "default" = "Drupal\apigee_m10n\Entity\Form\PurchasedPlanForm",
 *       "cancel"  = "Drupal\apigee_m10n\Entity\Form\CancelPurchaseConfirmForm",
 *     },
 *   },
 *   links = {
 *     "developer_collection" = "/user/{user}/monetization/purchased-plans",
 *   },
 *   entity_keys = {
 *     "id" = "id",
 *   },
 *   admin_permission       = "administer apigee monetization",
 *   field_ui_base_route    = "apigee_m10n.settings.purchased_plan",
 * )
 */
#[\AllowDynamicProperties]
class PurchasedPlan extends FieldableEdgeEntityBase implements PurchasedPlanInterface, EntityOwnerInterface {

  use EndDatePropertyAwareDecoratorTrait {
    getEndDate as traitGetEndDate;
  }
  use StartDatePropertyAwareDecoratorTrait;

  public const ENTITY_TYPE_ID = 'purchased_plan';

  /**
   * Suppress errors if rate plan that overlaps another accepted rate plan.
   *
   * @var bool
   */
  protected $suppressWarning;

  /**
   * The rate plan this purchased_plan belongs to.
   *
   * @var \Drupal\apigee_m10n\Entity\RatePlanInterface
   */
  protected $rate_plan;

  /**
   * The owner's user entity.
   *
   * @var \Drupal\user\UserInterface
   */
  protected $owner;

  /**
   * Constructs a `purchased_plan` entity.
   *
   * @param array $values
   *   An array of values to set, keyed by property name.
   * @param null|string $entity_type
   *   Type of the entity. It is optional because constructor sets its default
   *   value.
   * @param \Apigee\Edge\Entity\EntityInterface|null $decorated
   *   The SDK entity that this Drupal entity decorates.
   *
   * @throws \ReflectionException
   */
  public function __construct(array $values, ?string $entity_type = NULL, ?EdgeEntityInterface $decorated = NULL) {
    /** @var \Apigee\Edge\Api\Management\Entity\DeveloperAppInterface $decorated */
    $entity_type = $entity_type ?? static::ENTITY_TYPE_ID;
    parent::__construct($values, $entity_type, $decorated);
    // Save entity references in this class as well as the decorated instance.
    if (!empty($values['ratePlan']) && $values['ratePlan'] instanceof DrupalRatePlanInterface) {
      // @todo Since `RatePlan::createFrom($sdk_rate_plan)` is available do we
      // need to store an extra reference here. Is the slight performance
      // benefit worth it?
      $this->setRatePlan($values['ratePlan']);
    }

    // Do not suppress warnings by default.
    $this->suppressWarning = FALSE;
  }

  /**
   * {@inheritdoc}
   */
  protected static function decoratedClass(): string {
    return DeveloperAcceptedRatePlan::class;
  }

  /**
   * {@inheritdoc}
   */
  public static function idProperty(): string {
    return AcceptedRatePlan::idProperty();
  }

  /**
   * {@inheritdoc}
   */
  protected static function propertyToBaseFieldTypeMap(): array {
    return [
      'startDate'            => 'apigee_datestamp',
      'endDate'              => 'apigee_datestamp',
      'created'              => 'apigee_datestamp',
      'quotaTarget'          => 'integer',
      'ratePlan'             => 'entity_reference',
      'developer'            => 'apigee_monetization_developer',
      'updated'              => 'apigee_datestamp',
      'renewalDate'          => 'apigee_datestamp',
      'nextCycleStartDate'   => 'apigee_datestamp',
      'nextRecurringFeeDate' => 'apigee_datestamp',
      'prevRecurringFeeDate' => 'apigee_datestamp',
    ];
  }

  /**
   * {@inheritdoc}
   */
  public static function baseFieldDefinitions(EntityTypeInterface $entity_type) {
    /** @var \Drupal\Core\Field\BaseFieldDefinition[] $definitions */
    $definitions = parent::baseFieldDefinitions($entity_type);

    // The following fields should not be configurable through the UI.
    $read_only_fields = [
      'id',
      'created',
      'quotaTarget',
      'updated',
      'renewalDate',
      'nextCycleStartDate',
      'nextRecurringFeeDate',
      'prevRecurringFeeDate',
      'developer',
    ];
    // Disable the form display entry for all read only fields.
    foreach ($read_only_fields as $field_name) {
      $definitions[$field_name]->setDisplayConfigurable('form', FALSE);
    }

    $definitions['termsAndConditions']
      ->setRequired(TRUE);

    // Set the target_type for ratePlan base field.
    $definitions['ratePlan']->setSetting('target_type', 'rate_plan');

    return $definitions;
  }

  /**
   * {@inheritdoc}
   */
  protected static function getProperties(): array {
    $properties = parent::getProperties();
    $properties['termsAndConditions'] = 'apigee_tnc';

    return $properties;
  }

  /**
   * {@inheritdoc}
   *
   * @throws \Drupal\Component\Plugin\Exception\InvalidPluginDefinitionException
   * @throws \Drupal\Component\Plugin\Exception\PluginNotFoundException
   */
  public static function loadByDeveloperId(string $developer_id): array {
    return \Drupal::entityTypeManager()
      ->getStorage(static::ENTITY_TYPE_ID)
      ->loadByDeveloperId($developer_id);
  }

  /**
   * {@inheritdoc}
   */
  public function toUrl($rel = 'canonical', array $options = []) {
    // The string formatter assumes entities are revisionable.
    $rel = ($rel === 'revision') ? 'canonical' : $rel;
    // Use the developer collection as the default collection.
    $rel = ($rel === 'collection') ? 'developer_collection' : $rel;
    // Build the URL.
    $url = parent::toUrl($rel, $options);
    // Add the user parameter to any routes that require it.
    if ($rel == 'developer_collection') {
      // Strip the `purchased_plan` parameter from the collection.
      $url->setRouteParameters(array_diff_key($url->getRouteParameters(), ['purchased_plan' => NULL]));
      // Set the developer's user ID.
      $url->setRouteParameter('user', $this->getOwnerId());
    }

    return $url;
  }

  /**
   * {@inheritdoc}
   */
  protected function drupalEntityId(): ?string {
    return $this->getId();
  }

  /**
   * {@inheritdoc}
   */
  public function getId(): ?string {
    return $this->decorated->getId();
  }

  /**
   * {@inheritdoc}
   */
  public function isActive(): bool {
    return ($this->getStatus() === PurchasedPlanInterface::STATUS_ACTIVE
      || $this->getStatus() === PurchasedPlanInterface::STATUS_FUTURE);
  }

  /**
   * {@inheritdoc}
   */
  public function getTermsAndConditions(): bool {
    $developer_email = $this->getDeveloper()->getEmail();
    // Caching is handled by the monetization service.
    return $this->monetization()->isLatestTermsAndConditionAccepted($developer_email);
  }

  /**
   * {@inheritdoc}
   */
  public function getStatus(): string {
    $org_timezone = $this->getRatePlan()->getOrganization()->getTimezone();
    $today = (new \DateTimeImmutable('now'))->setTimezone($org_timezone);

    // If rate plan ended before today or today, the status is ended.
    $plan_end_date = $this->getRatePlan()->getEndDate();
    if (!empty($plan_end_date) && $plan_end_date < $today) {
      return PurchasedPlanInterface::STATUS_ENDED;
    }
    // If the developer ended the plan before today or today, the plan has ended.
    $developer_plan_end_date = $this->getEndDate();
    if (!empty($developer_plan_end_date) && $developer_plan_end_date < $today) {
      return PurchasedPlanInterface::STATUS_ENDED;
    }

    // If the start date is later than today, it is a future plan.
    $developer_plan_start_date = $this->getStartDate();
    if (!empty($developer_plan_start_date) && $developer_plan_start_date > $today) {
      return PurchasedPlanInterface::STATUS_FUTURE;
    }

    return PurchasedPlanInterface::STATUS_ACTIVE;
  }

  /**
   * {@inheritdoc}
   */
  public function getUpdated(): ?\DateTimeImmutable {
    return $this->decorated->getUpdated();
  }

  /**
   * {@inheritdoc}
   */
  public function getCreated(): ?\DateTimeImmutable {
    return $this->decorated->getCreated();
  }

  /**
   * {@inheritdoc}
   */
  public function getQuotaTarget(): ?int {
    return $this->decorated->getQuotaTarget();
  }

  /**
   * {@inheritdoc}
   */
  public function setQuotaTarget(int $quotaTarget): void {
    $this->decorated->setQuotaTarget($quotaTarget);
  }

  /**
   * {@inheritdoc}
   */
  public function getRatePlan(): RatePlanInterface {
    // Return the drupal entity for entity references.
    if (empty($this->rate_plan) && !empty($this->decorated()) && $sdk_rate_plan = $this->decorated()->getRatePlan()) {
      /** @var \Apigee\Edge\Api\Monetization\Entity\RatePlanInterface $sdk_rate_plan */
      $this->rate_plan = RatePlan::createFrom($sdk_rate_plan);
    }

    return $this->rate_plan;
  }

  /**
   * {@inheritdoc}
   */
  public function setRatePlan(RatePlanInterface $ratePlan): void {
    $this->rate_plan = $ratePlan;
    $this->decorated->setRatePlan($ratePlan->decorated());
  }

  /**
   * {@inheritdoc}
   */
  public function getRenewalDate(): ?\DateTimeImmutable {
    return $this->decorated->getRenewalDate();
  }

  /**
   * {@inheritdoc}
   */
  public function getNextCycleStartDate(): ?\DateTimeImmutable {
    return $this->decorated->getNextCycleStartDate();
  }

  /**
   * {@inheritdoc}
   */
  public function getNextRecurringFeeDate(): ?\DateTimeImmutable {
    return $this->decorated->getNextRecurringFeeDate();
  }

  /**
   * {@inheritdoc}
   */
  public function getPrevRecurringFeeDate(): ?\DateTimeImmutable {
    return $this->decorated->getPrevRecurringFeeDate();
  }

  /**
   * {@inheritdoc}
   */
  public function getDeveloper(): ?DeveloperInterface {
    // @todo Return the `apigee_edge` developer entity reference.
    return $this->decorated->getDeveloper();
  }

  /**
   * {@inheritdoc}
   */
  public function setSuppressWarning(bool $value): PurchasedPlanInterface {
    $this->suppressWarning = $value;
    return $this;
  }

  /**
   * {@inheritdoc}
   */
  public function getSuppressWarning(): bool {
    return $this->suppressWarning;
  }

  /**
   * Gets the monetization service.
   *
   * This gets the monetization service as needed avoiding loading the SDK
   * connector during bootstrap.
   *
   * @return \Drupal\apigee_m10n\MonetizationInterface
   *   The monetization service.
   */
  protected function monetization() {
    return \Drupal::service('apigee_m10n.monetization');
  }

  /**
   * {@inheritdoc}
   */
  public function getOwner() {
    if (!isset($this->owner)) {
      $owner = $this->entityTypeManager()->getStorage('user')->loadByProperties([
        'mail' => $this->getDeveloper()->getEmail(),
      ]);
      $this->owner = !empty($owner) ? reset($owner) : NULL;
    }
    return $this->owner;
  }

  /**
   * {@inheritdoc}
   */
  public function getOwnerId() {
    return ($owner = $this->getOwner()) ? $owner->id() : NULL;
  }

  /**
   * {@inheritdoc}
   */
  public function setOwnerId($uid) {
    // The owner is not settable after instantiation.
    return $this;
  }

  /**
   * {@inheritdoc}
   */
  public function setOwner(UserInterface $account) {
    // The owner is not settable after instantiation.
    return $this;
  }

  /**
   * {@inheritdoc}
   */
  public function getEndDate(): ?\DateTimeImmutable {
    return $this->getAdjustedEndDate();
  }

  /**
   * Adjust the date so it never ends before it starts.
   *
   * @return \DateTimeImmutable|null
   *   The adjusted end date.
   *
   * @throws \Exception
   */
  protected function getAdjustedEndDate() : ?\DateTimeImmutable {
    $today = new \DateTime('today', $this->getRatePlan()->getOrganization()->getTimezone());
    // If the plan has ended, make sure the end date doesn't come before the
    // start date.
    if (($end_date = $this->traitGetEndDate())
      && ($start_date = $this->getStartDate())
      && $start_date <= $today
      && $end_date < $start_date
    ) {
      return $start_date;
    }
    else {
      return $end_date;
    }
  }

}

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

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