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;
}
}
