Browse Source

Upload form

pull/754/head
dannylamb 6 years ago
parent
commit
bfd7b4facf
  1. 12
      config/schema/islandora.schema.yml
  2. 10
      islandora.links.action.yml
  3. 23
      islandora.routing.yml
  4. 179
      src/Form/AddChildrenForm.php
  5. 246
      src/Form/AddMediaForm.php
  6. 38
      src/Form/IslandoraSettingsForm.php
  7. 27
      src/IslandoraUtils.php

12
config/schema/islandora.schema.yml

@ -14,6 +14,18 @@ islandora.settings:
jwt_expiry:
type: string
label: 'How long JWTs should last before expiring.'
upload_form_bundle:
type: string
label: 'Upload Form Content Type'
upload_form_location:
type: string
label: 'Upload Form Location'
upload_form_term:
type: string
label: 'Upload Form Media Use Term'
upload_form_allowed_extensions:
type: string
label: 'Upload Form Allowed Extensions'
gemini_url:
type: uri
label: 'Url to Gemini microservice'

10
islandora.links.action.yml

@ -1,12 +1,12 @@
islandora.add_media_to_node:
route_name: islandora.add_media_to_node_page
title: Add media
route_name: islandora.add_media_form
title: Add Media
appears_on:
- view.media_of.page_1
islandora.add_member_to_node:
route_name: islandora.add_member_to_node_page
title: Add child
islandora.add_children_to_node:
route_name: islandora.add_children_form
title: Add Children
appears_on:
- view.manage_members.page_1

23
islandora.routing.yml

@ -16,27 +16,24 @@ system.islandora_settings:
requirements:
_permission: 'administer site configuration'
islandora.add_member_to_node_page:
islandora.add_children_form:
path: '/node/{node}/members/add'
defaults:
_controller: '\Drupal\islandora\Controller\ManageMembersController::addToNodePage'
_title_callback: '\Drupal\islandora\Controller\ManageMembersController::addTitle'
entity_type_id: node
_form: '\Drupal\islandora\Form\AddChildrenForm'
_title: 'Add children'
options:
_admin_route: 'true'
_admin_route: 'TRUE'
requirements:
_entity_create_any_access: 'node'
_permssion: 'create node,create media'
islandora.add_media_to_node_page:
islandora.add_media_form:
path: '/node/{node}/media/add'
defaults:
_controller: '\Drupal\islandora\Controller\ManageMediaController::addToNodePage'
_title_callback: '\Drupal\islandora\Controller\ManageMediaController::addTitle'
entity_type_id: media
_form: '\Drupal\islandora\Form\AddMediaForm'
_title: 'Add media'
options:
_admin_route: 'true'
_admin_route: 'TRUE'
requirements:
_entity_create_any_access: 'media'
_permssion: 'create media'
islandora.media_source_update:
path: '/media/{media}/source'

179
src/Form/AddChildrenForm.php

