acquia_commercemanager-8.x-1.122/modules/acm_sku/src/SKUFieldsManager.php

modules/acm_sku/src/SKUFieldsManager.php
<?php

namespace Drupal\acm_sku;

use Drupal\Core\Config\ConfigFactoryInterface;
use Drupal\Core\Entity\EntityDefinitionUpdateManagerInterface;
use Drupal\Core\Entity\EntityTypeManagerInterface;
use Drupal\Core\Extension\ModuleHandlerInterface;
use Psr\Log\LoggerInterface;

/**
 * Class SKUFieldsManager.
 *
 * @package Drupal\acm_sku
 */
class SKUFieldsManager {

  const BASE_FIELD_ADDITIONS_CONFIG = 'acm_sku.base_field_additions';

  /**
   * The Config Factory service.
   *
   * @var \Drupal\Core\Config\ConfigFactoryInterface
   */
  private $configFactory;

  /**
   * The Module Handler service.
   *
   * @var \Drupal\Core\Extension\ModuleHandlerInterface
   */
  private $moduleHandler;

  /**
   * The Entity Type Manager service.
   *
   * @var \Drupal\Core\Entity\EntityTypeManagerInterface
   */
  private $entityTypeManager;

  /**
   * The Entity Definition Update Manager service.
   *
   * @var \Drupal\Core\Entity\EntityDefinitionUpdateManagerInterface
   */
  private $entityDefinitionUpdateManager;

  /**
   * The logger.
   *
   * @var \Psr\Log\LoggerInterface
   */
  private $logger;

  /**
   * SKUFieldsManager constructor.
   *
   * @param \Drupal\Core\Config\ConfigFactoryInterface $config_factory
   *   The Config Factory service.
   * @param \Drupal\Core\Extension\ModuleHandlerInterface $module_handler
   *   The Module Handler service.
   * @param \Drupal\Core\Entity\EntityTypeManagerInterface $entity_type_manager
   *   The Entity Type Manager service.
   * @param \Drupal\Core\Entity\EntityDefinitionUpdateManagerInterface $entity_definition_update_manager
   *   The Entity Definition Update Manager service.
   * @param \Psr\Log\LoggerInterface $logger
   *   The Logger.
   */
  public function __construct(ConfigFactoryInterface $config_factory,
                              ModuleHandlerInterface $module_handler,
                              EntityTypeManagerInterface $entity_type_manager,
                              EntityDefinitionUpdateManagerInterface $entity_definition_update_manager,
                              LoggerInterface $logger) {
    $this->configFactory = $config_factory;
    $this->moduleHandler = $module_handler;
    $this->entityTypeManager = $entity_type_manager;
    $this->entityDefinitionUpdateManager = $entity_definition_update_manager;
    $this->logger = $logger;
  }

  /**
   * Function to add all new field definitions from custom modules to SKU Base.
   */
  public function addFields() {
    $this->logger->info('addFields() invoked to add newly added base fields to SKU.');
    // Get all the additional fields from all custom modules.
    $fields = $this->getAllCustomFields();

    // Store the fields in config.
    $config = $this->configFactory->getEditable(self::BASE_FIELD_ADDITIONS_CONFIG);
    $existing_fields = $config->getRawData();

    $fields = array_diff_key($fields, $existing_fields);
    $existing_fields = array_merge($existing_fields, $fields);
    $config->setData($existing_fields)->save();

    if ($fields) {
      $this->logger->info('Adding new fields %fields.', [
        '%fields' => json_encode($fields),
      ]);

      // Apply entity updates, we will read from config and add/update fields.
      $this->entityDefinitionUpdateManager->applyUpdates();

      // Allow other modules to take some action after the fields are added.
      $this->moduleHandler->invokeAll('acm_sku_base_fields_updated', [$fields, 'add']);
    }
    else {
      $this->logger->warning('No new fields found to add.');
    }

  }

  /**
   * Remove base field from SKU entity.
   *
   * Note: Calling function needs to take care of clearing data.
   *
   * @param string $field_code
   *   Field code to remove.
   */
  public function removeField($field_code) {
    $config = $this->configFactory->getEditable(self::BASE_FIELD_ADDITIONS_CONFIG);
    $fields = $config->getRawData();

    if (!isset($fields[$field_code])) {
      return;
    }

    $field = $fields[$field_code];
    unset($fields[$field_code]);
    $config->setData($fields)->save();

    $this->entityTypeManager->clearCachedDefinitions();
    $this->entityDefinitionUpdateManager->applyUpdates();

    $fields_removed = [
      $field_code => $field,
    ];

    $this->moduleHandler->invokeAll('acm_sku_base_fields_updated', [$fields_removed, 'remove']);
  }

