file_bulkupload_translations-1.0.x-dev/src/Plugin/Field/FieldWidget/FileBulkuploadTranslationsWidget.php

src/Plugin/Field/FieldWidget/FileBulkuploadTranslationsWidget.php
<?php

namespace Drupal\file_bulkupload_translations\Plugin\Field\FieldWidget;

use Drupal\Component\Utility\NestedArray;
use Drupal\Core\Database\Database;
use Drupal\Core\Entity\EntityInterface;
use Drupal\Core\Field\Attribute\FieldWidget;
use Drupal\Core\Field\FieldItemListInterface;
use Drupal\Core\Field\FieldStorageDefinitionInterface;
use Drupal\Core\Form\FormStateInterface;
use Drupal\Core\Language\LanguageManagerInterface;
use Drupal\Core\Render\Element;
use Drupal\Core\Render\ElementInfoManagerInterface;
use Drupal\Core\StringTranslation\TranslatableMarkup;
use Drupal\file\Entity\File;
use Drupal\file\Plugin\Field\FieldWidget\FileWidget;
use Symfony\Component\DependencyInjection\ContainerInterface;

/**
 * Plugin implementation of the 'file_bulkupload_translations_widget' widget.
 */
#[FieldWidget(
  id: 'file_bulkupload_translations_widget',
  label: new TranslatableMarkup('File Bulkupload and Translations'),
  field_types: ['file'],
)]
class FileBulkuploadTranslationsWidget extends FileWidget {

  /**
   * The language manager service.
   *
   * @var \Drupal\Core\Language\LanguageManagerInterface
   */
  protected $languageManager;

  /**
   * The original cardinality of the widget before our changes.
   *
   * @var int
   */
  protected $originalCardinality;

  /**
   * Constructs a FileAndTranslationsWidget object.
   *
   * @param string $plugin_id
   *   The plugin_id for the widget.
   * @param mixed $plugin_definition
   *   The plugin implementation definition.
   * @param \Drupal\Core\Field\FieldDefinitionInterface $field_definition
   *   The field definition.
   * @param array $settings
   *   The settings for the widget.
   * @param array $third_party_settings
   *   Third party settings.
   * @param \Drupal\Core\Language\LanguageManagerInterface $language_manager
   *   The language manager service.
   * @param \Drupal\Core\Render\ElementInfoManagerInterface $element_info
   *   The element info manager service.
   */
  public function __construct($plugin_id, $plugin_definition, $field_definition, array $settings, array $third_party_settings, LanguageManagerInterface $language_manager, ElementInfoManagerInterface $element_info) {
    parent::__construct($plugin_id, $plugin_definition, $field_definition, $settings, $third_party_settings, $element_info);

    // Inject the service language_manager.
    $this->languageManager = $language_manager;
    // Backup the original cardinality.
    $this->originalCardinality = $field_definition->getFieldStorageDefinition()->getCardinality();
  }

  /**
   * {@inheritdoc}
   */
  public static function create(ContainerInterface $container, array $configuration, $plugin_id, $plugin_definition) {
    return new static(
      $plugin_id,
      $plugin_definition,
      $configuration['field_definition'],
      $configuration['settings'],
      $configuration['third_party_settings'],
      $container->get('language_manager'),
      $container->get('element_info')
    );
  }

  /**
   * {@inheritdoc}
   */
  public function formElement(FieldItemListInterface $items, $delta, array $element, array &$form, FormStateInterface $form_state) {
    $element = parent::formElement($items, $delta, $element, $form, $form_state);

    // Allow multiple upload.
//    $element['#multiple'] = TRUE;
//    $element['#cardinality'] = -1;
//    kint($form);
//    kint($cardinality = $this->getFieldDefinition()->getFieldStorageDefinition()->getCardinality());
    if (empty($element['#default_value']['fids'])) {
      // Target only "Add a new file" element.
      // Add custom validator.
      $element['#upload_validators']['UniqueLanguage'] = [];
      // $element['#upload_validators']['EnabledLanguage'] = [];
    }
    else {
      // Already uploaded files elements.
    }
    return $element;
  }

