commercetools-8.x-1.2-alpha1/src/Plugin/Block/CommercetoolsProductListBlockBase.php

src/Plugin/Block/CommercetoolsProductListBlockBase.php
<?php

declare(strict_types=1);

namespace Drupal\commercetools\Plugin\Block;

use Drupal\commercetools\CommercetoolsLocalization;
use Drupal\commercetools\Exception\CommercetoolsOperationFailedException;
use Drupal\Core\Form\FormStateInterface;
use Symfony\Component\DependencyInjection\ContainerInterface;

/**
 * Defines a base class for commercetools product list blocks.
 */
abstract class CommercetoolsProductListBlockBase extends CommercetoolsCatalogBlockBase {

  /**
   * The Commercetools service.
   *
   * @var \Drupal\commercetools\CommercetoolsService
   */
  protected $ct;

  /**
   * The commercetools products service.
   *
   * @var \Drupal\commercetools\CommercetoolsProducts
   */
  protected $ctProducts;

  /**
   * The pager manager service.
   *
   * @var \Drupal\Core\Pager\PagerManagerInterface
   */
  protected $pagerManager;

  /**
   * The form builder.
   *
   * @var \Drupal\Core\Form\FormBuilderInterface
   */
  protected $formBuilder;

  /**
   * The config factory.
   *
   * @var \Drupal\Core\Config\ConfigFactoryInterface
   */
  protected $configFactory;

  /**
   * The request stack service.
   *
   * @var \Symfony\Component\HttpFoundation\RequestStack
   */
  protected $requestStack;

  /**
   * The Commercetools API service.
   *
   * @var \Drupal\commercetools\CommercetoolsApiServiceInterface
   */
  protected $ctApi;

  /**
   * {@inheritdoc}
   */
  public static function create(ContainerInterface $container, array $configuration, $plugin_id, $plugin_definition): static {
    $instance = parent::create(...func_get_args());
    $instance->ct = $container->get('commercetools');
    $instance->ctProducts = $container->get('commercetools.products');
    $instance->pagerManager = $container->get('pager.manager');
    $instance->formBuilder = $container->get('form_builder');
    $instance->configFactory = $container->get('config.factory');
    $instance->requestStack = $container->get('request_stack');
    $instance->ctApi = $container->get('commercetools.api');
    return $instance;
  }

  /**
   * {@inheritdoc}
   */
  public function blockForm($form, FormStateInterface $form_state): array {
    $form = parent::blockForm($form, $form_state);
    try {
      $categoriesTree = $this->ct->getProductCategoriesTree();
      $category_options = ['_none' => $this->t('Any (Show all products)')] + $this->buildHierarchicalOptions($categoriesTree);
    }
    catch (CommercetoolsOperationFailedException $e) {
      $form['error'] = [
        '#type' => 'markup',
        '#markup' => '<div class="messages messages--warning">' . $e->getMessage() . '</div>',
        '#weight' => 0,
      ];
      $category_options = ['_none' => $this->t('No categories available due to an error.')];
    }

    $form['style'] = [
      '#type' => 'radios',
      '#title' => $this->t('Style'),
      '#options' => [
        'cards' => $this->t('Cards'),
        'list' => $this->t('List'),
        'titles' => $this->t('Titles'),
      ],
      '#default_value' => $this->configuration['style'] ?? 'cards',
    ];

    $form['columns_number'] = [
      '#type' => 'select',
      '#title' => $this->t('Number of columns'),
      '#options' => array_combine(range(1, 12), range(1, 12)),
      '#default_value' => $this->configuration['columns_number'] ?? 4,
      '#states' => [
        'invisible' => [
          ':input[name="settings[style]"]' => ['value' => 'titles'],
        ],
      ],
    ];

    $form['categories'] = [
      '#type' => 'select',
      '#title' => $this->t('Categories'),
      '#options' => $category_options,
      '#default_value' => $this->configuration['categories'] ?? ['_none'],
      '#multiple' => TRUE,
      '#description' => $this->t('Filter the product list by one or more categories by default. Leave "Any" to allow all categories.'),
    ];

    $form['total_limit'] = [
      '#type' => 'number',
      '#title' => $this->t('Total number of items'),
      '#default_value' => $this->configuration['total_limit'] ?? NULL,
      '#min' => 1,
      '#max' => 100,
      '#description' => $this->t('The total limit of items to be displayed. Leave empty to display all matching products.'),
    ];

    $form['items_per_page'] = [
      '#type' => 'number',
      '#title' => $this->t('Items per page'),
      '#default_value' => $this->configuration['items_per_page'] ?? 10,
      '#min' => 1,
      '#description' => $this->t('The number of products to show per page for this block. If empty, the general items per page value will be used.'),
    ];

    $form['sort_by'] = [
      '#type' => 'select',
      '#title' => $this->t('Sort by'),
      '#options' => $this->getSortByOptions(),
      '#default_value' => $this->configuration['sort_by'] ?? 'createdAt',
      '#description' => $this->t('Choose the field to sort by.'),
    ];

    $form['sort_order'] = [
      '#type' => 'select',
      '#title' => $this->t('Sort order'),
      '#options' => [
        'asc' => $this->t('Ascending'),
        'desc' => $this->t('Descending'),
      ],
      '#default_value' => $this->configuration['sort_order'] ?? 'asc',
      '#description' => $this->t('Choose the sort order.'),
    ];

    $form['advanced'] = [
      '#type' => 'details',
      '#title' => $this->t('Advanced'),
      '#open' => FALSE,
    ];

    $form['advanced']['display_by_sku'] = [
      '#type' => 'textfield',
      '#title' => $this->t('Display products by SKU'),
      '#default_value' => $this->configuration['display_by_sku'] ?? NULL,
      '#description' => $this->t('Using this field you can list product SKUs to display only them.'),
    ];

    $form['advanced']['custom_filters'] = [
      '#type' => 'textarea',
      '#title' => $this->t('Additional filters'),
      '#default_value' => $this->configuration['custom_filters_raw'] ?? '',
      '#description' => $this->t('Here you can put a JSON with custom query filters to apply on the product list, <a href="https://docs.commercetools.com/api/projects/products-search#filters">documentation</a>'),
    ];

    return $form;
  }

