commit
c1cd174af3
9 changed files with 335 additions and 0 deletions
@ -0,0 +1,19 @@
|
||||
## INTRODUCTION |
||||
|
||||
The Islandora Inplace Media module allows ussers ti create and attach media from files staged on the server. |
||||
|
||||
## INSTALLATION |
||||
|
||||
Install as you would normally install a contributed Drupal module. |
||||
See: https://www.drupal.org/node/895232 for further information. |
||||
|
||||
## USAGE |
||||
Navigate to islandora-inplace-media/create-media-from-file and fill in the form. |
||||
|
||||
|
||||
## MAINTAINERS |
||||
|
||||
Current maintainers for Drupal 10: |
||||
|
||||
- Robertson Library UPEI |
||||
|
@ -0,0 +1,13 @@
|
||||
/* Use Flexbox to align form fields side by side */ |
||||
.media-fields-wrapper { |
||||
display: flex; |
||||
gap: 20px; /* Space between elements */ |
||||
align-items: center; |
||||
} |
||||
|
||||
/* Ensure each field takes up equal space */ |
||||
.media-side-by-side { |
||||
flex: 1; |
||||
min-width: 200px; /* Prevents elements from getting too small */ |
||||
} |
||||
|
@ -0,0 +1,7 @@
|
||||
name: 'Islandora Inplace Media' |
||||
type: module |
||||
description: 'Allows Uploaded files to be attched to exisitng nodes as media' |
||||
package: Custom |
||||
core_version_requirement: ^10 || ^11 |
||||
dependencies: |
||||
- islandora:islandora |
@ -0,0 +1,5 @@
|
||||
form_styles: |
||||
version: 1.x |
||||
css: |
||||
theme: |
||||
css/form-styles.css: {} |
@ -0,0 +1,6 @@
|
||||
<?php |
||||
|
||||
/** |
||||
* @file |
||||
* Primary module hooks for Islandora Inplace Media module. |
||||
*/ |
@ -0,0 +1,7 @@
|
||||
islandora_inplace_media.create_media_from_file: |
||||
path: '/islandora-inplace-media/create-media-from-file' |
||||
defaults: |
||||
_title: 'Create Media From File' |
||||
_form: 'Drupal\islandora_inplace_media\Form\CreateMediaFromFileForm' |
||||
requirements: |
||||
_permission: 'access content' |
@ -0,0 +1,4 @@
|
||||
services: |
||||
islandora_inplace_media.utils: |
||||
class: Drupal\islandora_inplace_media\Utils |
||||
arguments: ['@entity_type.manager', '@file_system', '@logger.factory', '@entity_field.manager'] |
@ -0,0 +1,154 @@
|
||||
<?php |
||||
|
||||
declare(strict_types=1); |
||||
|
||||
namespace Drupal\islandora_inplace_media\Form; |
||||
|
||||
use Drupal\Core\Form\FormBase; |
||||
use Drupal\Core\Form\FormStateInterface; |
||||
use Drupal\islandora_inplace_media\Utils; |
||||
use Drupal\Core\Entity\EntityTypeManagerInterface; |
||||
use Symfony\Component\DependencyInjection\ContainerInterface; |
||||
|
||||
/** |
||||
* Provides an Islandora Inplace Media form. |
||||
*/ |
||||
final class CreateMediaFromFileForm extends FormBase { |
||||
|
||||
/** |
||||
* The Inplace Media Utils service. |
||||
* |
||||
* @var \Drupal\islandora_inplace_media\Utils |
||||
*/ |
||||
protected Utils $mediaUtils; |
||||
|
||||
/** |
||||
* The entity type manager service. |
||||
* |
||||
* @var \Drupal\Core\Entity\EntityTypeManagerInterface |
||||
*/ |
||||
protected $entityTypeManager; |
||||
|
||||
/** |
||||
* {@inheritdoc} |
||||
*/ |
||||
public function __construct(Utils $mediaUtils, EntityTypeManagerInterface $entityTypeManager) { |
||||
$this->mediaUtils = $mediaUtils; |
||||
$this->entityTypeManager = $entityTypeManager; |
||||
} |
||||
|
||||
/** |
||||
* {@inheritdoc} |
||||
*/ |
||||
public static function create(ContainerInterface $container): self { |
||||
return new self( |
||||
$container->get('islandora_inplace_media.utils'), |
||||
$container->get('entity_type.manager') |
||||
); |
||||
} |
||||
|
||||
/** |
||||
* {@inheritdoc} |
||||
*/ |
||||
public function getFormId(): string { |
||||
return 'islandora_inplace_media_create_media_from_file'; |
||||
} |
||||
|
||||
/** |
||||
* {@inheritdoc} |
||||
*/ |
||||
public function buildForm(array $form, FormStateInterface $form_state): array { |
||||
$vid = 'islandora_media_use'; |
||||
$terms = $this->entityTypeManager->getStorage('taxonomy_term')->loadTree($vid); |
||||
$media_use_options = []; |
||||
$term_default = ''; |
||||
foreach ($terms as $term) { |
||||
$media_use_options[$term->tid] = $term->name; |
||||
if ($term->name == 'Original File') { |
||||
$term_default = $term->tid; |
||||
} |
||||
} |
||||
|
||||
$media_types = $this->entityTypeManager->getStorage('media_type')->loadMultiple(); |
||||
$types = array_map(fn($media_type) => $media_type->label(), $media_types); |
||||
$form['source'] = [ |
||||
'#type' => 'textfield', |
||||
'#title' => $this->t('Enter full file path to input directory'), |
||||
'#required' => TRUE, |
||||
]; |
||||
$form['directory'] = [ |
||||
'#type' => 'textfield', |
||||
'#title' => $this->t('Enter the destination directory'), |
||||
'#required' => TRUE, |
||||
]; |
||||
$form['destination'] = [ |
||||
'#type' => 'radios', |
||||
'#options' => [ |
||||
'public' => $this->t('Public'), |
||||
'private' => $this->t('Private'), |
||||
], |
||||
'#title' => $this->t('Select file system'), |
||||
'#required' => TRUE, |
||||
'#default_value' => 'public', |
||||
]; |
||||
$form['field_wrapper'] = [ |
||||
'#type' => 'container', |
||||
'#attributes' => ['class' => ['media-fields-wrapper']], |
||||
]; |
||||
$form['field_wrapper']['media_type'] = [ |
||||
'#title' => $this->t("Media type."), |
||||
'#type' => 'select', |
||||
'#options' => $types, |
||||
'#attributes' => ['class' => ['media-side-by-side']], |
||||
]; |
||||
$form['field_wrapper']['media_use'] = [ |
||||
'#title' => $this->t("Media use."), |
||||
'#type' => 'select', |
||||
'#options' => $media_use_options, |
||||
'#default_value' => $term_default, |
||||
'#attributes' => ['class' => ['media-side-by-side']], |
||||
]; |
||||
|
||||
$form['actions'] = [ |
||||
'#type' => 'actions', |
||||
'submit' => [ |
||||
'#type' => 'submit', |
||||
'#value' => $this->t('Send'), |
||||
], |
||||
]; |
||||
$form['#attached']['library'][] = 'islandora_inplace_media/form_styles'; |
||||
|
||||
return $form; |
||||
} |
||||
|
||||
/** |
||||
* {@inheritdoc} |
||||
*/ |
||||
public function validateForm(array &$form, FormStateInterface $form_state): void { |
||||
$source_path = $form_state->getValue('source'); |
||||
|
||||
if (!is_dir($source_path)) { |
||||
$form_state->setErrorByName('source', $this->t('The specified directory does not exist.')); |
||||
} |
||||
} |
||||
|
||||
/** |
||||
* {@inheritdoc} |
||||
*/ |
||||
public function submitForm(array &$form, FormStateInterface $form_state): void { |
||||
$source_path = $form_state->getValue('source'); |
||||
$directory = trim($form_state->getValue('directory'), '/'); |
||||
$file_system = $form_state->getValue('destination') === 'public' ? 'public://' : 'private://'; |
||||
$destination = "{$file_system}{$directory}"; |
||||
$media_type = $form_state->getValue('media_type'); |
||||
$media_use = $form_state->getValue('media_use'); |
||||
$results = $this->mediaUtils->buildMedia($source_path, $destination, $media_type, $media_use); |
||||
$this->messenger()->addStatus($this->t('Media files have been processed from %source to %destination.', [ |
||||
'%source' => $source_path, |
||||
'%destination' => $destination, |
||||
])); |
||||
|
||||
$form_state->setRedirect('<front>'); |
||||
} |
||||
|
||||
} |
@ -0,0 +1,120 @@
|
||||
<?php |
||||
|
||||
declare(strict_types=1); |
||||
|
||||
namespace Drupal\islandora_inplace_media; |
||||
|
||||
use Drupal\Core\Entity\EntityTypeManagerInterface; |
||||
use Drupal\Core\File\FileSystemInterface; |
||||
use Drupal\Core\Logger\LoggerChannelFactoryInterface; |
||||
use Drupal\Core\Entity\EntityFieldManagerInterface; |
||||
use Drupal\file\Entity\File; |
||||
use Drupal\media\Entity\Media; |
||||
use Drupal\media\Entity\MediaType; |
||||
|
||||
/** |
||||
* Utility class for managing media file operations in Islandora. |
||||
*/ |
||||
final class Utils { |
||||
|
||||
/** |
||||
* Constructs a Utils object. |
||||
*/ |
||||
public function __construct( |
||||
private readonly EntityTypeManagerInterface $entityTypeManager, |
||||
private readonly FileSystemInterface $fileSystem, |
||||
private readonly LoggerChannelFactoryInterface $loggerFactory, |
||||
private readonly EntityFieldManagerInterface $entityFieldManager, |
||||
) {} |
||||
|
||||
/** |
||||
* Moves files from staging to a managed folder and creates media entities. |
||||
* |
||||
* @param string $dir |
||||
* The source directory containing files. |
||||
* @param string $dest |
||||
* The destination directory (e.g., 'public://media' or 'private://media'). |
||||
* @param string $media_type |
||||
* The media type to be created. |
||||
* @param string $media_use_tid |
||||
* The terms id for new media. |
||||
*/ |
||||
public function buildMedia(string $dir, string $dest, string $media_type, string $media_use_tid): array { |
||||
$results = []; |
||||
if (!is_dir($dir)) { |
||||
$this->loggerFactory->get('islandora_inplace_media')->error('Source directory does not exist: @dir', ['@dir' => $dir]); |
||||
return $results; |
||||
} |
||||
$default_file_field = $this->getDefaultFileField($media_type); |
||||
$this->fileSystem->prepareDirectory($dest, FileSystemInterface::CREATE_DIRECTORY); |
||||
|
||||
$files = scandir($dir); |
||||
$files = array_diff($files, ['.', '..']); |
||||
|
||||
foreach ($files as $file_name) { |
||||
$source_path = $dir . '/' . $file_name; |
||||
$destination_path = $dest . '/' . $file_name; |
||||
|
||||
$moved_file = $this->fileSystem->move($source_path, $destination_path, FileSystemInterface::EXISTS_RENAME); |
||||
$new_file = File::create([ |
||||
'uri' => $moved_file, |
||||
'status' => 1, |
||||
]); |
||||
$new_file->save(); |
||||
$results[$new_file->id()] = $moved_file; |
||||
if (preg_match('/n(\d+)_/', $file_name, $matches)) { |
||||
$nid = $matches[1] ?? NULL; |
||||
} |
||||
unlink($source_path); |
||||
if ($nid) { |
||||
$media = Media::create([ |
||||
"bundle" => $media_type, |
||||
"name" => $file_name, |
||||
$default_file_field => [ |
||||
"target_id" => $new_file->id(), |
||||
], |
||||
'field_media_use' => [ |
||||
"target_id" => $media_use_tid, |
||||
], |
||||
"field_media_of" => $nid, |
||||
]); |
||||
$media->save(); |
||||
} |
||||
} |
||||
return $results; |
||||
} |
||||
|
||||
/** |
||||
* Get the default file field from a media type. |
||||
* |
||||
* @param string $media_type_id |
||||
* The media type ID. |
||||
* |
||||
* @return string|null |
||||
* The field name of the default file field, or NULL if none is found. |
||||
*/ |
||||
public function getDefaultFileField(string $media_type_id): ?string { |
||||
// Load the media type. |
||||
$media_type = MediaType::load($media_type_id); |
||||
if (!$media_type) { |
||||
$this->loggerFactory->get('islandora_inplace_media')->error('Media type @type not found.', ['@type' => $media_type_id]); |
||||
return NULL; |
||||
} |
||||
|
||||
// Get all field definitions for the media entity type. |
||||
$field_definitions = $this->entityFieldManager->getFieldDefinitions('media', $media_type_id); |
||||
|
||||
// Look for the first file-based field (file or image). |
||||
foreach ($field_definitions as $field_name => $field_definition) { |
||||
$storage_type = $field_definition->getType(); |
||||
if (in_array($storage_type, ['file', 'image'])) { |
||||
if ($field_name != 'thumbnail') { |
||||
return $field_name; |
||||
} |
||||
} |
||||
} |
||||
|
||||
return NULL; |
||||
} |
||||
|
||||
} |
Loading…
Reference in new issue