external_entities-8.x-2.x-dev/modules/xntt_file_field/xntt_file_field.module
modules/xntt_file_field/xntt_file_field.module
<?php
/**
* @file
* External Entities Files Storage Client module file.
*/
use Drupal\Core\Entity\EntityStorageException;
use Drupal\Core\Form\FormStateInterface;
use Drupal\external_entities\Entity\ConfigurableExternalEntityTypeInterface;
use Drupal\external_entities\Entity\ExternalEntityInterface;
use Drupal\xntt_file_field\Element\ExternalFile;
use Drupal\xntt_file_field\ExternalFileStorageInterface;
use Drupal\xntt_file_field\Plugin\ExternalEntities\FieldMapper\FileFieldMapper;
use Drupal\xntt_file_field\Plugin\Field\FieldType\ExternalFileFieldItemList;
use Drupal\Core\Entity\EntityTypeInterface;
/**
* @file
* External Entitites Files Storage Client plugin for External Entities.
*/
/**
* Implements hook_entity_preload().
*
* This implementation enables the use of external entity identifiers prefixed
* with "xntt-<content type machine name>-<content identifier>-
* <uri drupal field machine name>#<file number>" as file identifiers in order
* to use those external entities as Drupal managed files.
* The matching external entities must return at least a non-empty 'uri' field
* in order to be taken into account.
*/
function xntt_file_field_entity_preload(array $ids, string $entity_type_id) {
$entities = [];
if ('file' === $entity_type_id) {
foreach ($ids as $id) {
if (!is_numeric($id)
&& preg_match(ExternalFileStorageInterface::XNTT_FILE_ID_REGEX, $id)
) {
try {
$external_file_storage = \Drupal::entityTypeManager()
->getStorage('xnttfile');
$entities[$id] = $external_file_storage->loadExternalFile($id);
}
catch (EntityStorageException $e) {
// Failed to load, just ignore.
}
}
}
}
return $entities;
}
/**
* Implements hook_entity_storage_load().
*
* Only update external entity file or image fields that have been mapped.
* Sets the correct external file virtual identifier so it could be loaded later
* on when the system will try to access it through "xntt://" stream.
*/
function xntt_file_field_entity_storage_load(array $entities, $entity_type_id) {
foreach ($entities as $entity) {
// Only work on external entities.
if (!$entity instanceof ExternalEntityInterface) {
continue;
}
// Only work with configurable external entities types.
$xntt_type = $entity->getExternalEntityType();
if (!$xntt_type instanceof ConfigurableExternalEntityTypeInterface) {
continue;
}
// Check if we got a file mapping.
// Get all field types.
$file_fields = array_filter(
$xntt_type->getMappableFields(),
function ($field_definition) {
return in_array($field_definition->getType(), ['file', 'image']);
}
);
foreach ($file_fields as $field_name => $field_definition) {
if (('file' == $xntt_type->getFieldMapperId($field_name))
|| (($field_mapper = $xntt_type->getFieldMapper($field_name))
&& (is_a($field_mapper, FileFieldMapper::class)))
) {
// Mapped using a file field mapper.
$fm_config = $xntt_type->getFieldMapperConfig($field_name);
if (!empty($fm_config['property_mappings']['real_uri'])) {
// Got xntt_file_field mapping, apply it.
$type_id = $xntt_type->getDerivedEntityTypeId();
// Set file field mapping to a special file ID using the format:
// "xntt-xntt_type-xntt_instance_id-file_field_name#delta".
foreach ($entity->$field_name as $i => &$value) {
$fid =
'xntt-'
. $type_id
. '-'
. $entity->id()
. '-'
. $field_name
. '#'
. $i;
$value->set('target_id', $fid);
}
}
}
}
}
}
/**
* Implements hook_field_widget_single_element_form_alter().
*/
function xntt_file_field_field_widget_single_element_form_alter(array &$element, FormStateInterface $form_state, array $context) {
// Only process managed_file field of external entities mapped using the file
// field mapper plugin.
if (($element['#type'] ?? '') === 'managed_file') {
$xntt_type = \Drupal::entityTypeManager()->getStorage('external_entity_type')->load($element['#entity_type'] ?? '-');
if (!empty($xntt_type)
&& !empty($element['#field_name'])
&& $xntt_type instanceof ConfigurableExternalEntityTypeInterface
&& !empty($fm_id = $xntt_type->getFieldMapperId($element['#field_name']))
&& ($fm_id === 'file')
) {
$element['#type'] = 'external_file';
$element['#value_callback'] = [
ExternalFile::class,
"valueCallback",
];
// Add process callback to add real_uri field.
$element['#process'][] = [
ExternalFile::class,
"processExternalFile",
];
}
}
}
/**
* Implements hook_field_info_alter().
*/
function xntt_file_field_field_info_alter(&$info) {
// Replace file field item list class with the external file one to also
// manage external files when needed.
// Also replace file validator to support external files.
if (isset($info['file'])) {
$info['file']['list_class'] = ExternalFileFieldItemList::class;
$info['file']['constraints']['ExternalFileValidation'] = $info['file']['constraints']['FileValidation'];
$info['file']['constraints']['ExternalReferenceAccess'] = $info['file']['constraints']['ReferenceAccess'];
unset($info['file']['constraints']['FileValidation']);
unset($info['file']['constraints']['ReferenceAccess']);
}
if (isset($info['image'])) {
$info['image']['list_class'] = ExternalFileFieldItemList::class;
$info['image']['constraints']['ExternalFileValidation'] = $info['image']['constraints']['FileValidation'];
$info['image']['constraints']['ExternalReferenceAccess'] = $info['image']['constraints']['ReferenceAccess'];
unset($info['image']['constraints']['FileValidation']);
unset($info['image']['constraints']['ReferenceAccess']);
}
}
/**
* Implements hook_entity_field_storage_info_alter().
*/
function xntt_file_field_entity_field_storage_info_alter(&$fields, EntityTypeInterface $entity_type) {
if (is_a($entity_type->getClass(), ExternalEntityInterface::class, TRUE)) {
foreach ($fields as &$field) {
if (in_array($field->getType(), ['file', 'image'])
&& ($field->getSetting('target_type') === 'file')
) {
$field->setSetting('target_type', 'xnttfile');
}
}
}
}