  /**
   * {@inheritdoc}
   */
  public function blockValidate($form, FormStateInterface $form_state): void {
    parent::blockValidate($form, $form_state);
    $customFiltersRaw = trim($form_state->getValue(['advanced', 'custom_filters']));
    if (!empty($customFiltersRaw)) {
      json_decode($customFiltersRaw, TRUE);
      if (json_last_error() !== JSON_ERROR_NONE) {
        $form_state->setErrorByName(
          'advanced][custom_filters',
          $this->t('Invalid JSON format for additional filters: @error', [
            '@error' => json_last_error_msg(),
          ])
        );
      }
    }
  }

  /**
   * Gets the sort by options for the block form.
   */
  protected function getSortByOptions(): array {
    $language = $this->configFactory
      ->get(CommercetoolsLocalization::CONFIGURATION_NAME)
      ->get(CommercetoolsLocalization::CONFIG_LANGUAGE);

    return [
      'createdAt' => $this->t('Default'),
      'name.' . $language => $this->t('Name'),
    ];
  }

  /**
   * {@inheritdoc}
   */
  public function blockSubmit($form, FormStateInterface $form_state): void {
    parent::blockSubmit($form, $form_state);
    $this->configuration['style'] = $form_state->getValue('style');
    $categories = array_filter($form_state->getValue('categories'), fn ($category): bool => $category !== '_none');
    $this->configuration['categories'] = $categories;
    $displayBySku = trim($form_state->getValue(['advanced', 'display_by_sku']));
    $this->configuration['display_by_sku'] = $displayBySku === '' ? [] : array_map('trim', explode(',', $displayBySku));
    $customFiltersRaw = trim($form_state->getValue(['advanced', 'custom_filters']));
    $this->configuration['custom_filters_raw'] = $customFiltersRaw;
    $this->configuration['custom_filters'] = $customFiltersRaw === '' ? [] : json_decode($customFiltersRaw, TRUE);
  }

  /**
   * {@inheritdoc}
   */
  public function getBlockConfigKeys(): array {
    $keys = parent::getBlockConfigKeys();
    array_push(
      $keys,
      'total_limit',
      'style',
      'items_per_page',
      'sort_by',
      'sort_order',
      'columns_number',
    );
    return $keys;
  }

  /**
   * Fetches product categories from commercetools.
   */
  protected function fetchCategories(): array {
    $categories = $this->ct->getProductCategories() ?? [];
    $fillChildren = function ($parentId = NULL) use ($categories, &$fillChildren) {
      $children = [];
      foreach ($categories as $category) {
        if (($category['parent']['id'] ?? NULL) == $parentId) {
          $catChildren = $fillChildren($category['id']);
          $category['children'] = $catChildren;
          $children[] = $category;
        }
      }
      return $children;
    };
    return array_filter($fillChildren(), fn ($cat) => empty($cat['parent']['id']));
  }

}

Главная | Обратная связь

drupal hosting | друпал хостинг | it patrol .inc