  public static function processMultiple($element, FormStateInterface $form_state, $form) {
    $element = parent::processMultiple($element, $form_state, $form);
    return $element;
//    ddl(__FUNCTION__);
//    ddl($element);
    $element_children = Element::children($element, TRUE);
    $count = count($element_children);

    // Récupérer l'entité courante.
    $entity = $form_state->getFormObject()->getEntity();
    if (!$entity) {
      return $element;
    }

    // Récupérer les traductions de fichiers.
//    $file_translations = static::getFileTranslations($entity);
    // Exemple de données de traduction de fichiers.
    // Langcode as key and fid as value.
    $file_translations = [
      'bg' => 17297,
    ];

    // Ajouter des champs cachés pour stocker les relations parent-enfant.
    foreach ($element_children as $delta => $key) {
      $element[$key]['parent'] = [
        '#type' => 'hidden',
        '#default_value' => isset($element[$key]['#default_value']['parent']) ? $element[$key]['#default_value']['parent'] : '',
      ];
    }

    // Ajouter des éléments draggable pour permettre la réorganisation.
    foreach ($element_children as $delta => $key) {
      $element[$key]['#attributes']['class'][] = 'draggable';
      $element[$key]['_weight'] = [
        '#type' => 'weight',
        '#title' => t('Weight for @title', ['@title' => $element[$key]['#title']]),
        '#title_display' => 'invisible',
        '#delta' => $count,
        '#default_value' => $delta,
      ];

      // Ajouter un champ pour afficher la relation parent-enfant.
      $element[$key]['parent_display'] = [
        '#type' => 'markup',
        '#markup' => isset($element[$key]['#default_value']['parent']) ? t('Parent: @parent', ['@parent' => $element[$key]['#default_value']['parent']]) : t('No parent'),
      ];

      // Ajouter les traductions comme enfants.
      $current_langcode = $entity->language()->getId();
      foreach ($file_translations as $field_name => $translations) {
        foreach ($translations as $langcode => $file) {
          if ($langcode != $current_langcode) {
            $element[$key]['translations'][$langcode] = [
              '#type' => 'markup',
              '#markup' => t('Translation: @filename', ['@filename' => $file->getFilename()]),
              '#attributes' => ['class' => ['translation']],
            ];
          }
        }
      }
    }

    // Ajouter un nouveau wrapper autour de tous les éléments pour le remplacement Ajax.
    $element['#prefix'] = '<div id="' . $element['#id'] . '-ajax-wrapper">';
    $element['#suffix'] = '</div>';

    return $element;
  }

   /**
   * @inheritDoc
   */
  public static function submit($form, FormStateInterface $form_state) {
//    Database::getConnection()->delete('devel_debug_log')
//      ->execute();
    parent::submit($form, $form_state);
    // Retrieve the entity from form state.
    $entity = $form_state->getFormObject()->getEntity();

    if (!$entity) {
      return;
    }

    $button = $form_state->getTriggeringElement();

    // Go one level up in the form, to the widgets container.
    $element = NestedArray::getValue($form, array_slice($button['#array_parents'], 0, -1));
    $field_name = $element['#field_name'];

    // Process each uploaded file.

    // If there are more files uploaded via the same widget, we have to separate
    // them, as we display each file in its own widget.
    $submitted_values = NestedArray::getValue($form_state->getValues(), array_slice($button['#parents'], 0, -2));

    // Update form_state values.
    NestedArray::setValue($form_state->getValues(), array_slice($button['#parents'], 0, -2), $submitted_values);
    // Bulkupload : Update translations.
    foreach ($submitted_values as $key => $submitted_value) {
      if($submitted_value['display']){
        // Already existing file.
        unset($submitted_values[$key]);
        continue;
      }
      $fid = array_shift($submitted_value['fids']);

//      ddl('Bulkupload for Media#' . $entity->id() . ' via Field#' . $field_name . ' with value ' . $fid);
      if ($fid) {
        static::createOrEditTranslations($entity, $field_name, $fid);
        // Remove $fid from entity's files.
        $form_state->setValue($field_name, array_diff($form_state->getValue($field_name, []), [$fid]));
//        $entity->set($field_name, array_diff($entity->get($field_name), [$fid]))->save();
      }
    }

    // Update items.
//    $parents = array_slice($button['#parents'], 0, -2);
//    $field_state = static::getWidgetState($parents, $field_name, $form_state);
//    $field_state['items'] = $submitted_values;
//    static::setWidgetState($parents, $field_name, $form_state, $field_state);
  }

