commercetools-8.x-1.2-alpha1/src/Form/StoreSettingsForm.php
src/Form/StoreSettingsForm.php
<?php
namespace Drupal\commercetools\Form;
use Drupal\commercetools\CommercetoolsLocalization;
use Drupal\commercetools\CommercetoolsService;
use Drupal\Core\Extension\ModuleHandlerInterface;
use Drupal\Core\Form\FormStateInterface;
use Drupal\Core\State\StateInterface;
use Symfony\Component\DependencyInjection\ContainerInterface;
/**
* Configure a Commercetools settings form for this site.
*/
class StoreSettingsForm extends CommercetoolsSettingsFormBase {
const STATE_KEY_LOCALE_TIPS_DISMISSED = 'commercetools.locale_tips_dismissed';
/**
* The commercetools service.
*
* @var \Drupal\commercetools\CommercetoolsService
*/
protected CommercetoolsService $ct;
/**
* The commercetools localization service.
*
* @var \Drupal\commercetools\CommercetoolsLocalization
*/
protected CommercetoolsLocalization $ctLocalization;
/**
* The state store.
*
* @var \Drupal\Core\State\StateInterface
*/
protected StateInterface $state;
/**
* The module handler service.
*
* @var \Drupal\Core\Extension\ModuleHandlerInterface
*/
protected ModuleHandlerInterface $moduleHandler;
/**
* {@inheritdoc}
*/
public static function create(ContainerInterface $container) {
$instance = parent::create($container);
$instance->ct = $container->get('commercetools');
$instance->ctLocalization = $container->get('commercetools.localization');
$instance->state = $container->get('state');
$instance->moduleHandler = $container->get('module_handler');
return $instance;
}
/**
* {@inheritdoc}
*/
public function buildForm(array $form, FormStateInterface $form_state) {
$projectSettings = $this->ctApi->getProjectInfo();
$optionsAny = ['' => $this->t('- Any -')];
$localeOptions[CommercetoolsLocalization::CONFIG_STORE] = $optionsAny;
foreach ($projectSettings['stores'] as $key => $store) {
$localeOptions[CommercetoolsLocalization::CONFIG_STORE][$key] = $this->ctLocalization->fromLocalizedArray($store);
}
foreach ($projectSettings['languages'] as $code) {
$localeOptions[CommercetoolsLocalization::CONFIG_LANGUAGE][$code] = "{$this->ctLocalization->getLanguageName($code)} ({$code})";
}
foreach ($projectSettings['countries'] as $country) {
$localeOptions[CommercetoolsLocalization::CONFIG_COUNTRY][$country] = "{$this->ctLocalization->getCountryName($country)} ({$country})";
}
foreach ($projectSettings['currencies'] as $currency) {
$localeOptions[CommercetoolsLocalization::CONFIG_CURRENCY][$currency] = "{$this->ctLocalization->getCurrencyName($currency)} ({$currency})";
}
$localeOptions[CommercetoolsLocalization::CONFIG_CHANNEL] = $optionsAny;
foreach ($projectSettings['channels'] as $id => $channel) {
$localeOptions[CommercetoolsLocalization::CONFIG_CHANNEL][$id] = $this->ctLocalization->fromLocalizedArray($channel);
}
$form['locale_settings'] = [
'#type' => 'details',
'#open' => !$this->ctLocalization->isConfigured(),
'#title' => $this->t('Locale settings'),
];
$form['locale_settings'][CommercetoolsLocalization::CONFIG_LANGUAGE_FALLBACK] = $this->getFormElement(CommercetoolsLocalization::CONFIG_LANGUAGE_FALLBACK, [
'#type' => 'value',
'#value' => reset($projectSettings['languages']),
], CommercetoolsLocalization::CONFIGURATION_NAME);
$form['locale_settings']['mapping'] = [
'#type' => 'table',
'#title' => 'Drupal Locale mapping with commercetools',
'#header' => [
$this->t('Setting'),
],
];
$settings = $this->ctLocalization->getAllLocalesSettings();
foreach ($localeOptions as $optionKey => $options) {
$form['locale_settings']['mapping'][$optionKey]['row'] = [
'#markup' => $this->getSettingLabel(CommercetoolsLocalization::CONFIGURATION_NAME . ':' . $optionKey),
];
foreach ($this->ctLocalization->languages as $language) {
$id = $language->getId();
$isDefault = $id === $this->ctLocalization->defaultLanguage->getId();
$form['locale_settings']['mapping']['#header'][$id] = "{$language->getName()} ({$id})" . ($isDefault ? ' (default)' : '');
$form['locale_settings']['mapping'][$optionKey][$id] = [
'#type' => 'select',
'#options' => $options,
'#default_value' => $settings[$id][$optionKey],
];
}
}
if (!$this->state->get(self::STATE_KEY_LOCALE_TIPS_DISMISSED)) {
$form['locale_settings']['locale_tips'] = [
'#type' => 'container',
'#attributes' => [
'class' => ['card__content-wrapper', 'color-warning'],
],
'tip_info' => [
'#type' => 'html_tag',
'#tag' => 'p',
'#value' => $this->t('commercetools requires defining currency, language, and country to display products, with additional localization settings being optional based on your requirements.'),
],
'tip_dismiss' => [
'#type' => 'submit',
'#value' => $this->t('Do not show this message again'),
'#submit' => ['::dismissFormTipsSubmit'],
'#ajax' => [
'callback' => '::dismissFormTips',
'wrapper' => 'edit-locale-settings',
'effect' => 'fade',
],
'#attributes' => [
'class' => ['button', 'button--small'],
],
'#weight' => 100,
],
];
if (count($this->ctLocalization->languages) < 2) {
$form['locale_settings']['locale_tips']['tip_locale_enhance'] = [
'#type' => 'html_tag',
'#tag' => 'p',
'#value' => $this->t(
'To enhance your store versatility, set up multi-currency, multi-language, and multi-store configurations following the next steps:',
),
];
$steps = [];
if (!$this->moduleHandler->moduleExists('language')) {
$steps[] = $this->t(
'<a href="@link">Install Drupal Language module</a>',
['@link' => '/admin/modules'],
);
}
$steps[] = $this->t(
'<a href="@link">add various locales</a>',
['@link' => '/admin/config/regional/language/add'],
);
$steps[] = $this->t('complete the form above');
$form['locale_settings']['locale_tips']['tip_locale_enhance_steps'] = [
'#theme' => 'item_list',
'#list_type' => 'ul',
'#items' => $steps,
];
}
}
$form['product_attributes'] = [
'#type' => 'details',
'#open' => TRUE,
'#title' => $this->t('Product types and attributes'),
'#description' => $this->t('By default, all available product types and attributes are displayed in product details. Check options below to customize.'),
'#description_display' => 'before',
];
$productTypes = $this->ct->getProductsTypes();
$attributeTypes = [
"boolean" => $this->t('Yes / No (boolean)'),
"text" => $this->t('Text'),
"ltext" => $this->t('Localized Text'),
"enum" => $this->t('List (enum)'),
"lenum" => $this->t('Localized List (enum)'),
"number" => $this->t('Number'),
"money" => $this->t('Money'),
"date" => $this->t('Date'),
"time" => $this->t('Time'),
"datetime" => $this->t('Date and Time'),
"reference" => $this->t('Reference'),
"set" => $this->t('Set'),
"nested" => $this->t('Nested'),
];
$pageOptions = [];
$optionsByDefault = [];
foreach ($productTypes as $productTypeKey => $productType) {
foreach ($productType['attributeDefinitions'] as $attributeKey => $attribute) {
$isFieldTypeSupported = !in_array($attribute['type'], ['enum', 'lenum', 'ltext']) && $attribute['isSearchable'];
$supportedText = $isFieldTypeSupported ? '' : ', ' . $this->t('not supported');
$attributeLabel = $attributeTypes[$attribute['type']] ?? $this->t('Other');
$optionKey = "{$productTypeKey}_{$attributeKey}";
$pageOptions[$optionKey] = $this->t('@productType: <b>@attrName</b> (@attrType)', [
'@attrName' => $attribute['label'],
'@attrType' => $attributeLabel,
'@productType' => $productType['name'],
]);
$optionsByDefault[] = $optionKey;
}
}
$fieldsets = [
'page' => [
'label' => $this->t('Customize a list for product detailed page'),
'description' => $this->t('Only enabled product types/attributes will be listed for products.'),
'enableKey' => CommercetoolsService::CONFIG_PAGE_ATTRIBUTES_ENABLED,
'attributesKey' => CommercetoolsService::CONFIG_PAGE_ATTRIBUTES,
'options' => $pageOptions,
],
];
foreach ($fieldsets as $fieldsetKey => $fieldset) {
$typeWrapperKey = "{$fieldsetKey}_wr";
$optionsWrapperKey = "{$fieldset['attributesKey']}_wr";
$form['product_attributes'][$typeWrapperKey] = [
'#type' => 'fieldset',
$fieldset['enableKey'] => [
'#type' => 'checkbox',
'#title' => $fieldset['label'],
'#description' => $fieldset['description'],
'#config_target' => CommercetoolsService::CONFIGURATION_NAME . ':' . $fieldset['enableKey'],
],
$optionsWrapperKey => [
'#type' => 'container',
'#states' => [
'visible' => [
':input[name="' . $fieldset['enableKey'] . '"]' => [
'checked' => TRUE,
],
],
],
$fieldset['attributesKey'] => [
'#type' => 'checkboxes',
'#options' => $fieldset['options'],
'#config_target' => CommercetoolsService::CONFIGURATION_NAME . ':' . $fieldset['attributesKey'],
'#default_value' => array_keys($pageOptions),
],
],
];
if (!$this->config(CommercetoolsService::CONFIGURATION_NAME)->get($fieldset['attributesKey'])) {
$form['product_attributes'][$typeWrapperKey][$optionsWrapperKey][$fieldset['attributesKey']]['#default_value'] = $optionsByDefault;
}
}
$form['product_display'] = [
'#type' => 'details',
'#open' => TRUE,
'#title' => $this->t('Default settings for displaying products'),
'#description' => $this->t('Configures display product settings that will be used by default on all pages and blocks, and can be overridden on individual block settings.'),
'#description_display' => 'before',
];
$form['product_display'][CommercetoolsService::CONFIG_CARD_IMAGE_STYLE] = $this->getFormElement(CommercetoolsService::CONFIG_CARD_IMAGE_STYLE, [
'#type' => 'select',
'#options' => [
'thumb' => $this->t('Thumb (50x50)'),
'small' => $this->t('Small (150x150)'),
'medium' => $this->t('Medium (400x400)'),
'large' => $this->t('Large (700x700)'),
'zoom' => $this->t('Zoom (1400x1400)'),
],
'#description' => $this->t('Allows loading reduced thumbnails of product images on the product cards. <strong>Warning!</strong> Thumbnails generation works only for images, uploaded as files using commercetools Merchant Center. For linked images commercetools doesn\'t provide API to resize images, therefore images will be broken. Use the "Original size" option if the thumbnail generation doesn\'t work for your project.</b>'),
'#empty_option' => $this->t('Original size'),
]);
$form['product_display'][CommercetoolsService::CONFIG_ITEMS_PER_PAGE] = $this->getFormElement(CommercetoolsService::CONFIG_ITEMS_PER_PAGE, [
'#title' => $this->t('Items per page'),
'#type' => 'number',
'#description' => $this->t('Number of product items displayed in the product catalog.'),
'#default_value' => $this->config(CommercetoolsService::CONFIGURATION_NAME)->get(CommercetoolsService::CONFIG_ITEMS_PER_PAGE),
'#min' => 1,
]);
$form['product_display']['customer_group'] = [
'#title' => $this->t('Customer Group'),
'#type' => 'select',
'#description' => $this->t('Customer group for applying group-specific prices.'),
'#options' => $projectSettings['customerGroups'] ?? [],
'#empty_option' => $this->t('- None -'),
];
$form['product_display']['hide_products_with_no_prices'] = [
'#title' => $this->t('Hide products if no price is available'),
'#type' => 'checkbox',
];
$form['product_display'][CommercetoolsService::CONFIG_UNAVAILABLE_DATA_TEXT] = $this->getFormElement(CommercetoolsService::CONFIG_UNAVAILABLE_DATA_TEXT, [
'#title' => $this->t('Unavailable price text'),
'#description' => $this->t('Text to display in place of price when it is unavailable.'),
'#default_value' => $this->config(CommercetoolsService::CONFIGURATION_NAME)->get(CommercetoolsService::CONFIG_UNAVAILABLE_DATA_TEXT),
]);
return parent::buildForm($form, $form_state);
}
/**
* {@inheritdoc}
*/
public function submitForm(array &$form, FormStateInterface $form_state) {
$submittedMapping = $form_state->getValue('mapping');
$settings = [];
foreach ($submittedMapping as $option => $languages) {
foreach ($languages as $code => $value) {
$settings[$code][$option] = $value;
}
}
$this->ctLocalization->saveAllLocalesSettings($settings);
parent::submitForm($form, $form_state);
}
/**
* Custom form submit handler to dismiss form tips.
*
* @param array $form
* The form build array.
* @param \Drupal\Core\Form\FormStateInterface $form_state
* The form state.
*/
public function dismissFormTipsSubmit(array &$form, FormStateInterface $form_state): void {
$this->state->set(self::STATE_KEY_LOCALE_TIPS_DISMISSED, TRUE);
unset($form['locale_settings']['locale_tips']);
$form_state->setRebuild();
}
/**
* Ajax callback to dismiss form tips.
*
* @param array $form
* The form build array.
*
* @return array
* An updated form element.
*/
public function dismissFormTips(array $form): array {
return $form['locale_settings'];
}
}