  /**
   * Function to update field definitions for the additional SKU base fields.
   *
   * This will not update the actual field but only additional information used
   * in custom code like field is configurable or not, indexable or not.
   *
   * It will not do anything except updating the config. Be very careful when
   * using this.
   *
   * @param string $field_code
   *   Field code.
   * @param array $field
   *   Field definition.
   *
   * @throws \Exception
   *   Throws exception if field doesn't exist in config.
   */
  public function updateFieldMetaInfo($field_code, array $field) {
    $config = $this->configFactory->getEditable(self::BASE_FIELD_ADDITIONS_CONFIG);
    $existing_fields = $config->getRawData();

    if (empty($existing_fields[$field_code])) {
      throw new \Exception('Field not available, try adding it first.');
    }

    // Checks to avoid errors.
    $field_structure_info = [
      'type',
      'cardinality',
    ];

    foreach ($field_structure_info as $info) {
      if (isset($field[$info]) && $field['type'] != $existing_fields[$field_code]['type']) {
        throw new \Exception('Can not modify field structure.');
      }
    }

    // Need to apply entity updates for following.
    $apply_updates = FALSE;
    $field_labels_info = [
      'label',
      'description',
      'visible_view',
      'visible_form',
      'weight',
    ];

    foreach ($field_labels_info as $info) {
      if (isset($field[$info]) && $field['type'] != $existing_fields[$field_code]['type']) {
        $apply_updates = TRUE;
        break;
      }
    }

    $existing_fields[$field_code] = array_replace($existing_fields[$field_code], $field);
    $config->setData($existing_fields)->save();

    if ($apply_updates) {
      $this->entityDefinitionUpdateManager->applyUpdates();
    }
  }

  /**
   * Get all existing field additions.
   *
   * @return array
   *   Existing field additions.
   */
  public function getFieldAdditions() {
    return $this->configFactory->get(self::BASE_FIELD_ADDITIONS_CONFIG)->getRawData();
  }

  /**
   * Get all fields defined in custom modules.
   *
   * @return array
   *   All fields defined in custom modules.
   */
  private function getAllCustomFields() {
    $fields = [];

    $this->moduleHandler->alter('acm_sku_base_field_additions', $fields);

    foreach ($fields as $field_code => $field) {
      $fields[$field_code] = $this->applyDefaults($field_code, $field);
    }

    return $fields;
  }

  /**
   * Function to apply defaults and complete field definition.
   *
   * @param string $field_code
   *   Field code.
   * @param array $field
   *   Field definition.
   *
   * @return array
   *   Field definition with all defaults applied.
   */
  private function applyDefaults($field_code, array $field) {
    $defaults = $this->getDefaults();

    if (empty($field['source'])) {
      $field['source'] = $field_code;
    }

    // We will always have label, still we do a check to avoid errors.
    if (empty($field['label'])) {
      $field['label'] = $field_code;
    }

    // Add description if empty.
    if (empty($field['description'])) {
      $field['description'] = str_replace('[label]', $field['label'], $defaults['description']);
    }

    // Merge all other defaults.
    $field += $defaults;

    return $field;
  }

  /**
   * Returns an associative [] containing all required fields with defaults set.
   *
   * @returns array
   *   Associative array containing all required values with defaults set.
   */
  private function getDefaults() {
    return [
      // (Required) Label to be used for admin forms and display.
      'label' => '',
      // Soruce field code to use for reading from product data.
      'source' => '',
      // Description of the field to be used in admin forms.
      'description' => '[label] attribute for the product.',
      // (Required) Parent key in the array where to look for data.
      'parent' => 'attributes',
      // Type of the field.
      'type' => 'attribute',
      // Number of values allowed to be stored.
      'cardinality' => 1,
      // (Optional) Should the data be stored as serialized.
      'serialize' => 0,
      // Whether the field is part of configurable options.
      'configurable' => 0,
      // Default weight of the field in form and display.
      'weight' => NULL,
      // Whether the field should be visible while viewing content.
      'visible_view' => 0,
      // Whether the field should be visible in form.
      'visible_form' => 1,
    ];
  }

}

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

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