  /**
   * Create media translation entities.
   */
  protected static function createOrEditTranslations( EntityInterface $entity, string $field_name, int $fid): bool {
    $file = File::load($fid);
    $langcode = static::getLanguageFromRegexFilename($file->getFilename());
    // ddl('Langcode: ' . $langcode);
    if($langcode != $file->get('langcode')->value && !$entity->hasTranslation($langcode)){
      // Set File language according $langcode.
      $file->set('langcode', $langcode)->save();

      /** @var \Drupal\Core\Entity\ContentEntityInterface $translation */
      $translation = $entity->addTranslation($langcode);
      // ddl('Translation created for ' . $langcode . ' with fid ' . $fid . ' for Media#' . $entity->id());

      return $translation
        ->set($field_name, [
          'target_id' => $fid,
        ])->save();
      // ddl('Translation '. $translation->id() .  'updated with fid ' . $fid . ' for field ' . $field_name);
    }
    return FALSE;
  }

  /**
   * Get the language suffix from the name of the given file.
   */
  protected static function getLanguageFromRegexFilename(string $filename): string {
    $config = \Drupal::config('file_bulkupload_translations.settings');
    $regex = $config->get('regex') ?? '/(?:[-_])([a-zA-Z]{2})(?=_\d+\.|[.-][a-zA-Z]+$)/i';
    if (preg_match($regex, str_replace(' ', '', $filename), $match)) {
      return mb_strtolower($match[1]);
    }
    // Drupal service languagemanager in static function.
    return \Drupal::service('language_manager')->getDefaultLanguage()->getId();
  }

  /**
   * Determine the number of widgets to display.
   *
   * @param \Drupal\Core\Form\FormStateInterface $form_state
   *   The form_state.
   *
   * @return int
   *   Number of widgets to display.
   */
  protected function getFieldCardinality(FormStateInterface $form_state) {
    /** @var \Drupal\media\Entity\Media $entity */
    $entity = $form_state->getFormObject()->getEntity();

    $entityLanguage = $entity->language()->getId();
    $defaultLanguage = $this->languageManager->getDefaultLanguage()->getId();
    //    kint($entityLanguage, $defaultLanguage, $entityLanguage !== $defaultLanguage ? 1 : FieldStorageDefinitionInterface::CARDINALITY_UNLIMITED);
    if ($entityLanguage !== $defaultLanguage) {
      return 1;
    }

    return FieldStorageDefinitionInterface::CARDINALITY_UNLIMITED;
  }

  /**
   * Custom helper to get the file translations.
   */
  protected function getFileTranslations($entity) {
    // Get the referenced entities from the custom field.
    $file_translations = [];
    $fields = $this->getFileAndTranslationFields($entity);
    foreach ($fields as $field) {
      foreach ($field->referencedEntities() as $file) {
        $filename = mb_strtolower($file->getFilename($file));
        $language_suffix = $this->getLanguageSuffix($filename);
        $languageCodes = $this->getLanguageCodes();
        if (in_array($language_suffix, $languageCodes, TRUE)) {
          $langcode = array_search($language_suffix, $languageCodes, TRUE);
          $file_translations[$field->getName()][$langcode] = $file;
        }
      }
    }

    return $file_translations;
  }
}

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

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