Why Gemfury? Push, build, and install  RubyGems npm packages Python packages Maven artifacts PHP packages Go Modules Debian packages RPM packages NuGet packages

Repository URL to install this package:

Details    
novicell/dds / src / Commands / DDSCommands.php
Size: Mime:
<?php

namespace Drupal\dds\Commands;

use Consolidation\OutputFormatters\StructuredData\RowsOfFields;
use Drupal\Core\Entity\EntityFieldManager;
use Drupal\field\Entity\FieldConfig;
use Drush\Commands\DrushCommands;
use Drush\Exceptions\UserAbortException;

/**
 * A Drush commandfile.
 *
 * In addition to this file, you need a drush.services.yml
 * in root of your module, and a composer.json file that provides the name
 * of the services file to use.
 *
 * See these files for an example of injecting Drupal services:
 *   - http://cgit.drupalcode.org/devel/tree/src/Commands/DevelCommands.php
 *   - http://cgit.drupalcode.org/devel/tree/drush.services.yml
 */
class DDSCommands extends DrushCommands {

  /** @var \Drupal\Core\Entity\EntityFieldManager */
  protected $entityFieldManager;

  public function __construct(EntityFieldManager $entity_field_manager) {
    parent::__construct();
    $this->entityFieldManager = $entity_field_manager;
  }

  /**
   * Rebuilds the bundle field maps inside the key value store.
   *
   * @param $type
   *   The entity type to rebuild field maps for.
   * @param array $options
   *   An associative array of options whose values come from cli, aliases,
   *   config, etc.
   * @return \Consolidation\OutputFormatters\StructuredData\RowsOfFields|void
   * @throws \Drush\Exceptions\UserAbortException
   *
   * @command rebuild:field-map
   * @option force Force rebuilding even if no additions or removals were
   *   detected.
   * @usage drush rebuild:field-map node --force
   *   Rebuild the field mappings for nodes and ignore if no changes were
   *   detected.
   * @usage drush rebuild:field-map paragraph
   *   Rebuild the field mappings for paragraphs
   * @aliases rfm,rebuild-field-map
   * @table-style default
   * @field-labels
   *   field: Field
   *   bundle: Bundle
   *   change: Change
   */
  public function rebuildFieldMap($type, array $options = ['force' => FALSE, 'format' => 'table']) {
    /** @var \Drupal\Core\KeyValueStore\KeyValueStoreInterface $bundle_key_value */
    $bundle_key_value = \Drupal::service('keyvalue')->get('entity.definitions.bundle_field_map');

    $existing_mappings = $bundle_key_value->get($type);
    $new_mappings = $this->getBundleMapByEntityType($type);

    $added_mappings = array_diff_key($new_mappings, $existing_mappings);
    $removed_mappings = array_diff_key($existing_mappings, $new_mappings);
    $has_changes = !empty($added_mappings) || !empty($removed_mappings);

    if ($has_changes) {
      $this->output()->writeln(dt('Rebuilding stored field mapping values for @entity_type.', ['@entity_type' => $type]));
      $rows = [];

      // Add added mappings to the resulting rows.
      foreach ($added_mappings as $field => $mappings) {
        foreach ($mappings as $bundle) {
          $rows[] = [
            'field' => $field,
            'bundle' => $bundle,
            'change' => dt('Add')
          ];
        }
      }

      // Add removed mappings to the resulting rows.
      foreach ($removed_mappings as $field => $mappings) {
        foreach ($mappings as $bundle) {
          $rows[] = [
            'field' => $field,
            'bundle' => $bundle,
            'change' => dt('Remove')
          ];
        }
      }

      return new RowsOfFields($rows);
    } else {
      if ($options['force'] != TRUE) {
        $this->output()->writeln(dt('There are no changes to be made. The stored field mappings matches the generated ones.'));
      }
    }

    if ($has_changes || $options['force'] == TRUE) {
      $bundle_key_value->set($type, $new_mappings);
      drupal_flush_all_caches();
      $this->output()->writeln(dt('The field mappings for @entity_type has been rebuilt.', ['@entity_type' => $type]));
    }
  }

  /**
   * Gets the field mappings for the given entity type.
   *
   * @param string $type
   *   The type of the entity to generate field mappings for.
   *
   * @return array
   *   An array of field mappings ready to store in the key value store.
   */
  private function getBundleMapByEntityType($type) {
    $bundle_field_map = [];

    /** @var array $bundle_info */
    $bundle_info = \Drupal::service('entity_type.bundle.info')->getBundleInfo($type);

    foreach ($bundle_info as $bundle => $info) {
      $definitions = $this->entityFieldManager->getFieldDefinitions($type, $bundle);

      // If there are no definitions, we skip this loop and continue to the next.
      if (empty($definitions)) {
        continue;
      }

      // Filter out the definitions that are not of the target type.
      $definitions = array_filter($definitions, function($definition) {
        return $definition instanceof FieldConfig;
      });

      if (!empty($definitions)) {
        foreach ($definitions as $field_definition) {
          $field_bundle = $field_definition->getTargetBundle();
          $field_name = $field_definition->getName();

          if (!isset($bundle_field_map[$field_name])) {
            // If the field doesn't exist yet we initialize it with type and empty bundle list.
            $bundle_field_map[$field_name] = [
              'type' => $field_definition->getType(),
              'bundles' => []
            ];
          }

          $bundle_field_map[$field_name]['bundles'][$field_bundle] = $field_bundle;
        }
      }
    }

    return $bundle_field_map;
  }

}