@ -0,0 +1,179 @@
<?php
namespace Drupal\islandora\Form;
use Drupal\Core\Form\FormStateInterface;
use Drupal\Core\Url;
use Drupal\islandora\IslandoraUtils;
use Symfony\Component\HttpFoundation\RedirectResponse;
use Symfony\Component\HttpKernel\Exception\HttpException;
use Drupal\Core\Utility\Token;
/**
* Form that lets users upload one or more files as children to a resource node.
*/
class AddChildrenForm extends AddMediaForm {
/**
* {@inheritdoc}
*/
public function getFormId() {
return 'add_children_form';
}
/**
* {@inheritdoc}
*/
public function buildForm(array $form, FormStateInterface $form_state) {
$upload_pattern = $this->config->get(IslandoraSettingsForm::UPLOAD_FORM_LOCATION);
$upload_location = $this->token->replace($upload_pattern);
$valid_extensions = $this->config->get(IslandoraSettingsForm::UPLOAD_FORM_ALLOWED_MIMETYPES);
$this->parentId = $this->routeMatch->getParameter('node');
$parent = $this->entityTypeManager->getStorage('node')->load($this->parentId);
$form['upload'] = [
'#type' => 'managed_file',
'#title' => $this->t('Files'),
'#description' => $this->t("Upload one or more files to add children to @title", ['@title' => $parent->getTitle()]),
'#upload_location' => $upload_location,
'#upload_validators' => [
'file_validate_extensions' => [$valid_extensions],
],
'#multiple' => TRUE,
];
$form['submit'] = [
'#type' => 'submit',
'#value' => $this->t('Submit'),
];
return $form;
}
/**
* {@inheritdoc}
*/
public function submitForm(array &$form, FormStateInterface $form_state) {
$parent_id = $this->routeMatch->getParameter('node');
$parent = $this->entityTypeManager->getStorage('node')->load($parent_id);
$fids = $form_state->getValue('upload');
$operations = [];
foreach ($fids as $fid) {
$operations[] = [[$this, 'buildNodeForFile'], [$fid, $parent_id]];
}
$batch = [
'title' => $this->t("Uploading Children for @title", ['@title' => $parent->getTitle()]),
'operations' => $operations,
'progress_message' => t('Processed @current out of @total. Estimated time: @estimate.'),
'error_message' => t('The process has encountered an error.'),
'finished' => [$this, 'buildNodeFinished'],
];
batch_set($batch);
}
/**
* Wires up a file/media/node combo for a file upload.
*
* @param int $fid
* Uploaded file id.
* @param int $parent_id
* Id of the parent node.
* @param array $context
* Batch context.
*
* @throws \Symfony\Component\HttpKernel\Exception\HttpException
*/
public function buildNodeForFile($fid, $parent_id, array &$context) {
// Since we make 3 different entities, do this in a transaction.
$transaction = $this->database->startTransaction();
try {
$file = $this->entityTypeManager->getStorage('file')->load($fid);
$file->setPermanent();
$file->save();
$parent = $this->entityTypeManager->getStorage('node')->load($parent_id);
$mime = $file->getMimetype();
$exploded_mime = explode('/', $mime);
if ($exploded_mime[0] == 'image') {
if (in_array($exploded_mime[1], ['tiff', 'jp2'])) {
$media_type = 'file';
}
else {
$media_type = 'image';
}
$model = $this->utils->getTermForUri('http://purl.org/coar/resource_type/c_c513');
}
elseif ($exploded_mime[0] == 'audio') {
$media_type = 'audio';
$model = $this->utils->getTermForUri('http://purl.org/coar/resource_type/c_18cc');
}
elseif ($exploded_mime[0] == 'video') {
$media_type = 'video';
$model = $this->utils->getTermForUri('http://purl.org/coar/resource_type/c_12ce');
}
else {
$media_type = 'file';
if ($mime == 'application/pdf') {
$model = $this->utils->getTermForUri('https://schema.org/DigitalDocument');
}
else {
$model = $this->utils->getTermForUri('http://purl.org/coar/resource_type/c_1843');
}
}
$source_field = $this->mediaSource->getSourceFieldName($media_type);
$node = $this->entityTypeManager->getStorage('node')->create([
'type' => $this->config->get(IslandoraSettingsForm::UPLOAD_FORM_BUNDLE),
'title' => $file->getFileName(),
IslandoraUtils::MODEL_FIELD => $model,
IslandoraUtils::MEMBER_OF_FIELD => $parent,
'uid' => $this->account->id(),
'status' => 1,
]);
$node->save();
$uri = $this->config->get(IslandoraSettingsForm::UPLOAD_FORM_TERM);
$term = $this->utils->getTermForUri($uri);
$media = $this->entityTypeManager->getStorage('media')->create([
'bundle' => $media_type,
$source_field => $fid,
'name' => $file->getFileName(),
IslandoraUtils::MEDIA_USAGE_FIELD => $term,
IslandoraUtils::MEDIA_OF_FIELD => $node,
]);
$media->save();
}
catch (HttpException $e) {
$transaction->rollBack();
throw $e;
}
catch (\Exception $e) {
$transaction->rollBack();
throw new HttpException(500, $e->getMessage());
}
}
/**
* Batch finished callback.
*
* $success bool
* Success status
* $results mixed
* The 'results' from the batch context.
* $operations array
* Remaining operations.
*/
public function buildNodeFinished($success, $results, $operations) {
return new RedirectResponse(
Url::fromRoute('view.manage_members.page_1', ['node' => $this->parentId])->toString()
);
}
}

