Skip to content

Instantly share code, notes, and snippets.

@BBGuy
Last active November 15, 2023 12:20
Show Gist options
  • Star 2 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save BBGuy/c362a30bb0dda65777b076040b14cab5 to your computer and use it in GitHub Desktop.
Save BBGuy/c362a30bb0dda65777b076040b14cab5 to your computer and use it in GitHub Desktop.
<?php
// some examples on
// https://docs.drupalcommerce.org/commerce2/developer-guide/products/product-architecture/code-recipes
// https://docs.drupalcommerce.org/commerce2/developer-guide/products/product-management/code-recipes
// https://docs.drupalcommerce.org/commerce2/developer-guide/products/displaying-products/code-recipes
// Work with orders.
/** @var \Drupal\commerce_order\Entity\OrderInterface $order */
$order = \Drupal::entityTypeManager()->getStorage('commerce_order')->load($order_id);
$order_id = $order->id();
// Work with line items.
$qty = $order_item->getQuantity();
// Work with products
// Load the product mathod 1.
$product = \Drupal\commerce_product\Entity\Product::load($prod_id);
// Load the product mathod 2.
$entity = \Drupal::entityTypeManager()->getStorage('commerce_product')->load($prod_id);
// Load the product mathod 3.
$entity = \Drupal::service('entity_type.manager')->getStorage('commerce_product')->load($prod_id);
// Check the status
$is_published = $product->isPublished();
// Get the Product Variation ID from the product.
$variation_id = $product->getVariationIds()[0];
// Get the Product Variation from the product.
$variation = $product->getDefaultVariation();
// Load the product variation.
$variation_storage = \Drupal::service('entity_type.manager')->getStorage('commerce_product_variation');
$product_variation = $variation_storage->load($variation_id);
$variation_id = $product_variation->id();
// Get the product form the variation
$product = $product_variation->getProduct();
$product_id = $product_variation->getProductId();
// Reading price from an entity \Drupal\Core\Entity\EntityInterface $entity (not using purchasable entity)
$number = $entity->price->number;
$curreny = $entity->price->currency_code;
$price_break_1 = $entity->field_price_break_1->number;
$price_break_1 = $entity->field_price_break_2->number;
// Cycle the line items of an order and load each product.
foreach ($order->getItems() as $id => $order_item) {
$purchased_entity = $order_item->getPurchasedEntity();
$pe_price = $purchased_entity->getPrice();
if (!$purchased_entity) {
// Not every order item has a purchased entity.
continue;
}
$name = $purchased_entity->getTitle();
$qty = $order_item->getQuantity();
// Unit price
$unit_price_obj = $order_item->getUnitPrice();
$price_amount = $unit_price_obj->getNumber();
$price_currency = $unit_price_obj->getCurrencyCode();
// Line total price
$line_price_obj = $order_item->getTotalPrice();
}
// Set the price example 1
$new_price = new Price('12.36', 'GBP');
$variation->set('price', $new_price);
$variation->save();
// Set the price example 2
/** @var \Drupal\commerce_product\ProductVariationStorageInterface $variation_storage */
$variation_storage = \Drupal::service('entity_type.manager')->getStorage('commerce_product_variation');
/** @var \Drupal\commerce_product\Entity\ProductVariationInterface|null */
$variation = $variation_storage->loadBySku($part_number);
if (isset($variation)) {
$price_obj = $variation->getPrice();
$price_currency = $price_obj->getCurrencyCode();
$new_price = new Price('12.36', $price_currency);
$variation->set('price', $new_price);
$variation->save();
}
// Conver currency (convert order sub total price to pounds for comparicen)
$order_total = $order->getSubtotalPrice();
// Make sure we are using £.
$order_total_amount_gbp = \Drupal::service('commerce_currency_resolver.calculator')->priceConversion($order_total, 'GBP');
$order_total_amount = (float) $order_total_amount_gbp->getNumber();
if ($order_total_amount < 175) {
// Do somthing.
}
// Needs the following use at the top of the file:
// use Drupal\commerce_product\Entity\ProductVariationInterface;
// Check if a purchasable entity is a product variation.
if ($purchasable_entity instanceof ProductVariationInterface) {
// Get the product variation from a line item.
$product_variation = $line_item->getPurchasedEntity();
}
// Get the Cart provider service
$cart_provider = \Drupal::service('commerce_cart.cart_provider');
// Get all the carts.
$all_carts = \Drupal::service('commerce_cart.cart_provider')->getCarts();
// Get the current store.
$store = \Drupal::service('commerce_store.current_store')->getStore();
// Get the cart for the curent store.
$cart = \Drupal::service('commerce_cart.cart_provider')->getCart('default', $store);
// get the store from an order
$order->getStore();
$order->getStoreid();
// Add to cart form
// Get the add to cart entity form.
$entity_form = $form_state->getFormObject();
// Get the line item and $purchased_entity.
$order_item = $entity_form->getEntity();
/** @var \Drupal\commerce\PurchasableEntityInterface $purchased_entity */
$purchased_entity = $order_item->getPurchasedEntity();
// Get the $context from the Add to cart form
/** @var \Drupal\commerce_product\Entity\ProductInterface $product */
$product = $form_state->get('product');
$selected_variation_id = $form_state->get('selected_variation');
if (!empty($selected_variation_id)) {
$selected_variation = \Drupal\commerce_product\Entity\ProductVariation::load($selected_variation_id);
}
else {
$selected_variation = $product->getDefaultVariation();
}
$context = commerce_stock_enforcement_get_context($selected_variation);
// Working with the cart page
// Get the order from the form state.
$order = $form_state->getFormObject()->getEntity();
// Checkout
// Check if the checkout form. need to make sure its not the commerce_checkout_flow_form (used to create new checkout flows)
if (strpos($form_id, "commerce_checkout_flow") !== false && $form_state->getFormObject()->getBaseFormId() == 'commerce_checkout_flow') {
// Get the order from the form
/** @var Drupal\Core\Form\FormInterface $form_object */
$form_object = $form_state->getFormObject();
/** @var \Drupal\commerce_order\Entity\OrderInterface $order */
$order = $form_object->getOrder();
// get a field value using getValue(), check it and cycle using the store.
$store = $context->getStore();
$locations = $store->field_available_stock_locations->getValue();
// If we have store locations.
if (!empty($locations)) {
// Load them.
$store_locations = [];
foreach ($locations as $location) {
$store_locations[$location['target_id']] = $location['target_id'];
}
$store_locations = $this->loadMultiple($store_locations);
}
// Check what type is a PurchasableEntity.
$entity_type = $entity->getEntityTypeId(); //example: commerce_product_variation
$entity_bundle = $entity->bundle(); //example: default
// Reading a field with a single value - all the below will return the same value
$external_product_id = $entity->field_external_product_id->getValue()[0]['value'];
$external_product_id = $entity->field_external_product_id->getString();
$external_product_id = $entity->field_external_product_id->value;
$external_product_id = $entity->field_external_product_id[0]->value;
// User data
// Get details from the order
$billing_profile = $order->getBillingProfile();
$email = $this->order->getEmail();
$address = $billing_profile->address->first();
$line_1 = $address->address_line1,
$line_2 = $address->address_line2,
$city = $address->locality,
$company = $address->organization,
$country = $address->country_code,
$first_name = $address->given_name,
$middle_name = $address->additional_name,
$last_name = $address->family_name,
$state = $address->administrative_area,
$post_code = $address->postal_code,
$custom_field $order->field_custom_field;
// Update order
$order->field_custom_field = 'custom value';
$order->save();
// Get Billing and shipping Profiles.
$profiles = $order->collectProfiles();
if (isset($profiles['billing'])) {
$billing_profile = $profiles['billing'];
}
if (isset($profiles['shipping'])) {
$shipping_profile = $profiles['shipping'];
}
// Get address as an array
$billing_profile->get('address')->first()->toArray())
// Check a profile type
$profile_type = $profile->type->target_id;
if ($profile_type == 'customer) {
// Customer profile code
}
// Shipping
// Get the shipments entity from the order reference.
$shipments = $order->shipments->referencedEntities();
$shipments = $order->get('shipments')->referencedEntities();
// Get the first shipment entity.
/** @var \Drupal\commerce_shipping\Entity\ShipmentInterface $shipment */
$shipment = reset($shipments);
// Get shipping Profile
$shipping_profile = $shipment->getShippingProfile();
// Get the address (from this point its the same as billing address)
$address = $shipping_profile->address->first();
$line_1 $shipping_profile->get('address')->address_line1;
// Get the address book profile ID.
$address_book_profile_id = $shipping_profile->getData('address_book_profile_id');
$address_book_profile = Profile::load($address_book_profile_id);
$is_default = $address_book_profile->isDefault();
// Shipping Method info.
$shipping_method = $shipment->getShippingMethod();
$shipping_method_label = $shipment->getShippingMethod()->label();
$shipping_method_id = $shipment->getShippingMethodId();
// Shipping service info.
$shipping_service = $shipment->getShippingService();
// Amount.
$shipping_amount_obj = $shipment->getAmount();
$shipping_original_amount_obj = $shipment->getOriginalAmount();
$shipping_amount = $shipping_amount_obj->getNumber();
$shipping_amount_currency =$shipping_amount_obj->getCurrencyCode()
// Other
$package_type = $shipment->getPackageType();
$package_type = $shipment->getPackageType();
$package_type_id = $shipment->getPackageType()->getId();
// Order states - check for state change
$order_state = $order->getState();
$new_state = $order_state->getLabel();
$original_state = $order_state->getOriginalLabel();
\Drupal::messenger()->addMessage(t('state changed from @from to @to.', ['@from' => $original_state, '@to' => $new_state]));
// Order Workflow
// Gets the workflow group i.e. commerce_order.
$workflow_id = $order->getState()->getWorkflow()->getId();
// Get the workflow ID i.e. order_default, order_fulfillment ..
$workflow_group = $order->getState()->getWorkflow()->getGroup();
// Check it is the base commerce_order workflow
if ($order->getState()->getWorkflow()->getGroup() !== 'commerce_order') {
return;
}
// Price adjustments
// full documentation: https://docs.drupalcommerce.org/commerce2/developer-guide/pricing/adjustments
/** @var \Drupal\commerce_order\Entity\OrderItemInterface $order_item */
$adjustment_amount = $order_item->getUnitPrice()->multiply(0.1);
$order_item->addAdjustment(new Adjustment([
'type' => 'custom',
'label' => 'Plus 10%',
'amount' => $adjustment_amount,
'percentage' => '0.1',
'included' => FALSE,
'locked' => TRUE,
]));
$order_item->addAdjustment(new Adjustment([
'type' => 'fee',
'label' => '$10 fee',
'amount' => new Price('10.00', 'USD'),
]);
// Read pricing information.
$order_item->getUnitPrice();
$order_item->getTotalPrice();
$order_item->getAdjustedTotalPrice();
$order_item->getAdjustedTotalPrice(['custom']);
$order_item->getAdjustedTotalPrice(['fee']);
// Order adjustments
$order->addAdjustment(new Adjustment([
'type' => 'fee',
'label' => 'Handling fee',
'amount' => new Price('10.00', 'USD'),
'locked' => TRUE,
]));
// Read pricing information.
$order->getTotalPrice();
$order->getSubtotalPrice();
$order->getAdjustments();
$order->getAdjustments(['fee'])
// Split a $10 discount across all the lines of an order.
$splitter = \Drupal::getContainer()->get('commerce_order.price_splitter');
/** @var \Drupal\commerce_order\Entity\OrderInterface $order */
$amounts = $splitter->split($order, new Price('10.00', 'USD'));
foreach ($order->getItems() as $order_item) {
if (isset($amounts[$order_item->id()])) {
$order_item->addAdjustment(new Adjustment([
'type' => 'custom',
'label' => $this->t('Special'),
'amount' => $amounts[$order_item->id()]->multiply('-1'),
]));
}
}
// Calculate the total unit discount for a line:
$purchased_entity = $order_item->getPurchasedEntity();
$purchased_entity_price = $purchased_entity->getPrice()->getNumber();
$line_adjustmented_unit_price = $order_item->getAdjustedUnitPrice()->getNumber();
$unit_discounbt = $purchased_entity_price - $line_adjustmented_unit_price;
<?php
//** Stock Transactions **//
// Create a stock transaction
$stockManager = \Drupal::service('commerce_stock.service_manager');
// High level typed transaction using the stock manager.
$stockManager->receiveStock($purchasable_entity, $location_id, $zone, $quantity, $unit_cost, $message);
// Low level un-typed transaction using the stock updater.
$stockManager->getService($purchasable_entity)->getStockUpdater()->createTransaction($purchasable_entity, $location_id, $zone, $quantity, $unit_cost, $transaction_type, $metadata);
//** Use Commerce Stock to check stock **//
// The easy way to check.
/** @var \Drupal\commerce_stock\StockServiceManagerInterface $stockManager */
$stockManager = \Drupal::service('commerce_stock.service_manager');
$stock = $stockManager->getStockLevel($variation);
// The long way.
//Get the Stock manager:
/** @var \Drupal\commerce_stock\StockServiceManagerInterface $stockManager */
$stockManager = \Drupal::service('commerce_stock.service_manager');
// Get the Stock service for the PurchasableEntity and use that to get the stock checker.
$stock_service = $stockManager->getService($variation);
$stock_checker = $stock_service->getStockChecker();
// You can then check if it is always in stock:
$is_always_in_stock = $stock_checker->getIsAlwaysInStock($variation);
// Get the configuration object. Needed to get the locations to check for.
$stock_config = $stock_service->getConfiguration();
// Get the context.
$context = commerce_stock_enforcement_get_context($variation);
// and finally you can get the stock level:
$stock_level = $stock_checker->getTotalStockLevel(
$variation,
$stock_config->getAvailabilityLocations($context, $variation)
);
//** Used Drupal Commerce to check stock **//
// Deprecated/does not work - Check if available using drupal commerce.
/** @var \Drupal\commerce\AvailabilityManager $availabilityManager */
$availabilityManager = \Drupal::service('commerce.availability_manager');
// Get the context.
$context = commerce_stock_enforcement_get_context($variation);
// Check
$availabe = $availabilityManager->check($variation, 1, $context);
// Not sure - New way to check with core drupal commerce
/** @var \Drupal\commerce_order\AvailabilityManager $availabilityManager */
$availabilityManager = \Drupal::service('commerce.availability_manager');
// Get the context.
$context = commerce_stock_enforcement_get_context($variation);
// Check
$order_item = @todo - get an item from the product.
$availabe = $availabilityManager->check($order_item, $context);
// Get Stock level
// Get the Stock service for the PurchasableEntity and use that to get the stock checker.
$stock_service = $stockManager->getService($entity);
$stock_checker = $stock_service->getStockChecker();
// You can then check if it is always in stock:
stock_checker->getIsAlwaysInStock($entity)
// Get the configuration object. Needed to get the locations to check for.
// $stock_config = $stock_service->getConfiguration();
// and finally you can get the stock level:
$stock_level = $stock_checker->getTotalStockLevel(
$entity,
$stock_config->getAvailabilityLocations($context, $entity)
);
<?php
// Delete a product and its variations.
function RemoveProduct($product_id) {
/** @var \Drupal\commerce_product\Entity\ProductInterface $product */
$product = \Drupal\commerce_product\Entity\Product::load($product_id);
// Delete all product variations associated with the product (should be only one).
$variations = $product->getVariations();
foreach ($variations as $variation) {
$variation->delete();
}
// Delete the product
$product->delete();
}
<?php
// Util functions for https://www.drupal.org/project/commerce_exchanger
// used for currency convertion.
/** @var \Drupal\commerce_exchanger\DefaultExchangerCalculator $exchanger_calculate */
$exchanger_calculator = \Drupal::service('commerce_exchanger.calculate');
// Conver unit price to GBP
$unit_price = $exchanger_calculator->priceConversion($unit_price, 'GBP');
// Get the rates.
$rates = $exchanger_calculator->getExchangeRates();
// Get the € to £ rate (make sure you check it is set before using)
$ex_rate = $rates['EUR']['GBP']['value'];
// Use commerce core functionality to convert the price.
$gbp_unit_price = $eur_unit_price->convert('GBP', $ex_rate);
<?php
// Create a product and variation
public function createProduct(array $product) {
$sku = strtoupper($product['sku']);
$title = $product['title'];
// Create product variatin.
$variation = ProductVariation::create([
'type' => 'default',
'sku' => $sku,
'status' => TRUE,
'price' => new Price('25.99', 'GBP'),
]);
$variation->save();
$variations = [$variation];
// Create the product
$product = Product::create([
'type' => 'default',
'title' => $title,
'variations' => $variations,
]);
$product->save();
}
<?php
// Payment method.
$payment_method = $order->get('payment_method')->entity;
// Payment method values.
$method_id = $payment_method->get('method_id')->value;
$payment_type = $payment_method->get('type')->value;
$card_type = $payment_method->get('card_type')->value;
// The remote ID returned by the request.
$remote_id = $payment_method->get('remote_id')->value;
// method + last two card digits.
$payment_method->label();
// Detailed information not needed as includes billing information.
$view_builder = $this->entityTypeManager->getViewBuilder('commerce_payment_method');
$payment_summary = $view_builder->view($payment_method, 'default');
// Payment Gateway
$payment_gateway = $payment_method->get('payment_gateway')->referencedEntities()[0];
$payment_gateway_mode = $payment_method->get('payment_gateway_mode')->value;
$payment_gateway_id = $payment_gateway->get('id');
$payment_gateway_configuration = $payment_gateway->get('configuration');
// Payment Gateway API Key
$api_key = $payment_gateway_configuration['api_key'];
// Get payment_method details for templating.
$payment_method = $order->get('payment_method')->entity;
if ($payment_method) {
// method + last two card digits.
$payment_summary = $payment_method->label();
}
else {
/** @var \Drupal\commerce_payment\Entity\PaymentGatewayInterface $payment_gateway */
$payment_gateway = $order->get('payment_gateway')->entity;
$payment_summary = [
'payment_gateway' => [
'#markup' => $payment_gateway->getPlugin()->getDisplayLabel(),
],
];
}
$body['#payment_method'] = $payment_summary;
<?php
// Also see examples in main Commerce 2.x code.php file.
// Create a price object
$price = new Price(10.50, 'GBP');
// Display
/** @var \CommerceGuys\Intl\Formatter\CurrencyFormatterInterface $currency_formatter */
$currency_formatter = \Drupal::service('commerce_price.currency_formatter');
$formatted_price = $currency_formatter->format($price->getNumber(), $price->getCurrencyCode());
// Convert from one currency to another.
/** @var \Drupal\commerce_currency_resolver\PriceExchangerCalculator $currency_calculator */
$currency_calculator = \Drupal::service('commerce_currency_resolver.calculator');
$local_price = $currency_calculator->priceConversion($price_from, $currency_code);
<?php
// We have two methods For controlling prices:
//
// Price resolvers:
// * Using weights the first to resolve the price is the one used.
// * You can't have two resolvers used on a single price so if you are on a multi-currency site this will be an issue.
// * Resolvers set the base price
//
// Adjustments:
// You can have multiple adjustments per order line.
// The adjustments themselves are a part of the order line so you can use those and the base price to do calculations, like remove the VAT element of an order.
// Using Price resolvers (notes)
// ============================
// Create the service - check what other price resolvers you have on the system and set the weight acordingly.
// Resolver that needs currency conversion
// Make sure you add the following two services to your class: 'commerce_currency_resolver.current_currency' & 'commerce_currency_resolver.calculator'
// After calculating the price add:
$resolved_currency = $this->currentCurrency->getCurrency();
if ($resolved_currency !== $price->getCurrencyCode()) {
$converted_price = $this->priceExchanger->priceConversion($price, $resolved_currency);
return $converted_price;
}
else {
return $price;
}
// Using Adjustments
// ====================
// Adjustments are added usin a Order processor service (commerce_order.order_processor)
// Below is a simple example from commerce_order_test.
// For more complaxexamples see "class PromotionOrderProcessor" and "class TaxOrderProcessor".
// commerce_order_test_services.yml file
commerce_order_test.test_adjustment_processor:
class: Drupal\commerce_order_test\TestAdjustmentProcessor
tags:
- { name: commerce_order.order_processor, priority: 500, adjustment_type: test_adjustment_type }
// TestAdjustmentProcessor.php
namespace Drupal\commerce_order_test;
use Drupal\commerce_order\Adjustment;
use Drupal\commerce_order\Entity\OrderInterface;
use Drupal\commerce_order\OrderProcessorInterface;
use Drupal\commerce_price\Price;
/**
* Adds order and order item adjustments for testing purposes.
*/
class TestAdjustmentProcessor implements OrderProcessorInterface {
/**
* {@inheritdoc}
*/
public function process(OrderInterface $order) {
foreach ($order->getItems() as $order_item) {
// Add adjustment for PriceCalculatorTest.
if ($order->getEmail() == 'user2@example.com') {
$order_item->addAdjustment(new Adjustment([
'type' => 'test_adjustment_type',
'label' => '$2.00 fee',
'amount' => new Price('2.00', 'USD'),
]));
}
}
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment