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

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

namespace Drupal\commercetools\Plugin\Block;

use Drupal\Core\Cache\Cache;
use Drupal\Core\Form\FormStateInterface;
use Symfony\Component\DependencyInjection\ContainerInterface;

/**
 * Defines a base class for listing blocks of commercetools categories.
 */
abstract class CommercetoolsCategoriesListBlockBase extends CommercetoolsCatalogActionBlockBase {

  const MAXIMUM_EXPANDED_TREE = 20;

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

  /**
   * {@inheritdoc}
   */
  public static function create(ContainerInterface $container, array $configuration, $plugin_id, $plugin_definition): self {
    $instance = parent::create(...func_get_args());
    $instance->ct = $container->get('commercetools');
    return $instance;
  }

  /**
   * {@inheritdoc}
   */
  public function getBlockConfigKeys(): array {
    $keys = parent::getBlockConfigKeys();
    $keys[] = 'max_level';
    $keys[] = 'display_from_current';
    $keys[] = 'initial_level';
    $keys[] = 'display_style';
    $keys[] = 'cards_columns';
    $keys[] = 'parent_category';
    return $keys;
  }

  /**
   * {@inheritdoc}
   */
  public function defaultConfiguration(): array {
    return [
      'max_level' => 1,
      'display_from_current' => FALSE,
      'initial_level' => 1,
      'display_style' => 'list',
      'cards_columns' => 3,
      'parent_category' => '',
    ];
  }

  /**
   * {@inheritdoc}
   */
  public function blockForm($form, FormStateInterface $form_state): array {
    $form = parent::blockForm($form, $form_state);

    $categoriesTree = $this->getCategoriesTree();
    $categoryOptions = $this->buildHierarchicalOptions($categoriesTree);
    $categoryOptions = ['' => $this->t('Display from the root')] + $categoryOptions;

    $form['display_from_current'] = [
      '#type' => 'checkbox',
      '#title' => $this->t('Display from current category'),
      '#default_value' => $this->configuration['display_from_current'] ?? FALSE,
      '#description' => $this->t('If checked, the block will use the category from URL.'),
    ];

    $form['parent_category'] = [
      '#type' => 'select',
      '#title' => $this->t('Parent category'),
      '#default_value' => $this->configuration['parent_category'] ?? '',
      '#options' => $categoryOptions,
      '#states' => [
        'visible' => [
          ':input[name="settings[display_from_current]"]' => ['checked' => FALSE],
        ],
      ],
    ];

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

    $form['cards_columns'] = [
      '#type' => 'select',
      '#title' => $this->t('Number of columns (cards only)'),
      '#default_value' => $this->configuration['cards_columns'] ?? 3,
      '#options' => array_combine(range(1, 6), range(1, 6)),
      '#states' => [
        'visible' => [
          ':input[name="settings[display_style]"]' => ['value' => 'cards'],
        ],
      ],
    ];

    $categories = $this->ct->getProductCategoriesTree();
    $maxDepth = $this->getCategoriesTreeDepth($categories);
    $options = range(0, $maxDepth);
    $options[0] = $this->t('Unlimited');
    $form['max_level'] = [
      '#type' => 'select',
      '#title' => $this->t('Number of levels to display'),
      '#default_value' => $this->configuration['max_level'],
      '#options' => $options,
      '#description' => $this->t('Currently active category always expands its children. Sibling categories of level that exceeds this number will be hidden from display.'),
      '#required' => TRUE,
      '#states' => [
        'visible' => [
          ':input[name="settings[display_style]"]' => ['value' => 'list'],
        ],
      ],
    ];

    $form['initial_level'] = [
      '#type' => 'select',
      '#title' => $this->t('Initial visibility level'),
      '#default_value' => $this->configuration['initial_level'] ?? 1,
      '#options' => array_combine(range(1, 10), range(1, 10)),
      '#description' => $this->t('Levels below this number are collapsed by default.'),
    ];

    return $form;
  }

  /**
   * {@inheritdoc}
   */
  public function getCacheContexts(): array {
    $cacheContexts = parent::getCacheContexts();
    return Cache::mergeContexts($cacheContexts, [
      'url.query_args',
    ]);
  }

  /**
   * Provides a categories tree.
   *
   * @param string|null $activeCategory
   *   Any category ID to build active-trail on. Optional.
   *
   * @return array
   *   A tree of categories.
   */
  protected function getCategoriesTree(?string $activeCategory = NULL): array {
    $categories = $this->ct->getProductCategories();

    // Set active-trails if available.
    if ($activeCategory && !empty($categories[$activeCategory])) {
      $categories[$activeCategory]['is_active'] = TRUE;
      do {
        $categories[$activeCategory]['in_active_trail'] = TRUE;
        $activeCategory = $categories[$activeCategory]['parent'] ?? NULL;
      } while (array_key_exists($activeCategory, $categories));
    }

    return $this->ct->getProductCategoriesTree($categories);
  }

  /**
   * Returns the maximum depth of categories tree.
   *
   * @param array $list
   *   A data structure representing the categories tree.
   *
   * @return int
   *   The maximum array depth.
   */
  protected function getCategoriesTreeDepth(array $list): int {
    $max_indentation = 1;
    $array_str = print_r($list, TRUE);
    $lines = explode("\n", $array_str);
    foreach ($lines as $line) {
      if (!stripos($line, '=> Array')) {
        continue;
      }
      $indentation = (strlen($line) - strlen(ltrim($line))) / 4;
      if ($indentation > $max_indentation) {
        $max_indentation = $indentation;
      }
    }
    return (int) ceil(($max_indentation - 1) / 4);
  }

}

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

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