246
src/Form/AddMediaForm.php

@ -0,0 +1,246 @@
<?php
namespace Drupal\islandora\Form;
use Drupal\Core\Config\ImmutableConfig;
use Drupal\Core\Database\Connection;
use Drupal\Core\Form\FormBase;
use Drupal\Core\Form\FormStateInterface;
use Drupal\Core\Entity\EntityTypeManagerInterface;
use Drupal\Core\Session\AccountInterface;
use Drupal\islandora\IslandoraUtils;
use Drupal\islandora\MediaSource\MediaSourceService;
use Symfony\Component\DependencyInjection\ContainerInterface;
use Symfony\Component\HttpKernel\Exception\HttpException;
use Drupal\Core\Utility\Token;
use Drupal\Core\Routing\RouteMatchInterface;
/**
* Form that lets users upload one or more files as children to a resource node.
*/
class AddMediaForm extends FormBase {
/**
* Entity type manager.
*
* @var \Drupal\Core\Entity\EntityTypeManagerInterface
*/
protected $entityTypeManager;
/**
* Media source service.
*
* @var \Drupal\islandora\MediaSource\MediaSourceService
*/
protected $mediaSource;
/**
* Islandora utils.
*
* @var \Drupal\islandora\IslandoraUtils
*/
protected $utils;
/**
* Islandora settings.
*
* @var \Drupal\Core\Config\ImmutableConfig
*/
protected $config;
/**
* Token service.
*
* @var \Drupal\Core\Utility\Token
*/
protected $token;
/**
* Current user account.
*
* @var \Drupal\Core\Session\AccountInterface
*/
protected $account;
/**
* Parent ID, cached to survive between batch operations.
*
* @var int
*/
protected $parentId;
/**
* The route match object.
*
* @var \Drupal\Core\Routing\RouteMatchInterface
*/
protected $routeMatch;
/**
* Database connection.
*
* @var \Drupal\Core\Database\Connection
*/
protected $database;
/**
* Constructs a new IslandoraUploadForm object.
*/
public function __construct(
EntityTypeManagerInterface $entity_type_manager,
IslandoraUtils $utils,
MediaSourceService $media_source,
ImmutableConfig $config,
Token $token,
AccountInterface $account,
RouteMatchInterface $route_match,
Connection $database
) {
$this->entityTypeManager = $entity_type_manager;
$this->utils = $utils;
$this->mediaSource = $media_source;
$this->config = $config;
$this->token = $token;
$this->account = $account;
$this->routeMatch = $route_match;
$this->database = $database;
}
/**
* {@inheritdoc}
*/
public static function create(ContainerInterface $container) {
return new static(
$container->get('entity_type.manager'),
$container->get('islandora.utils'),
$container->get('islandora.media_source_service'),
$container->get('config.factory')->get('islandora.settings'),
$container->get('token'),
$container->get('current_user'),
$container->get('current_route_match'),
$container->get('database')
);
}
/**
* {@inheritdoc}
*/
public function getFormId() {
return 'add_media_form';
}
/**
* {@inheritdoc}
*/
public function buildForm(array $form, FormStateInterface $form_state) {
$upload_pattern = $this->config->get(IslandoraSettingsForm::UPLOAD_FORM_LOCATION);
$upload_location = $this->token->replace($upload_pattern);
$valid_extensions = $this->config->get(IslandoraSettingsForm::UPLOAD_FORM_ALLOWED_MIMETYPES);
$this->parentId = $this->routeMatch->getParameter('node');
$parent = $this->entityTypeManager->getStorage('node')->load($this->parentId);
$form['upload'] = [
'#type' => 'managed_file',
'#title' => $this->t('File'),
'#description' => $this->t("Upload a file for @title", ['@title' => $parent->getTitle()]),
'#upload_location' => $upload_location,
'#upload_validators' => [
'file_validate_extensions' => [$valid_extensions],
],
'#required' => TRUE,
];
$options = [];
$terms = $this->entityTypeManager->getStorage('taxonomy_term')->loadTree('islandora_media_use', 0, NULL, TRUE);
foreach ($terms as $term) {
$options[$this->utils->getUriForTerm($term)] = $term->getName();
};
$form['use'] = [
'#type' => 'checkboxes',
'#title' => $this->t('Usage'),
'#description' => $this->t("Defined by Portland Common Data Model: Use Extension https://pcdm.org/2015/05/12/use. ''Original File'' will trigger creation of derivatives."),
'#options' => $options,
'#required' => TRUE,
];
$form['submit'] = [
'#type' => 'submit',
'#value' => $this->t('Submit'),
];
return $form;
}
/**
* {@inheritdoc}
*/
public function submitForm(array &$form, FormStateInterface $form_state) {
$parent_id = $this->routeMatch->getParameter('node');
$parent = $this->entityTypeManager->getStorage('node')->load($parent_id);
$fid = $form_state->getValue('upload')[0];
$external_uris = $form_state->getValue('use');
// Since we make 2 different entities, do this in a transaction.
$transaction = $this->database->startTransaction();
try {
$file = $this->entityTypeManager->getStorage('file')->load($fid);
$file->setPermanent();
$file->save();
$parent = $this->entityTypeManager->getStorage('node')->load($parent_id);
$mime = $file->getMimetype();
$exploded_mime = explode('/', $mime);
if ($exploded_mime[0] == 'image') {
if (in_array($exploded_mime[1], ['tiff', 'jp2'])) {
$media_type = 'file';
}
else {
$media_type = 'image';
}
}
elseif ($exploded_mime[0] == 'audio') {
$media_type = 'audio';
}
elseif ($exploded_mime[0] == 'video') {
$media_type = 'video';
}
else {
$media_type = 'file';
}
$source_field = $this->mediaSource->getSourceFieldName($media_type);
$terms = [];
foreach ($external_uris as $uri) {
$terms[] = $this->utils->getTermForUri($uri);
}
$media = $this->entityTypeManager->getStorage('media')->create([
'bundle' => $media_type,
'uid' => $this->account->id(),
$source_field => $fid,
'name' => $file->getFileName(),
IslandoraUtils::MEDIA_USAGE_FIELD => $terms,
IslandoraUtils::MEDIA_OF_FIELD => $parent,
]);
$media->save();
$form_state->setRedirect(
'view.media_of.page_1',
['node' => $parent_id]
);
}
catch (HttpException $e) {
$transaction->rollBack();
throw $e;
}
catch (\Exception $e) {
$transaction->rollBack();
throw new HttpException(500, $e->getMessage());
}
}
}

