arch-8.x-1.x-dev/modules/price/src/Plugin/Field/FieldType/PriceItem.php
modules/price/src/Plugin/Field/FieldType/PriceItem.php
<?php namespace Drupal\arch_price\Plugin\Field\FieldType; use Drupal\Component\Datetime\DateTimePlus; use Drupal\Core\Entity\TypedData\EntityDataDefinition; use Drupal\Core\Field\FieldItemBase; use Drupal\Core\Field\FieldStorageDefinitionInterface; use Drupal\Core\TypedData\DataDefinition; use Drupal\Core\TypedData\DataReferenceDefinition; use Drupal\Core\TypedData\DataReferenceTargetDefinition; /** * Plugin implementation of the 'price' field type. * * @FieldType( * id = "price", * label = @Translation("Price", context = "arch_price"), * default_widget = "price_default", * default_formatter = "price_default", * list_class = "\Drupal\arch_price\Plugin\Field\FieldType\PriceFieldItemList" * ) */ class PriceItem extends FieldItemBase implements PriceItemInterface { /** * {@inheritdoc} */ public static function propertyDefinitions(FieldStorageDefinitionInterface $field_definition) { $properties = []; $properties['base'] = DataReferenceTargetDefinition::create('string') ->setLabel(t('Price calculation base', [], ['context' => 'arch_price'])) ->addConstraint('Length', ['max' => 5]); $properties['price_type'] = DataReferenceTargetDefinition::create('string') ->setLabel(t('Price type ID', [], ['context' => 'arch_price'])); $properties['price_type_entity'] = DataReferenceDefinition::create('entity') ->setLabel(t('Price type entity', [], ['context' => 'arch_price'])) // The entity object is computed out of the entity ID. ->setComputed(TRUE) ->setReadOnly(FALSE) ->setTargetDefinition(EntityDataDefinition::create('price_type')) // We can add a constraint for the target entity type. The list of // referenceable bundles is a field setting, so the corresponding // constraint is added dynamically in ::getConstraints(). ->addConstraint('EntityType', 'price_type'); $properties['currency'] = DataDefinition::create('string') ->setLabel(t('Currency', [], ['context' => 'arch_price'])) ->addConstraint('Length', ['max' => 5]); $properties['currency_entity'] = DataReferenceDefinition::create('entity') ->setLabel(t('Currency entity', [], ['context' => 'arch_price'])) ->setComputed(TRUE) ->setReadOnly(FALSE) ->setTargetDefinition(EntityDataDefinition::create('currency')) // We can add a constraint for the target entity type. The list of // referenceable bundles is a field setting, so the corresponding // constraint is added dynamically in ::getConstraints(). ->addConstraint('EntityType', 'currency'); $properties['net'] = DataDefinition::create('float') ->setLabel(t('Net price', [], ['context' => 'arch_price'])) ->setSetting('precision', 3) ->setSetting('size', 14); $properties['gross'] = DataDefinition::create('float') ->setLabel(t('Gross price', [], ['context' => 'arch_price'])) ->setSetting('precision', 3) ->setSetting('size', 14); $properties['vat_category'] = DataDefinition::create('string') ->setLabel(t('VAT category', [], ['context' => 'arch_price'])) ->addConstraint('Length', ['max' => 32]); $properties['vat_category_entity'] = DataReferenceDefinition::create('entity') ->setLabel(t('VAT category entity', [], ['context' => 'arch_price'])) // The entity object is computed out of the entity ID. ->setComputed(TRUE) ->setReadOnly(FALSE) ->setTargetDefinition(EntityDataDefinition::create('vat_category')) // We can add a constraint for the target entity type. The list of // referenceable bundles is a field setting, so the corresponding // constraint is added dynamically in ::getConstraints(). ->addConstraint('EntityType', 'vat_category'); $properties['vat_rate'] = DataDefinition::create('float') ->setLabel(t('VAT rate', [], ['context' => 'arch_price'])) ->setSetting('precision', 4) ->setSetting('size', 8); $properties['vat_value'] = DataDefinition::create('float') ->setLabel(t('VAT value', [], ['context' => 'arch_price'])) ->setSetting('precision', 3) ->setSetting('size', 14); $properties['date_from'] = DataDefinition::create('datetime_iso8601') ->setLabel(t('Date from', [], ['context' => 'arch_price'])); $properties['date_to'] = DataDefinition::create('datetime_iso8601') ->setLabel(t('Date to', [], ['context' => 'arch_price'])); $properties['available_from'] = DataDefinition::create('any') ->setLabel(t('Computed start date', [], ['context' => 'arch_price'])) ->setDescription(t('The computed start DateTime object.', [], ['context' => 'arch_price'])) ->setComputed(TRUE) ->setClass('\Drupal\datetime\DateTimeComputed') ->setSetting('date source', 'date_from'); $properties['available_to'] = DataDefinition::create('any') ->setLabel(t('Computed end date', [], ['context' => 'arch_price'])) ->setDescription(t('The computed end DateTime object.', [], ['context' => 'arch_price'])) ->setComputed(TRUE) ->setClass('\Drupal\datetime\DateTimeComputed') ->setSetting('date source', 'date_to'); return $properties; } /** * {@inheritdoc} */ public function toArray() { $values = parent::toArray(); $values['net'] = $this->getNetPrice(); $values['gross'] = $this->getGrossPrice(); $values['vat_rate'] = $this->getVatRate(); $values['vat_value'] = $this->getVatValue(); return $values; } /** * {@inheritdoc} */ public function toPrice() { return $this->getPriceFactory()->getInstance($this->toArray()); } /** * {@inheritdoc} */ public function isEmpty() { if (parent::isEmpty()) { return TRUE; } if ( $this->getGrossPrice() === floatval(0) && $this->getNetPrice() === floatval(0) ) { return TRUE; } return FALSE; } /** * {@inheritdoc} */ public static function schema(FieldStorageDefinitionInterface $field_definition) { return [ 'columns' => [ 'price_type' => [ 'type' => 'varchar_ascii', 'length' => 32, ], 'base' => [ 'type' => 'varchar_ascii', 'length' => 5, ], 'currency' => [ 'type' => 'varchar_ascii', 'length' => 5, ], 'net' => [ 'type' => 'numeric', 'precision' => 14, 'scale' => 3, ], 'gross' => [ 'type' => 'numeric', 'precision' => 14, 'scale' => 3, ], 'vat_category' => [ 'type' => 'varchar_ascii', 'length' => 32, ], 'vat_rate' => [ 'type' => 'numeric', 'precision' => 8, 'scale' => 4, ], 'vat_value' => [ 'type' => 'numeric', 'precision' => 14, 'scale' => 3, ], 'date_from' => [ 'description' => 'The date value.', 'type' => 'varchar', 'length' => 20, ], 'date_to' => [ 'description' => 'The date value.', 'type' => 'varchar', 'length' => 20, ], ], 'indexed' => [ 'type' => ['price_type'], 'currency' => ['currency'], 'net_price' => ['price_type', 'net'], 'gross_price' => ['price_type', 'gross'], 'availability' => ['date_from', 'date_to'], ], ]; } /** * {@inheritdoc} */ public function getPriceTypeId() { return $this->get('price_type')->getValue(); } /** * {@inheritdoc} */ public function getPriceType() { $price_type_id = $this->getPriceTypeId(); $storage = $this->getEntityTypeManager()->getStorage('price_type'); return $storage->load($price_type_id); } /** * {@inheritdoc} */ public function getCurrencyId() { return $this->get('currency')->getValue(); } /** * {@inheritdoc} */ public function getCurrency() { $currency_id = $this->getCurrencyId(); $storage = $this->getEntityTypeManager()->getStorage('currency'); return $storage->load($currency_id); } /** * {@inheritdoc} */ public function getCalculationBase() { return $this->get('base')->getValue(); } /** * {@inheritdoc} */ public function getNetPrice() { if ($this->getCalculationBase() === 'net') { return round((float) $this->get('net')->getValue(), 2); } $gross = round((float) $this->get('gross')->getValue(), 2); $rate = $this->getVatRate(); return round($gross / (1 + $rate), 2); } /** * {@inheritdoc} */ public function getGrossPrice() { if ($this->getCalculationBase() === 'gross') { return round((float) $this->get('gross')->getValue(), 2); } $net = round((float) $this->get('net')->getValue(), 2); $rate = $this->getVatRate(); return round($net * (1 + $rate), 2); } /** * {@inheritdoc} */ public function getVatCategoryId() { return $this->get('vat_category')->getValue(); } /** * {@inheritdoc} */ public function getVatCategory() { $vat_category_id = $this->getVatCategoryId(); $storage = $this->getEntityTypeManager()->getStorage('vat_category'); return $storage->load($vat_category_id); } /** * {@inheritdoc} */ public function getVatRate() { $vat_category = $this->getVatCategory(); if ($vat_category->isCustom()) { return round((float) $this->get('vat_rate')->getValue(), 4); } return $vat_category->getRate(); } /** * {@inheritdoc} */ public function getVatRatePercentage() { return round($this->getVatRate() * 100, 2); } /** * {@inheritdoc} */ public function getVatValue() { return round($this->getGrossPrice() - $this->getNetPrice(), 2); } /** * {@inheritdoc} */ public function getAvailableFrom() { /** @var \Drupal\Core\TypedData\Plugin\DataType\DateTimeIso8601 $date */ $date = $this->get('date_from'); return $date->getDateTime(); } /** * {@inheritdoc} */ public function getAvailableTo() { /** @var \Drupal\Core\TypedData\Plugin\DataType\DateTimeIso8601 $date */ $date = $this->get('date_to'); return $date->getDateTime(); } /** * {@inheritdoc} */ public function isAvailable() { $timestamp = $this->getTime()->getCurrentTime(); $time = DateTimePlus::createFromTimestamp($timestamp); return $this->isAvailableAt($time); } /** * {@inheritdoc} */ public function isAvailableAt($time) { $from = $this->getAvailableFrom(); $to = $this->getAvailableTo(); $time = $time->getTimestamp(); if (!isset($from) && !isset($to)) { return TRUE; } if (isset($from) && $time < $from->getTimestamp()) { return FALSE; } if (isset($to) && $time > $to->getTimestamp()) { return FALSE; } return TRUE; } /** * Get time service. * * @return \Drupal\Component\Datetime\TimeInterface * Time service. */ protected function getTime() { // @codingStandardsIgnoreStart return \Drupal::time(); // @codingStandardsIgnoreEnd } /** * Entity type manager. * * @return \Drupal\Core\Entity\EntityTypeManagerInterface * Entity type manager. */ protected function getEntityTypeManager() { // @codingStandardsIgnoreStart return \Drupal::entityTypeManager(); // @codingStandardsIgnoreEnd } /** * Price factory. * * @return \Drupal\arch_price\Price\PriceFactoryInterface * Price factory. */ protected function getPriceFactory() { // @codingStandardsIgnoreStart return \Drupal::service('price_factory'); // @codingStandardsIgnoreEnd } }