From f656b7fd590da2ef4627ac141387bfe2c805adc0 Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?Valentino=20Me=C4=91imorec?=
 <43341-valic@users.noreply.drupalcode.org>
Date: Mon, 9 Oct 2023 11:21:20 +0000
Subject: [PATCH] Issue #3381018: Add price field formatter to display
 converted price

---
 config/schema/commerce_exchanger.schema.yml   |  14 ++
 .../PriceExchangerFormatter.php               | 150 ++++++++++++++++++
 2 files changed, 164 insertions(+)
 create mode 100644 src/Plugin/Field/FieldFormatter/PriceExchangerFormatter.php

diff --git a/config/schema/commerce_exchanger.schema.yml b/config/schema/commerce_exchanger.schema.yml
index e42556c..58b966c 100644
--- a/config/schema/commerce_exchanger.schema.yml
+++ b/config/schema/commerce_exchanger.schema.yml
@@ -82,3 +82,17 @@ commerce_exchanger.latest_exchange_rates.*:
             sync:
               type: integer
               label: 'Sync'
+
+field.formatter.settings.commerce_price_exchanger:
+  type: mapping
+  label: 'Exchanger price formatter settings'
+  mapping:
+    strip_trailing_zeroes:
+      type: boolean
+      label: 'Strip trailing zeroes after the decimal point'
+    currency_display:
+      type: string
+      label: 'Currency display'
+    target_currency:
+      type: string
+      label: 'Target currency'
diff --git a/src/Plugin/Field/FieldFormatter/PriceExchangerFormatter.php b/src/Plugin/Field/FieldFormatter/PriceExchangerFormatter.php
new file mode 100644
index 0000000..69b129d
--- /dev/null
+++ b/src/Plugin/Field/FieldFormatter/PriceExchangerFormatter.php
@@ -0,0 +1,150 @@
+<?php
+
+namespace Drupal\commerce_exchanger\Plugin\Field\FieldFormatter;
+
+use CommerceGuys\Intl\Formatter\CurrencyFormatterInterface;
+use Drupal\commerce_exchanger\ExchangerCalculatorInterface;
+use Drupal\commerce_price\Plugin\Field\FieldFormatter\PriceDefaultFormatter;
+use Drupal\Core\Entity\EntityTypeManagerInterface;
+use Drupal\Core\Field\FieldDefinitionInterface;
+use Drupal\Core\Field\FieldItemListInterface;
+use Drupal\Core\Form\FormStateInterface;
+use Drupal\Core\Language\LanguageInterface;
+use Symfony\Component\DependencyInjection\ContainerInterface;
+
+/**
+ * Plugin implementation of the 'commerce_price_exchanger' formatter.
+ *
+ * @FieldFormatter(
+ *   id = "commerce_price_exchanger",
+ *   label = @Translation("Currency converter price"),
+ *   field_types = {
+ *     "commerce_price"
+ *   }
+ * )
+ */
+class PriceExchangerFormatter extends PriceDefaultFormatter {
+
+  /**
+   * The price exchanger.
+   *
+   * @var \Drupal\commerce_exchanger\ExchangerCalculatorInterface
+   */
+  protected $priceExchanger;
+
+  /**
+   * The entity type manager.
+   *
+   * @var \Drupal\Core\Entity\EntityTypeManagerInterface
+   */
+  protected $entityTypeManager;
+
+  /**
+   * Constructs a new PriceConvertedFormatter object.
+   *
+   * @param string $plugin_id
+   *   The plugin_id for the formatter.
+   * @param mixed $plugin_definition
+   *   The plugin implementation definition.
+   * @param \Drupal\Core\Field\FieldDefinitionInterface $field_definition
+   *   The definition of the field to which the formatter is associated.
+   * @param array $settings
+   *   The formatter settings.
+   * @param string $label
+   *   The formatter label display setting.
+   * @param string $view_mode
+   *   The view mode.
+   * @param array $third_party_settings
+   *   Any third party settings.
+   * @param \CommerceGuys\Intl\Formatter\CurrencyFormatterInterface $currency_formatter
+   *   The currency formatter.
+   * @param \Drupal\commerce_exchanger\ExchangerCalculatorInterface $price_exchanger
+   *   The price exchanger.
+   * @param \Drupal\Core\Entity\EntityTypeManagerInterface $entity_type_manager
+   *   The entity type manager.
+   */
+  public function __construct($plugin_id, $plugin_definition, FieldDefinitionInterface $field_definition, array $settings, $label, $view_mode, array $third_party_settings, CurrencyFormatterInterface $currency_formatter, ExchangerCalculatorInterface $price_exchanger, EntityTypeManagerInterface $entity_type_manager) {
+    parent::__construct($plugin_id, $plugin_definition, $field_definition, $settings, $label, $view_mode, $third_party_settings, $currency_formatter);
+    $this->priceExchanger = $price_exchanger;
+    $this->entityTypeManager = $entity_type_manager;
+  }
+
+  /**
+   * {@inheritdoc}
+   */
+  public static function create(ContainerInterface $container, array $configuration, $plugin_id, $plugin_definition) {
+    return new static($plugin_id,
+      $plugin_definition,
+      $configuration['field_definition'],
+      $configuration['settings'],
+      $configuration['label'],
+      $configuration['view_mode'],
+      $configuration['third_party_settings'],
+      $container->get('commerce_price.currency_formatter'),
+      $container->get('commerce_exchanger.calculate'),
+      $container->get('entity_type.manager'));
+  }
+
+  /**
+   * {@inheritdoc}
+   */
+  public static function defaultSettings() {
+    return ['target_currency' => 'USD'] + parent::defaultSettings();
+  }
+
+  /**
+   * {@inheritdoc}
+   */
+  public function settingsForm(array $form, FormStateInterface $form_state) {
+    $elements = parent::settingsForm($form, $form_state);
+    $currency_storage = $this->entityTypeManager->getStorage('commerce_currency');
+    // Get all active currencies.
+    /** @var \Drupal\commerce_price\Entity\CurrencyInterface[] $active_currencies */
+    $active_currencies = $currency_storage->loadByProperties(['status' => 1]);
+    $options = [];
+    foreach ($active_currencies as $active_currency) {
+      $options[$active_currency->getCurrencyCode()] = $active_currency->getName();
+    }
+
+    $elements['target_currency'] = [
+      '#type' => 'radios',
+      '#title' => $this->t('Target currency'),
+      '#options' => $options,
+      '#default_value' => $this->getSetting('target_currency'),
+    ];
+    return $elements;
+  }
+
+  /**
+   * {@inheritdoc}
+   */
+  public function settingsSummary() {
+    $summary = parent::settingsSummary();
+    $target_currency = $this->getSetting('target_currency');
+    $summary[] = $this->t('Target currency: @target_currency.', ['@target_currency' => $target_currency]);
+    return $summary;
+  }
+
+  /**
+   * {@inheritdoc}
+   */
+  public function viewElements(FieldItemListInterface $items, $langcode) {
+    $options = $this->getFormattingOptions();
+    $elements = [];
+    foreach ($items as $delta => $item) {
+      $price = $item->toPrice();
+      $converted_price = $this->priceExchanger->priceConversion($price, $this->getSetting('target_currency'));
+      $elements[$delta] = [
+        '#markup' => $this->currencyFormatter->format($converted_price->getNumber(), $converted_price->getCurrencyCode(), $options),
+        '#cache' => [
+          'contexts' => [
+            'languages:' . LanguageInterface::TYPE_INTERFACE,
+            'country',
+          ],
+        ],
+      ];
+    }
+    return $elements;
+  }
+
+}
-- 
GitLab