38
src/Form/IslandoraSettingsForm.php

@ -23,6 +23,9 @@ class IslandoraSettingsForm extends ConfigFormBase {
const BROKER_USER = 'broker_user';
const BROKER_PASSWORD = 'broker_password';
const JWT_EXPIRY = 'jwt_expiry';
const UPLOAD_FORM = 'upload_form';
const UPLOAD_FORM_LOCATION = 'upload_form_location';
const UPLOAD_FORM_ALLOWED_MIMETYPES = 'upload_form_allowed_mimetypes';
const GEMINI_PSEUDO = 'gemini_pseudo_bundles';
const FEDORA_URL = 'fedora_url';
const TIME_INTERVALS = [
@ -58,7 +61,10 @@ class IslandoraSettingsForm extends ConfigFormBase {
* @param \Drupal\Core\Entity\EntityTypeBundleInfoInterface $entity_type_bundle_info
* The EntityTypeBundleInfo service.
*/
public function __construct(ConfigFactoryInterface $config_factory, EntityTypeBundleInfoInterface $entity_type_bundle_info) {
public function __construct(
ConfigFactoryInterface $config_factory,
EntityTypeBundleInfoInterface $entity_type_bundle_info
) {
$this->setConfigFactory($config_factory);
$this->entityTypeBundleInfo = $entity_type_bundle_info;
$this->brokerPassword = $this->config(self::CONFIG_NAME)->get(self::BROKER_PASSWORD);
@ -70,7 +76,7 @@ class IslandoraSettingsForm extends ConfigFormBase {
public static function create(ContainerInterface $container) {
return new static(
$container->get('config.factory'),
$container->get('entity_type.bundle.info')
$container->get('entity_type.bundle.info'),
);
}
@ -145,6 +151,32 @@ class IslandoraSettingsForm extends ConfigFormBase {
),
];
$form[self::UPLOAD_FORM] = [
'#type' => 'fieldset',
'#title' => $this->t('Add Children / Media Form'),
];
$form[self::UPLOAD_FORM][self::UPLOAD_FORM_LOCATION] = [
'#type' => 'textfield',
'#title' => $this->t('Upload location'),
'#description' => $this->t('Tokenized URI pattern where the uploaded file should go. You may use tokens to provide a pattern (e.g. "fedora://[current-date:custom:Y]-[current-date:custom:m]")'),
'#default_value' => $config->get(self::UPLOAD_FORM_LOCATION),
'#element_validate' => ['token_element_validate'],
'#token_types' => ['system'],
];
$form[self::UPLOAD_FORM]['TOKEN_HELP'] = [
'#theme' => 'token_tree_link',
'#token_type' => ['system'],
];
$form[self::UPLOAD_FORM][self::UPLOAD_FORM_ALLOWED_MIMETYPES] = [
'#type' => 'textarea',
'#title' => $this->t('Allowed Mimetypes'),
'#description' => $this->t('Add mimetypes as a space delimited list with no periods before the extension.'),
'#default_value' => $config->get(self::UPLOAD_FORM_ALLOWED_MIMETYPES),
];
$flysystem_config = Settings::get('flysystem');
if ($flysystem_config != NULL) {
$fedora_url = $flysystem_config['fedora']['config']['root'];
@ -296,6 +328,8 @@ class IslandoraSettingsForm extends ConfigFormBase {
$config
->set(self::BROKER_URL, $form_state->getValue(self::BROKER_URL))
->set(self::JWT_EXPIRY, $form_state->getValue(self::JWT_EXPIRY))
->set(self::UPLOAD_FORM_LOCATION, $form_state->getValue(self::UPLOAD_FORM_LOCATION))
->set(self::UPLOAD_FORM_ALLOWED_MIMETYPES, $form_state->getValue(self::UPLOAD_FORM_ALLOWED_MIMETYPES))
->set(self::GEMINI_PSEUDO, $pseudo_types)
->save();

27
src/IslandoraUtils.php

@ -32,6 +32,8 @@ class IslandoraUtils {
const MEDIA_OF_FIELD = 'field_media_of';
const MEDIA_USAGE_FIELD = 'field_media_use';
const MEMBER_OF_FIELD = 'field_member_of';
const MODEL_FIELD = 'field_model';
/**
* The entity type manager.
@ -611,4 +613,29 @@ class IslandoraUtils {
return $rest_url;
}
/**
* Determines if an entity type and bundle make an 'Islandora' type entity.
*
* @param string $entity_type
* The entity type ('node', 'media', etc...).
* @param string $bundle
* Entity bundle ('article', 'page', etc...).
*
* @return bool
* TRUE if the bundle has the correct fields to be an 'Islandora' type.
*/
public function isIslandoraType($entity_type, $bundle) {
$fields = $this->entityFieldManager->getFieldDefinitions($entity_type, $bundle);
switch ($entity_type) {
case 'media':
return isset($fields[self::MEDIA_OF_FIELD]) && isset($fields[self::MEDIA_USAGE_FIELD]);
case 'taxonomy_term':
return isset($fields[self::EXTERNAL_URI_FIELD]);
default:
return isset($fields[self::MEMBER_OF_FIELD]) && isset($fields[self::MODEL_FIELD]);
}
}
}

Loading…
Cancel
Save