View source
<?php
namespace Drupal\commerce_order\Entity;
use Drupal\commerce\Entity\CommerceContentEntityBase;
use Drupal\commerce_order\Adjustment;
use Drupal\commerce_order\Exception\OrderVersionMismatchException;
use Drupal\commerce_order\Event\OrderEvents;
use Drupal\commerce_order\Event\OrderProfilesEvent;
use Drupal\commerce_order\OrderBalanceFieldItemList;
use Drupal\commerce_price\Price;
use Drupal\commerce_store\Entity\StoreInterface;
use Drupal\Core\Datetime\DrupalDateTime;
use Drupal\Core\Entity\EntityChangedTrait;
use Drupal\Core\Entity\EntityStorageInterface;
use Drupal\Core\Entity\EntityTypeInterface;
use Drupal\Core\Field\BaseFieldDefinition;
use Drupal\user\Entity\User;
use Drupal\user\UserInterface;
use Drupal\profile\Entity\ProfileInterface;
class Order extends CommerceContentEntityBase implements OrderInterface {
use EntityChangedTrait;
public function getOrderNumber() {
return $this
->get('order_number')->value;
}
public function setOrderNumber($order_number) {
$this
->set('order_number', $order_number);
return $this;
}
public function getVersion() {
return $this
->get('version')->value;
}
public function setVersion($version) {
$this
->set('version', $version);
return $this;
}
public function getStore() {
return $this
->getTranslatedReferencedEntity('store_id');
}
public function setStore(StoreInterface $store) {
$this
->set('store_id', $store
->id());
return $this;
}
public function getStoreId() {
return $this
->get('store_id')->target_id;
}
public function setStoreId($store_id) {
$this
->set('store_id', $store_id);
return $this;
}
public function getCustomer() {
$customer = $this
->get('uid')->entity;
if (!$customer) {
$customer = User::getAnonymousUser();
}
return $customer;
}
public function setCustomer(UserInterface $account) {
$this
->set('uid', $account
->id());
return $this;
}
public function getCustomerId() {
return $this
->get('uid')->target_id;
}
public function setCustomerId($uid) {
$this
->set('uid', $uid);
return $this;
}
public function getEmail() {
return $this
->get('mail')->value;
}
public function setEmail($mail) {
$this
->set('mail', $mail);
return $this;
}
public function getIpAddress() {
return $this
->get('ip_address')->value;
}
public function setIpAddress($ip_address) {
$this
->set('ip_address', $ip_address);
return $this;
}
public function getBillingProfile() {
return $this
->get('billing_profile')->entity;
}
public function setBillingProfile(ProfileInterface $profile) {
$this
->set('billing_profile', $profile);
return $this;
}
public function collectProfiles() {
$profiles = [];
if ($billing_profile = $this
->getBillingProfile()) {
$profiles['billing'] = $billing_profile;
}
$event = new OrderProfilesEvent($this, $profiles);
\Drupal::service('event_dispatcher')
->dispatch(OrderEvents::ORDER_PROFILES, $event);
$profiles = $event
->getProfiles();
return $profiles;
}
public function getItems() {
return $this
->get('order_items')
->referencedEntities();
}
public function setItems(array $order_items) {
$this
->set('order_items', $order_items);
$this
->recalculateTotalPrice();
return $this;
}
public function hasItems() {
return !$this
->get('order_items')
->isEmpty();
}
public function addItem(OrderItemInterface $order_item) {
if (!$this
->hasItem($order_item)) {
$this
->get('order_items')
->appendItem($order_item);
$this
->recalculateTotalPrice();
}
return $this;
}
public function removeItem(OrderItemInterface $order_item) {
$index = $this
->getItemIndex($order_item);
if ($index !== FALSE) {
$this
->get('order_items')
->offsetUnset($index);
$this
->recalculateTotalPrice();
}
return $this;
}
public function hasItem(OrderItemInterface $order_item) {
return $this
->getItemIndex($order_item) !== FALSE;
}
protected function getItemIndex(OrderItemInterface $order_item) {
$values = $this
->get('order_items')
->getValue();
$order_item_ids = array_map(function ($value) {
return $value['target_id'];
}, $values);
return array_search($order_item
->id(), $order_item_ids);
}
public function getAdjustments(array $adjustment_types = []) {
$adjustments = $this
->get('adjustments')
->getAdjustments();
if ($adjustment_types) {
foreach ($adjustments as $index => $adjustment) {
if (!in_array($adjustment
->getType(), $adjustment_types)) {
unset($adjustments[$index]);
}
}
$adjustments = array_values($adjustments);
}
return $adjustments;
}
public function setAdjustments(array $adjustments) {
$this
->set('adjustments', $adjustments);
$this
->recalculateTotalPrice();
return $this;
}
public function addAdjustment(Adjustment $adjustment) {
$this
->get('adjustments')
->appendItem($adjustment);
$this
->recalculateTotalPrice();
return $this;
}
public function removeAdjustment(Adjustment $adjustment) {
$this
->get('adjustments')
->removeAdjustment($adjustment);
$this
->recalculateTotalPrice();
return $this;
}
public function clearAdjustments() {
$locked_callback = function ($adjustment) {
return $adjustment
->isLocked();
};
foreach ($this
->getItems() as $order_item) {
$adjustments = array_filter($order_item
->getAdjustments(), $locked_callback);
if ($adjustments && $order_item
->usesLegacyAdjustments()) {
foreach ($adjustments as $index => $adjustment) {
$adjustments[$index] = $adjustment
->multiply($order_item
->getQuantity());
}
}
$order_item
->set('uses_legacy_adjustments', FALSE);
$order_item
->setAdjustments($adjustments);
}
$adjustments = array_filter($this
->getAdjustments(), $locked_callback);
$this
->setAdjustments($adjustments);
return $this;
}
public function collectAdjustments(array $adjustment_types = []) {
$adjustments = [];
foreach ($this
->getItems() as $order_item) {
foreach ($order_item
->getAdjustments($adjustment_types) as $adjustment) {
if ($order_item
->usesLegacyAdjustments()) {
$adjustment = $adjustment
->multiply($order_item
->getQuantity());
}
$adjustments[] = $adjustment;
}
}
foreach ($this
->getAdjustments($adjustment_types) as $adjustment) {
$adjustments[] = $adjustment;
}
return $adjustments;
}
public function getSubtotalPrice() {
$subtotal_price = NULL;
foreach ($this
->getItems() as $order_item) {
if ($order_item_total = $order_item
->getTotalPrice()) {
$subtotal_price = $subtotal_price ? $subtotal_price
->add($order_item_total) : $order_item_total;
}
}
return $subtotal_price;
}
public function recalculateTotalPrice() {
$total_price = NULL;
foreach ($this
->getItems() as $order_item) {
if ($order_item_total = $order_item
->getTotalPrice()) {
$total_price = $total_price ? $total_price
->add($order_item_total) : $order_item_total;
}
}
if ($total_price) {
$adjustments = $this
->collectAdjustments();
if ($adjustments) {
$adjustment_transformer = \Drupal::service('commerce_order.adjustment_transformer');
$adjustments = $adjustment_transformer
->combineAdjustments($adjustments);
$adjustments = $adjustment_transformer
->roundAdjustments($adjustments);
foreach ($adjustments as $adjustment) {
if (!$adjustment
->isIncluded()) {
$total_price = $total_price
->add($adjustment
->getAmount());
}
}
}
}
$this->total_price = $total_price;
return $this;
}
public function getTotalPrice() {
if (!$this
->get('total_price')
->isEmpty()) {
return $this
->get('total_price')
->first()
->toPrice();
}
}
public function getTotalPaid() {
if (!$this
->get('total_paid')
->isEmpty()) {
return $this
->get('total_paid')
->first()
->toPrice();
}
elseif ($total_price = $this
->getTotalPrice()) {
return new Price('0', $total_price
->getCurrencyCode());
}
}
public function setTotalPaid(Price $total_paid) {
$this
->set('total_paid', $total_paid);
}
public function getBalance() {
if ($total_price = $this
->getTotalPrice()) {
return $total_price
->subtract($this
->getTotalPaid());
}
}
public function isPaid() {
$total_price = $this
->getTotalPrice();
if (!$total_price) {
return FALSE;
}
$balance = $this
->getBalance();
if ($total_price
->isZero()) {
return $this
->getState()
->getId() != 'draft';
}
else {
return $balance
->isNegative() || $balance
->isZero();
}
}
public function getState() {
return $this
->get('state')
->first();
}
public function getRefreshState() {
return $this
->getData('refresh_state');
}
public function setRefreshState($refresh_state) {
return $this
->setData('refresh_state', $refresh_state);
}
public function getData($key, $default = NULL) {
$data = [];
if (!$this
->get('data')
->isEmpty()) {
$data = $this
->get('data')
->first()
->getValue();
}
return isset($data[$key]) ? $data[$key] : $default;
}
public function setData($key, $value) {
$this
->get('data')
->__set($key, $value);
return $this;
}
public function unsetData($key) {
if (!$this
->get('data')
->isEmpty()) {
$data = $this
->get('data')
->first()
->getValue();
unset($data[$key]);
$this
->set('data', $data);
}
return $this;
}
public function isLocked() {
return (bool) $this
->get('locked')->value;
}
public function lock() {
$this
->set('locked', TRUE);
return $this;
}
public function unlock() {
$this
->set('locked', FALSE);
return $this;
}
public function getCreatedTime() {
return $this
->get('created')->value;
}
public function setCreatedTime($timestamp) {
$this
->set('created', $timestamp);
return $this;
}
public function getPlacedTime() {
return $this
->get('placed')->value;
}
public function setPlacedTime($timestamp) {
$this
->set('placed', $timestamp);
return $this;
}
public function getCompletedTime() {
return $this
->get('completed')->value;
}
public function setCompletedTime($timestamp) {
$this
->set('completed', $timestamp);
return $this;
}
public function getCalculationDate() {
$timezone = $this
->getStore()
->getTimezone();
$timestamp = $this
->getPlacedTime() ?: \Drupal::time()
->getRequestTime();
$date = DrupalDateTime::createFromTimestamp($timestamp, $timezone);
return $date;
}
public function preSave(EntityStorageInterface $storage) {
parent::preSave($storage);
if (isset($this->original) && !$this
->isNew() && $this->original
->getVersion() > $this
->getVersion()) {
$mismatch_exception = new OrderVersionMismatchException(sprintf('Attempted to save order %s with version %s. Current version is %s.', $this
->id(), $this
->getVersion(), $this->original
->getVersion()));
$log_only = $this
->getEntityType()
->get('log_version_mismatch');
if ($log_only) {
watchdog_exception('commerce_order', $mismatch_exception);
}
else {
throw $mismatch_exception;
}
}
$this
->setVersion($this
->getVersion() + 1);
if ($this
->isNew() && !$this
->getIpAddress()) {
$this
->setIpAddress(\Drupal::request()
->getClientIp());
}
$customer = $this
->getCustomer();
if ($this
->getCustomerId() && $customer
->isAnonymous()) {
$this
->setCustomerId(0);
}
if (!$this
->getEmail() && $customer
->isAuthenticated()) {
$this
->setEmail($customer
->getEmail());
}
$billing_profile = $this
->getBillingProfile();
if ($billing_profile && $billing_profile
->getOwnerId()) {
$billing_profile
->setOwnerId(0);
$billing_profile
->save();
}
if ($this
->getState()
->getId() == 'draft') {
if (empty($this
->getRefreshState())) {
$this
->setRefreshState(self::REFRESH_ON_SAVE);
}
if ($this
->getData('paid_event_dispatched') === NULL) {
$this
->setData('paid_event_dispatched', FALSE);
}
}
}
public function postSave(EntityStorageInterface $storage, $update = TRUE) {
parent::postSave($storage, $update);
foreach ($this
->getItems() as $order_item) {
if ($order_item->order_id
->isEmpty()) {
$order_item->order_id = $this
->id();
$order_item
->save();
}
}
}
public static function postDelete(EntityStorageInterface $storage, array $entities) {
parent::postDelete($storage, $entities);
$order_items = [];
foreach ($entities as $entity) {
foreach ($entity
->getItems() as $order_item) {
$order_items[$order_item
->id()] = $order_item;
}
}
$order_item_storage = \Drupal::service('entity_type.manager')
->getStorage('commerce_order_item');
$order_item_storage
->delete($order_items);
}
public static function baseFieldDefinitions(EntityTypeInterface $entity_type) {
$fields = parent::baseFieldDefinitions($entity_type);
$fields['order_number'] = BaseFieldDefinition::create('string')
->setLabel(t('Order number'))
->setDescription(t('The order number displayed to the customer.'))
->setRequired(TRUE)
->setDefaultValue('')
->setSetting('max_length', 255)
->setDisplayConfigurable('form', TRUE)
->setDisplayConfigurable('view', TRUE);
$fields['version'] = BaseFieldDefinition::create('integer')
->setLabel(t('Version'))
->setDescription(t('The order version number, it gets incremented on each save.'))
->setReadOnly(TRUE)
->setSetting('unsigned', TRUE)
->setDefaultValue(0);
$fields['store_id'] = BaseFieldDefinition::create('entity_reference')
->setLabel(t('Store'))
->setDescription(t('The store to which the order belongs.'))
->setCardinality(1)
->setRequired(TRUE)
->setSetting('target_type', 'commerce_store')
->setSetting('handler', 'default')
->setTranslatable(TRUE)
->setDisplayConfigurable('form', TRUE)
->setDisplayConfigurable('view', TRUE);
$fields['uid'] = BaseFieldDefinition::create('entity_reference')
->setLabel(t('Customer'))
->setDescription(t('The customer.'))
->setSetting('target_type', 'user')
->setSetting('handler', 'default')
->setDefaultValueCallback('Drupal\\commerce_order\\Entity\\Order::getCurrentUserId')
->setTranslatable(TRUE)
->setDisplayOptions('view', [
'label' => 'above',
'type' => 'author',
'weight' => 0,
])
->setDisplayConfigurable('form', TRUE)
->setDisplayConfigurable('view', TRUE);
$fields['mail'] = BaseFieldDefinition::create('email')
->setLabel(t('Contact email'))
->setDescription(t('The email address associated with the order.'))
->setDefaultValue('')
->setSetting('max_length', 255)
->setDisplayOptions('view', [
'label' => 'above',
'type' => 'string',
'weight' => 0,
])
->setDisplayConfigurable('form', TRUE)
->setDisplayConfigurable('view', TRUE);
$fields['ip_address'] = BaseFieldDefinition::create('string')
->setLabel(t('IP address'))
->setDescription(t('The IP address of the order.'))
->setDefaultValue('')
->setSetting('max_length', 128)
->setDisplayOptions('view', [
'label' => 'above',
'type' => 'string',
'weight' => 0,
])
->setDisplayOptions('form', [
'region' => 'hidden',
'weight' => 0,
])
->setDisplayConfigurable('form', TRUE)
->setDisplayConfigurable('view', TRUE);
$fields['billing_profile'] = BaseFieldDefinition::create('entity_reference_revisions')
->setLabel(t('Billing information'))
->setDescription(t('Billing profile'))
->setSetting('target_type', 'profile')
->setSetting('handler', 'default')
->setSetting('handler_settings', [
'target_bundles' => [
'customer' => 'customer',
],
])
->setTranslatable(TRUE)
->setDisplayOptions('form', [
'type' => 'commerce_billing_profile',
'weight' => 0,
'settings' => [],
])
->setDisplayConfigurable('form', TRUE)
->setDisplayConfigurable('view', TRUE);
$fields['order_items'] = BaseFieldDefinition::create('entity_reference')
->setLabel(t('Order items'))
->setDescription(t('The order items.'))
->setRequired(TRUE)
->setCardinality(BaseFieldDefinition::CARDINALITY_UNLIMITED)
->setSetting('target_type', 'commerce_order_item')
->setSetting('handler', 'default')
->setDisplayOptions('form', [
'type' => 'inline_entity_form_complex',
'weight' => 0,
'settings' => [
'override_labels' => TRUE,
'label_singular' => t('order item'),
'label_plural' => t('order items'),
],
])
->setDisplayOptions('view', [
'type' => 'commerce_order_item_table',
'weight' => 0,
])
->setDisplayConfigurable('form', TRUE)
->setDisplayConfigurable('view', TRUE);
$fields['adjustments'] = BaseFieldDefinition::create('commerce_adjustment')
->setLabel(t('Adjustments'))
->setCardinality(BaseFieldDefinition::CARDINALITY_UNLIMITED)
->setDisplayOptions('form', [
'type' => 'commerce_adjustment_default',
'weight' => 0,
])
->setDisplayConfigurable('form', TRUE)
->setDisplayConfigurable('view', FALSE);
$fields['total_price'] = BaseFieldDefinition::create('commerce_price')
->setLabel(t('Total price'))
->setDescription(t('The total price of the order.'))
->setReadOnly(TRUE)
->setDisplayOptions('view', [
'label' => 'hidden',
'type' => 'commerce_order_total_summary',
'weight' => 0,
])
->setDisplayConfigurable('form', FALSE)
->setDisplayConfigurable('view', TRUE);
$fields['total_paid'] = BaseFieldDefinition::create('commerce_price')
->setLabel(t('Total paid'))
->setDescription(t('The total paid price of the order.'))
->setDisplayConfigurable('form', FALSE)
->setDisplayConfigurable('view', TRUE);
$fields['balance'] = BaseFieldDefinition::create('commerce_price')
->setLabel(t('Order balance'))
->setDescription(t('The order balance.'))
->setReadOnly(TRUE)
->setComputed(TRUE)
->setClass(OrderBalanceFieldItemList::class)
->setDisplayConfigurable('form', FALSE)
->setDisplayConfigurable('view', TRUE);
$fields['state'] = BaseFieldDefinition::create('state')
->setLabel(t('State'))
->setDescription(t('The order state.'))
->setRequired(TRUE)
->setSetting('max_length', 255)
->setDisplayOptions('view', [
'label' => 'hidden',
'type' => 'state_transition_form',
'settings' => [
'require_confirmation' => TRUE,
'use_modal' => TRUE,
],
'weight' => 10,
])
->setDisplayConfigurable('form', TRUE)
->setDisplayConfigurable('view', TRUE)
->setSetting('workflow_callback', [
'\\Drupal\\commerce_order\\Entity\\Order',
'getWorkflowId',
]);
$fields['data'] = BaseFieldDefinition::create('map')
->setLabel(t('Data'))
->setDescription(t('A serialized array of additional data.'));
$fields['locked'] = BaseFieldDefinition::create('boolean')
->setLabel(t('Locked'))
->setSettings([
'on_label' => t('Yes'),
'off_label' => t('No'),
])
->setDefaultValue(FALSE);
$fields['created'] = BaseFieldDefinition::create('created')
->setLabel(t('Created'))
->setDescription(t('The time when the order was created.'));
$fields['changed'] = BaseFieldDefinition::create('changed')
->setLabel(t('Changed'))
->setDescription(t('The time when the order was last edited.'))
->setDisplayConfigurable('view', TRUE);
$fields['placed'] = BaseFieldDefinition::create('timestamp')
->setLabel(t('Placed'))
->setDescription(t('The time when the order was placed.'))
->setDisplayOptions('view', [
'label' => 'above',
'type' => 'timestamp',
'weight' => 0,
])
->setDisplayConfigurable('view', TRUE);
$fields['completed'] = BaseFieldDefinition::create('timestamp')
->setLabel(t('Completed'))
->setDescription(t('The time when the order was completed.'))
->setDisplayOptions('view', [
'label' => 'above',
'type' => 'timestamp',
'weight' => 0,
])
->setDisplayConfigurable('view', TRUE);
return $fields;
}
public static function getCurrentUserId() {
return [
\Drupal::currentUser()
->id(),
];
}
public static function getWorkflowId(OrderInterface $order) {
$workflow = OrderType::load($order
->bundle())
->getWorkflowId();
return $workflow;
}
}