Browse Source
* Add ctools, prior to using it. * Fix up all the dependency references. ... before the colon is the project name, so should only be "drupal" for modules shipped in core. * Some more together. * Decent progress... getting things actually rendering... ... bit of refactoring stuff making a mess. * More worky. ... as in, basically functional. Still needs coding standards pass, and testing with more/all types of content. * Coding standards, and warning of validation issues. * Pull the batch out to a separate service. * Something of namespacing the child-specific batch... ... 'cause need to slap together a media-specific batch similarly? * All together, I think... Both the child-uploading, and media-uploading forms. * It is not necessary to explicitly mark the files as permanent. * Further generalizing... ... no longer necessarily trying to load files, where files might not be present (for non-file media... oEmbed things?). * Adjust class comment. * Get rid of the deprecation flags. * Remove unused constant. ... is defined instead at the "FileSelectionForm" level, accidentally left it here from intermediate implementation state. * Pass the renderer along, with the version constraint. * Add update hook to enable ctools in sites where it may not be. ... as it's now required. * Cover ALL the exits. * Refine message. * Excessively long line in comment... ... whoops. * Bump spec up to allow ctools 4. Gave it a run through here, and seemed to work fine; however, ctools' project page still seems to suggest the 3 major version should be preferred... but let's allow 4, if people are using or want to test it out? * Fix undefined "count" index.pull/904/merge 2.5.0
Adam
2 years ago
committed by
GitHub
21 changed files with 1441 additions and 21 deletions
@ -0,0 +1,258 @@
|
||||
<?php |
||||
|
||||
namespace Drupal\islandora\Form\AddChildrenWizard; |
||||
|
||||
use Drupal\Core\Database\Connection; |
||||
use Drupal\Core\Datetime\DateFormatterInterface; |
||||
use Drupal\Core\DependencyInjection\DependencySerializationTrait; |
||||
use Drupal\Core\Entity\EntityTypeManagerInterface; |
||||
use Drupal\Core\Messenger\MessengerInterface; |
||||
use Drupal\Core\Session\AccountProxyInterface; |
||||
use Drupal\Core\StringTranslation\StringTranslationTrait; |
||||
use Drupal\Core\Url; |
||||
use Drupal\file\FileInterface; |
||||
use Drupal\islandora\IslandoraUtils; |
||||
use Drupal\media\MediaInterface; |
||||
use Drupal\node\NodeInterface; |
||||
use Symfony\Component\HttpKernel\Exception\HttpException; |
||||
use Symfony\Component\HttpKernel\Exception\HttpExceptionInterface; |
||||
|
||||
/** |
||||
* Abstract addition batch processor. |
||||
*/ |
||||
abstract class AbstractBatchProcessor { |
||||
|
||||
use FieldTrait; |
||||
use DependencySerializationTrait; |
||||
use StringTranslationTrait; |
||||
|
||||
/** |
||||
* The entity type manager service. |
||||
* |
||||
* @var \Drupal\Core\Entity\EntityTypeManagerInterface|null |
||||
*/ |
||||
protected ?EntityTypeManagerInterface $entityTypeManager = NULL; |
||||
|
||||
/** |
||||
* The database connection serivce. |
||||
* |
||||
* @var \Drupal\Core\Database\Connection|null |
||||
*/ |
||||
protected ?Connection $database; |
||||
|
||||
/** |
||||
* The current user. |
||||
* |
||||
* @var \Drupal\Core\Session\AccountProxyInterface|null |
||||
*/ |
||||
protected ?AccountProxyInterface $currentUser; |
||||
|
||||
/** |
||||
* The messenger service. |
||||
* |
||||
* @var \Drupal\Core\Messenger\MessengerInterface |
||||
*/ |
||||
protected MessengerInterface $messenger; |
||||
|
||||
/** |
||||
* The date formatter service. |
||||
* |
||||
* @var \Drupal\Core\Datetime\DateFormatterInterface |
||||
*/ |
||||
protected DateFormatterInterface $dateFormatter; |
||||
|
||||
/** |
||||
* Constructor. |
||||
*/ |
||||
public function __construct( |
||||
EntityTypeManagerInterface $entity_type_manager, |
||||
Connection $database, |
||||
AccountProxyInterface $current_user, |
||||
MessengerInterface $messenger, |
||||
DateFormatterInterface $date_formatter |
||||
) { |
||||
$this->entityTypeManager = $entity_type_manager; |
||||
$this->database = $database; |
||||
$this->currentUser = $current_user; |
||||
$this->messenger = $messenger; |
||||
$this->dateFormatter = $date_formatter; |
||||
} |
||||
|
||||
/** |
||||
* Implements callback_batch_operation() for our child addition batch. |
||||
*/ |
||||
public function batchOperation($delta, $info, array $values, &$context) { |
||||
$transaction = $this->database->startTransaction(); |
||||
|
||||
try { |
||||
$entities[] = $node = $this->getNode($info, $values); |
||||
$entities[] = $this->createMedia($node, $info, $values); |
||||
|
||||
$context['results'] = array_merge_recursive($context['results'], [ |
||||
'validation_violations' => $this->validationClassification($entities), |
||||
]); |
||||
$context['results']['count'] = ($context['results']['count'] ?? 0) + 1; |
||||
} |
||||
catch (HttpExceptionInterface $e) { |
||||
$transaction->rollBack(); |
||||
throw $e; |
||||
} |
||||
catch (\Exception $e) { |
||||
$transaction->rollBack(); |
||||
throw new HttpException(500, $e->getMessage(), $e); |
||||
} |
||||
} |
||||
|
||||
/** |
||||
* Loads the file indicated. |
||||
* |
||||
* @param mixed $info |
||||
* Widget values. |
||||
* |
||||
* @return \Drupal\file\FileInterface|null |
||||
* The loaded file. |
||||
* |
||||
* @throws \Drupal\Component\Plugin\Exception\InvalidPluginDefinitionException |
||||
* @throws \Drupal\Component\Plugin\Exception\PluginNotFoundException |
||||
*/ |
||||
protected function getFile($info) : ?FileInterface { |
||||
return (is_array($info) && isset($info['target_id'])) ? |
||||
$this->entityTypeManager->getStorage('file')->load($info['target_id']) : |
||||
NULL; |
||||
} |
||||
|
||||
/** |
||||
* Get the node to which to attach our media. |
||||
* |
||||
* @param mixed $info |
||||
* Info from the widget used to create the request. |
||||
* @param array $values |
||||
* Additional form inputs. |
||||
* |
||||
* @return \Drupal\node\NodeInterface |
||||
* The node to which to attach the created media. |
||||
*/ |
||||
abstract protected function getNode($info, array $values) : NodeInterface; |
||||
|
||||
/** |
||||
* Get a name to use for bulk-created assets. |
||||
* |
||||
* @param mixed $info |
||||
* Widget values. |
||||
* @param array $values |
||||
* Form values. |
||||
* |
||||
* @return string |
||||
* An applicable name. |
||||
* |
||||
* @throws \Drupal\Component\Plugin\Exception\InvalidPluginDefinitionException |
||||
* @throws \Drupal\Component\Plugin\Exception\PluginNotFoundException |
||||
*/ |
||||
protected function getName($info, array $values) : string { |
||||
$file = $this->getFile($info); |
||||
return $file ? $file->getFilename() : strtr('Bulk ingest, {date}', [ |
||||
'{date}' => $this->dateFormatter->format(time(), 'long'), |
||||
]); |
||||
} |
||||
|
||||
/** |
||||
* Create a media referencing the given file, associated with the given node. |
||||
* |
||||
* @param \Drupal\node\NodeInterface $node |
||||
* The node to which the media should be associated. |
||||
* @param mixed $info |
||||
* The widget info for the media source field. |
||||
* @param array $values |
||||
* Values from the wizard, which should contain at least: |
||||
* - media_type: The machine name/ID of the media type as which to create |
||||
* the media |
||||
* - use: An array of the selected "media use" terms. |
||||
* |
||||
* @return \Drupal\media\MediaInterface |
||||
* The created media entity. |
||||
* |
||||
* @throws \Drupal\Component\Plugin\Exception\InvalidPluginDefinitionException |
||||
* @throws \Drupal\Component\Plugin\Exception\PluginNotFoundException |
||||
* @throws \Drupal\Core\Entity\EntityStorageException |
||||
*/ |
||||
protected function createMedia(NodeInterface $node, $info, array $values) : MediaInterface { |
||||
$taxonomy_term_storage = $this->entityTypeManager->getStorage('taxonomy_term'); |
||||
|
||||
// Create a media with the file attached and also pointing at the node. |
||||
$field = $this->getField($values); |
||||
|
||||
$media_values = array_merge( |
||||
[ |
||||
'bundle' => $values['media_type'], |
||||
'name' => $this->getName($info, $values), |
||||
IslandoraUtils::MEDIA_OF_FIELD => $node, |
||||
IslandoraUtils::MEDIA_USAGE_FIELD => ($values['use'] ? |
||||
$taxonomy_term_storage->loadMultiple($values['use']) : |
||||
NULL), |
||||
'uid' => $this->currentUser->id(), |
||||
// XXX: Published... no constant? |
||||
'status' => 1, |
||||
], |
||||
[ |
||||
$field->getName() => [ |
||||
$info, |
||||
], |
||||
] |
||||
); |
||||
$media = $this->entityTypeManager->getStorage('media')->create($media_values); |
||||
if ($media->save() !== SAVED_NEW) { |
||||
throw new \Exception("Failed to create media."); |
||||
} |
||||
|
||||
return $media; |
||||
} |
||||
|
||||
/** |
||||
* Helper to bulk process validatable entities. |
||||
* |
||||
* @param array $entities |
||||
* An array of entities to scan for validation violations. |
||||
* |
||||
* @return array |
||||
* An associative array mapping entity type IDs to entity IDs to a count |
||||
* of validation violations found on then given entity. |
||||
*/ |
||||
protected function validationClassification(array $entities) { |
||||
$violations = []; |
||||
|
||||
foreach ($entities as $entity) { |
||||
$entity_violations = $entity->validate(); |
||||
if ($entity_violations->count() > 0) { |
||||
$violations[$entity->getEntityTypeId()][$entity->id()] = $entity_violations->count(); |
||||
} |
||||
} |
||||
|
||||
return $violations; |
||||
} |
||||
|
||||
/** |
||||
* Implements callback_batch_finished() for our child addition batch. |
||||
*/ |
||||
public function batchProcessFinished($success, $results, $operations): void { |
||||
if ($success) { |
||||
foreach ($results['validation_violations'] ?? [] as $entity_type => $info) { |
||||
foreach ($info as $id => $count) { |
||||
$this->messenger->addWarning($this->formatPlural( |
||||
$count, |
||||
'1 validation error present in <a target="_blank" href=":uri">bulk created entity of type %type, with ID %id</a>.', |
||||
'@count validation errors present in <a target="_blank" href=":uri">bulk created entity of type %type, with ID %id</a>.', |
||||
[ |
||||
'%type' => $entity_type, |
||||
':uri' => Url::fromRoute("entity.{$entity_type}.canonical", [$entity_type => $id])->toString(), |
||||
'%id' => $id, |
||||
] |
||||
)); |
||||
} |
||||
} |
||||
} |
||||
else { |
||||
$this->messenger->addError($this->t('Encountered an error when processing.')); |
||||
} |
||||
} |
||||
|
||||
} |
@ -0,0 +1,157 @@
|
||||
<?php |
||||
|
||||
namespace Drupal\islandora\Form\AddChildrenWizard; |
||||
|
||||
use Drupal\Core\Batch\BatchBuilder; |
||||
use Drupal\Core\Field\BaseFieldDefinition; |
||||
use Drupal\Core\Field\FieldDefinitionInterface; |
||||
use Drupal\Core\Field\FieldItemList; |
||||
use Drupal\Core\Field\FieldStorageDefinitionInterface; |
||||
use Drupal\Core\Field\WidgetInterface; |
||||
use Drupal\Core\Form\FormBase; |
||||
use Drupal\Core\Form\FormStateInterface; |
||||
use Drupal\Core\Session\AccountProxyInterface; |
||||
use Drupal\field\FieldStorageConfigInterface; |
||||
use Drupal\media\MediaTypeInterface; |
||||
use Symfony\Component\DependencyInjection\ContainerInterface; |
||||
|
||||
/** |
||||
* Children addition wizard's second step. |
||||
*/ |
||||
abstract class AbstractFileSelectionForm extends FormBase { |
||||
|
||||
use WizardTrait; |
||||
|
||||
const BATCH_PROCESSOR = 'abstract.abstract'; |
||||
|
||||
/** |
||||
* The current user. |
||||
* |
||||
* @var \Drupal\Core\Session\AccountProxyInterface|null |
||||
*/ |
||||
protected ?AccountProxyInterface $currentUser; |
||||
|
||||
/** |
||||
* The batch processor service. |
||||
* |
||||
* @var \Drupal\islandora\Form\AddChildrenWizard\AbstractBatchProcessor|null |
||||
*/ |
||||
protected ?AbstractBatchProcessor $batchProcessor; |
||||
|
||||
/** |
||||
* {@inheritdoc} |
||||
*/ |
||||
public static function create(ContainerInterface $container): self { |
||||
$instance = parent::create($container); |
||||
|
||||
$instance->entityTypeManager = $container->get('entity_type.manager'); |
||||
$instance->widgetPluginManager = $container->get('plugin.manager.field.widget'); |
||||
$instance->entityFieldManager = $container->get('entity_field.manager'); |
||||
$instance->currentUser = $container->get('current_user'); |
||||
|
||||
$instance->batchProcessor = $container->get(static::BATCH_PROCESSOR); |
||||
|
||||
return $instance; |
||||
} |
||||
|
||||
/** |
||||
* Helper; get the media type, based off discovering from form state. |
||||
* |
||||
* @param \Drupal\Core\Form\FormStateInterface $form_state |
||||
* The form state. |
||||
* |
||||
* @return \Drupal\media\MediaTypeInterface |
||||
* The target media type. |
||||
* |
||||
* @throws \Drupal\Component\Plugin\Exception\InvalidPluginDefinitionException |
||||
* @throws \Drupal\Component\Plugin\Exception\PluginNotFoundException |
||||
*/ |
||||
protected function getMediaTypeFromFormState(FormStateInterface $form_state): MediaTypeInterface { |
||||
return $this->getMediaType($form_state->getTemporaryValue('wizard')); |
||||
} |
||||
|
||||
/** |
||||
* Helper; get field instance, based off discovering from form state. |
||||
* |
||||
* @param \Drupal\Core\Form\FormStateInterface $form_state |
||||
* The form state. |
||||
* |
||||
* @return \Drupal\Core\Field\FieldDefinitionInterface |
||||
* The field definition. |
||||
*/ |
||||
protected function getFieldFromFormState(FormStateInterface $form_state): FieldDefinitionInterface { |
||||
$cached_values = $form_state->getTemporaryValue('wizard'); |
||||
|
||||
$field = $this->getField($cached_values); |
||||
$def = $field->getFieldStorageDefinition(); |
||||
if ($def instanceof FieldStorageConfigInterface) { |
||||
$def->set('cardinality', FieldStorageDefinitionInterface::CARDINALITY_UNLIMITED); |
||||
} |
||||
elseif ($def instanceof BaseFieldDefinition) { |
||||
$def->setCardinality(FieldStorageDefinitionInterface::CARDINALITY_UNLIMITED); |
||||
} |
||||
else { |
||||
throw new \Exception('Unable to remove cardinality limit.'); |
||||
} |
||||
|
||||
return $field; |
||||
} |
||||
|
||||
/** |
||||
* Helper; get widget for the field, based on discovering from form state. |
||||
* |
||||
* @param \Drupal\Core\Form\FormStateInterface $form_state |
||||
* The form state. |
||||
* |
||||
* @return \Drupal\Core\Field\WidgetInterface |
||||
* The widget. |
||||
*/ |
||||
protected function getWidgetFromFormState(FormStateInterface $form_state): WidgetInterface { |
||||
return $this->getWidget($this->getFieldFromFormState($form_state)); |
||||
} |
||||
|
||||
/** |
||||
* {@inheritdoc} |
||||
*/ |
||||
public function buildForm(array $form, FormStateInterface $form_state): array { |
||||
// Using the media type selected in the previous step, grab the |
||||
// media bundle's "source" field, and create a multi-file upload widget |
||||
// for it, with the same kind of constraints. |
||||
$field = $this->getFieldFromFormState($form_state); |
||||
$items = FieldItemList::createInstance($field, $field->getName(), $this->getMediaTypeFromFormState($form_state)->getTypedData()); |
||||
|
||||
$form['#tree'] = TRUE; |
||||
$form['#parents'] = []; |
||||
$widget = $this->getWidgetFromFormState($form_state); |
||||
$form['files'] = $widget->form( |
||||
$items, |
||||
$form, |
||||
$form_state |
||||
); |
||||
|
||||
return $form; |
||||
} |
||||
|
||||
/** |
||||
* {@inheritdoc} |
||||
*/ |
||||
public function submitForm(array &$form, FormStateInterface $form_state) { |
||||
$cached_values = $form_state->getTemporaryValue('wizard'); |
||||
|
||||
$widget = $this->getWidgetFromFormState($form_state); |
||||
$builder = (new BatchBuilder()) |
||||
->setTitle($this->t('Bulk creating...')) |
||||
->setInitMessage($this->t('Initializing...')) |
||||
->setFinishCallback([$this->batchProcessor, 'batchProcessFinished']); |
||||
$values = $form_state->getValue($this->getField($cached_values)->getName()); |
||||
$massaged_values = $widget->massageFormValues($values, $form, $form_state); |
||||
foreach ($massaged_values as $delta => $info) { |
||||
$builder->addOperation( |
||||
[$this->batchProcessor, 'batchOperation'], |
||||
[$delta, $info, $cached_values] |
||||
); |
||||
} |
||||
batch_set($builder->toArray()); |
||||
} |
||||
|
||||
} |
@ -0,0 +1,125 @@
|
||||
<?php |
||||
|
||||
namespace Drupal\islandora\Form\AddChildrenWizard; |
||||
|
||||
use Drupal\Core\DependencyInjection\ClassResolverInterface; |
||||
use Drupal\Core\Form\FormBuilderInterface; |
||||
use Drupal\Core\Render\RendererInterface; |
||||
use Drupal\Core\Routing\RouteMatchInterface; |
||||
use Drupal\Core\Session\AccountProxyInterface; |
||||
use Drupal\Core\TempStore\SharedTempStoreFactory; |
||||
use Drupal\ctools\Wizard\FormWizardBase; |
||||
use Drupal\islandora\IslandoraUtils; |
||||
use Symfony\Component\EventDispatcher\EventDispatcherInterface; |
||||
|
||||
/** |
||||
* Bulk children addition wizard base form. |
||||
*/ |
||||
abstract class AbstractForm extends FormWizardBase { |
||||
|
||||
const TEMPSTORE_ID = 'abstract.abstract'; |
||||
const TYPE_SELECTION_FORM = MediaTypeSelectionForm::class; |
||||
const FILE_SELECTION_FORM = AbstractFileSelectionForm::class; |
||||
|
||||
/** |
||||
* The Islandora Utils service. |
||||
* |
||||
* @var \Drupal\islandora\IslandoraUtils |
||||
*/ |
||||
protected IslandoraUtils $utils; |
||||
|
||||
/** |
||||
* The current node ID. |
||||
* |
||||
* @var mixed|null |
||||
*/ |
||||
protected $nodeId; |
||||
|
||||
/** |
||||
* The current route match. |
||||
* |
||||
* @var \Drupal\Core\Routing\RouteMatchInterface |
||||
*/ |
||||
protected RouteMatchInterface $currentRoute; |
||||
|
||||
/** |
||||
* The current user. |
||||
* |
||||
* @var \Drupal\Core\Session\AccountProxyInterface |
||||
*/ |
||||
protected AccountProxyInterface $currentUser; |
||||
|
||||
/** |
||||
* Constructor. |
||||
*/ |
||||
public function __construct( |
||||
SharedTempStoreFactory $tempstore, |
||||
FormBuilderInterface $builder, |
||||
ClassResolverInterface $class_resolver, |
||||
EventDispatcherInterface $event_dispatcher, |
||||
RouteMatchInterface $route_match, |
||||
RendererInterface $renderer, |
||||
$tempstore_id, |
||||
AccountProxyInterface $current_user, |
||||
$machine_name = NULL, |
||||
$step = NULL |
||||
) { |
||||
parent::__construct($tempstore, $builder, $class_resolver, $event_dispatcher, $route_match, $renderer, $tempstore_id, |
||||
$machine_name, $step); |
||||
|
||||
$this->nodeId = $this->routeMatch->getParameter('node'); |
||||
$this->currentUser = $current_user; |
||||
} |
||||
|
||||
/** |
||||
* {@inheritdoc} |
||||
*/ |
||||
public static function getParameters() : array { |
||||
return array_merge( |
||||
parent::getParameters(), |
||||
[ |
||||
'tempstore_id' => static::TEMPSTORE_ID, |
||||
'current_user' => \Drupal::service('current_user'), |
||||
] |
||||
); |
||||
} |
||||
|
||||
/** |
||||
* {@inheritdoc} |
||||
*/ |
||||
public function getOperations($cached_values) { |
||||
$ops = []; |
||||
|
||||
$ops['type_selection'] = [ |
||||
'title' => $this->t('Type Selection'), |
||||
'form' => static::TYPE_SELECTION_FORM, |
||||
'values' => [ |
||||
'node' => $this->nodeId, |
||||
], |
||||
]; |
||||
$ops['file_selection'] = [ |
||||
'title' => $this->t('Widget Input for Selected Type'), |
||||
'form' => static::FILE_SELECTION_FORM, |
||||
'values' => [ |
||||
'node' => $this->nodeId, |
||||
], |
||||
]; |
||||
|
||||
return $ops; |
||||
} |
||||
|
||||
/** |
||||
* {@inheritdoc} |
||||
*/ |
||||
public function getNextParameters($cached_values) { |
||||
return parent::getNextParameters($cached_values) + ['node' => $this->nodeId]; |
||||
} |
||||
|
||||
/** |
||||
* {@inheritdoc} |
||||
*/ |
||||
public function getPreviousParameters($cached_values) { |
||||
return parent::getPreviousParameters($cached_values) + ['node' => $this->nodeId]; |
||||
} |
||||
|
||||
} |
@ -0,0 +1,71 @@
|
||||
<?php |
||||
|
||||
namespace Drupal\islandora\Form\AddChildrenWizard; |
||||
|
||||
use Drupal\Core\Access\AccessResult; |
||||
use Drupal\Core\Access\AccessResultInterface; |
||||
use Drupal\Core\DependencyInjection\ContainerInjectionInterface; |
||||
use Drupal\Core\Routing\RouteMatch; |
||||
use Drupal\islandora\IslandoraUtils; |
||||
use Symfony\Component\DependencyInjection\ContainerInterface; |
||||
|
||||
/** |
||||
* Access checker. |
||||
* |
||||
* The _wizard/_form route enhancers do not really allow for access checking |
||||
* things, so let's roll it separately for now. |
||||
*/ |
||||
class Access implements ContainerInjectionInterface { |
||||
|
||||
/** |
||||
* The Islandora utils service. |
||||
* |
||||
* @var \Drupal\islandora\IslandoraUtils |
||||
*/ |
||||
protected IslandoraUtils $utils; |
||||
|
||||
/** |
||||
* Constructor. |
||||
*/ |
||||
public function __construct(IslandoraUtils $utils) { |
||||
$this->utils = $utils; |
||||
} |
||||
|
||||
/** |
||||
* {@inheritdoc} |
||||
*/ |
||||
public static function create(ContainerInterface $container) : self { |
||||
return new static( |
||||
$container->get('islandora.utils') |
||||
); |
||||
} |
||||
|
||||
/** |
||||
* Check if the user can create any "Islandora" nodes and media. |
||||
* |
||||
* @param \Drupal\Core\Routing\RouteMatch $route_match |
||||
* The current routing match. |
||||
* |
||||
* @return \Drupal\Core\Access\AccessResultInterface |
||||
* Whether we can or cannot show the "thing". |
||||
*/ |
||||
public function childAccess(RouteMatch $route_match) : AccessResultInterface { |
||||
return AccessResult::allowedIf($this->utils->canCreateIslandoraEntity('node', 'node_type')) |
||||
->andIf($this->mediaAccess($route_match)); |
||||
|
||||
} |
||||
|
||||
/** |
||||
* Check if the user can create any "Islandora" media. |
||||
* |
||||
* @param \Drupal\Core\Routing\RouteMatch $route_match |
||||
* The current routing match. |
||||
* |
||||
* @return \Drupal\Core\Access\AccessResultInterface |
||||
* Whether we can or cannot show the "thing". |
||||
*/ |
||||
public function mediaAccess(RouteMatch $route_match) : AccessResultInterface { |
||||
return AccessResult::allowedIf($this->utils->canCreateIslandoraEntity('media', 'media_type')); |
||||
} |
||||
|
||||
} |
@ -0,0 +1,57 @@
|
||||
<?php |
||||
|
||||
namespace Drupal\islandora\Form\AddChildrenWizard; |
||||
|
||||
use Drupal\islandora\IslandoraUtils; |
||||
use Drupal\node\NodeInterface; |
||||
|
||||
/** |
||||
* Children addition batch processor. |
||||
*/ |
||||
class ChildBatchProcessor extends AbstractBatchProcessor { |
||||
|
||||
/** |
||||
* {@inheritdoc} |
||||
*/ |
||||
protected function getNode($info, array $values) : NodeInterface { |
||||
$taxonomy_term_storage = $this->entityTypeManager->getStorage('taxonomy_term'); |
||||
$node_storage = $this->entityTypeManager->getStorage('node'); |
||||
$parent = $node_storage->load($values['node']); |
||||
|
||||
// Create a node (with the filename?) (and also belonging to the target |
||||
// node). |
||||
/** @var \Drupal\node\NodeInterface $node */ |
||||
$node = $node_storage->create([ |
||||
'type' => $values['bundle'], |
||||
'title' => $this->getName($info, $values), |
||||
IslandoraUtils::MEMBER_OF_FIELD => $parent, |
||||
'uid' => $this->currentUser->id(), |
||||
'status' => NodeInterface::PUBLISHED, |
||||
IslandoraUtils::MODEL_FIELD => ($values['model'] ? |
||||
$taxonomy_term_storage->load($values['model']) : |
||||
NULL), |
||||
]); |
||||
|
||||
if ($node->save() !== SAVED_NEW) { |
||||
throw new \Exception("Failed to create node."); |
||||
} |
||||
|
||||
return $node; |
||||
} |
||||
|
||||
/** |
||||
* {@inheritdoc} |
||||
*/ |
||||
public function batchProcessFinished($success, $results, $operations): void { |
||||
if ($success) { |
||||
$this->messenger->addMessage($this->formatPlural( |
||||
$results['count'], |
||||
'Added 1 child node.', |
||||
'Added @count child nodes.' |
||||
)); |
||||
} |
||||
|
||||
parent::batchProcessFinished($success, $results, $operations); |
||||
} |
||||
|
||||
} |
@ -0,0 +1,32 @@
|
||||
<?php |
||||
|
||||
namespace Drupal\islandora\Form\AddChildrenWizard; |
||||
|
||||
use Drupal\Core\Form\FormStateInterface; |
||||
use Drupal\Core\Url; |
||||
|
||||
/** |
||||
* Children addition wizard's second step. |
||||
*/ |
||||
class ChildFileSelectionForm extends AbstractFileSelectionForm { |
||||
|
||||
public const BATCH_PROCESSOR = 'islandora.upload_children.batch_processor'; |
||||
|
||||
/** |
||||
* {@inheritdoc} |
||||
*/ |
||||
public function getFormId() { |
||||
return 'islandora_add_children_wizard_file_selection'; |
||||
} |
||||
|
||||
/** |
||||
* {@inheritdoc} |
||||
*/ |
||||
public function submitForm(array &$form, FormStateInterface $form_state) { |
||||
parent::submitForm($form, $form_state); |
||||
|
||||
$cached_values = $form_state->getTemporaryValue('wizard'); |
||||
$form_state->setRedirectUrl(Url::fromUri("internal:/node/{$cached_values['node']}/members")); |
||||
} |
||||
|
||||
} |
@ -0,0 +1,24 @@
|
||||
<?php |
||||
|
||||
namespace Drupal\islandora\Form\AddChildrenWizard; |
||||
|
||||
/** |
||||
* Bulk children addition wizard base form. |
||||
*/ |
||||
class ChildForm extends AbstractForm { |
||||
|
||||
const TEMPSTORE_ID = 'islandora.upload_children'; |
||||
const TYPE_SELECTION_FORM = ChildTypeSelectionForm::class; |
||||
const FILE_SELECTION_FORM = ChildFileSelectionForm::class; |
||||
|
||||
/** |
||||
* {@inheritdoc} |
||||
*/ |
||||
public function getMachineName() { |
||||
return strtr("islandora_add_children_wizard__{userid}__{nodeid}", [ |
||||
'{userid}' => $this->currentUser->id(), |
||||
'{nodeid}' => $this->nodeId, |
||||
]); |
||||
} |
||||
|
||||
} |
@ -0,0 +1,157 @@
|
||||
<?php |
||||
|
||||
namespace Drupal\islandora\Form\AddChildrenWizard; |
||||
|
||||
use Drupal\Core\Cache\CacheableMetadata; |
||||
use Drupal\Core\Form\FormStateInterface; |
||||
use Drupal\islandora\IslandoraUtils; |
||||
|
||||
/** |
||||
* Children addition wizard's first step. |
||||
*/ |
||||
class ChildTypeSelectionForm extends MediaTypeSelectionForm { |
||||
|
||||
/** |
||||
* {@inheritdoc} |
||||
*/ |
||||
public function getFormId() : string { |
||||
return 'islandora_add_children_type_selection'; |
||||
} |
||||
|
||||
/** |
||||
* Memoization for ::getNodeBundleOptions(). |
||||
* |
||||
* @var array|null |
||||
*/ |
||||
protected ?array $nodeBundleOptions = NULL; |
||||
|
||||
/** |
||||
* Indicate presence of model field on node bundles. |
||||
* |
||||
* Populated as a side effect of ::getNodeBundleOptions(). |
||||
* |
||||
* @var array|null |
||||
*/ |
||||
protected ?array $nodeBundleHasModelField = NULL; |
||||
|
||||
/** |
||||
* Helper; get the node bundle options available to the current user. |
||||
* |
||||
* @return array |
||||
* An associative array mapping node bundle machine names to their human- |
||||
* readable labels. |
||||
*/ |
||||
protected function getNodeBundleOptions() : array { |
||||
if ($this->nodeBundleOptions === NULL) { |
||||
$this->nodeBundleOptions = []; |
||||
$this->nodeBundleHasModelField = []; |
||||
|
||||
$access_handler = $this->entityTypeManager->getAccessControlHandler('node'); |
||||
foreach ($this->entityTypeBundleInfo->getBundleInfo('node') as $bundle => $info) { |
||||
$access = $access_handler->createAccess( |
||||
$bundle, |
||||
NULL, |
||||
[], |
||||
TRUE |
||||
); |
||||
$this->cacheableMetadata->addCacheableDependency($access); |
||||
if (!$access->isAllowed()) { |
||||
continue; |
||||
} |
||||
$this->nodeBundleOptions[$bundle] = $info['label']; |
||||
$fields = $this->entityFieldManager->getFieldDefinitions('node', $bundle); |
||||
$this->nodeBundleHasModelField[$bundle] = array_key_exists(IslandoraUtils::MODEL_FIELD, $fields); |
||||
} |
||||
} |
||||
|
||||
return $this->nodeBundleOptions; |
||||
} |
||||
|
||||
/** |
||||
* Generates a mapping of taxonomy term IDs to their names. |
||||
* |
||||
* @return \Generator |
||||
* The mapping of taxonomy term IDs to their names. |
||||
* |
||||
* @throws \Drupal\Component\Plugin\Exception\InvalidPluginDefinitionException |
||||
* @throws \Drupal\Component\Plugin\Exception\PluginNotFoundException |
||||
*/ |
||||
protected function getModelOptions() : \Generator { |
||||
$terms = $this->entityTypeManager->getStorage('taxonomy_term') |
||||
->loadTree('islandora_models', 0, NULL, TRUE); |
||||
foreach ($terms as $term) { |
||||
yield $term->id() => $term->getName(); |
||||
} |
||||
} |
||||
|
||||
/** |
||||
* Helper; map node bundles supporting the "has model" field, for #states. |
||||
* |
||||
* @return \Generator |
||||
* Yields associative array mapping the string 'value' to the bundles which |
||||
* have the given field. |
||||
*/ |
||||
protected function mapModelStates() : \Generator { |
||||
$this->getNodeBundleOptions(); |
||||
foreach (array_keys(array_filter($this->nodeBundleHasModelField)) as $bundle) { |
||||
yield ['value' => $bundle]; |
||||
} |
||||
} |
||||
|
||||
/** |
||||
* {@inheritdoc} |
||||
*/ |
||||
public function buildForm(array $form, FormStateInterface $form_state) { |
||||
$this->cacheableMetadata = CacheableMetadata::createFromRenderArray($form) |
||||
->addCacheContexts([ |
||||
'url', |
||||
'url.query_args', |
||||
]); |
||||
$cached_values = $form_state->getTemporaryValue('wizard'); |
||||
|
||||
$form['bundle'] = [ |
||||
'#type' => 'select', |
||||
'#title' => $this->t('Content Type'), |
||||
'#description' => $this->t('Each child created will have this content type.'), |
||||
'#empty_value' => '', |
||||
'#default_value' => $cached_values['bundle'] ?? '', |
||||
'#options' => $this->getNodeBundleOptions(), |
||||
'#required' => TRUE, |
||||
]; |
||||
|
||||
$model_states = iterator_to_array($this->mapModelStates()); |
||||
$form['model'] = [ |
||||
'#type' => 'select', |
||||
'#title' => $this->t('Model'), |
||||
'#description' => $this->t('Each child will be tagged with this model.'), |
||||
'#options' => iterator_to_array($this->getModelOptions()), |
||||
'#empty_value' => '', |
||||
'#default_value' => $cached_values['model'] ?? '', |
||||
'#states' => [ |
||||
'visible' => [ |
||||
':input[name="bundle"]' => $model_states, |
||||
], |
||||
'required' => [ |
||||
':input[name="bundle"]' => $model_states, |
||||
], |
||||
], |
||||
]; |
||||
|
||||
$this->cacheableMetadata->applyTo($form); |
||||
return parent::buildForm($form, $form_state); |
||||
} |
||||
|
||||
/** |
||||
* {@inheritdoc} |
||||
*/ |
||||
protected static function keysToSave() : array { |
||||
return array_merge( |
||||
parent::keysToSave(), |
||||
[ |
||||
'bundle', |
||||
'model', |
||||
] |
||||
); |
||||
} |
||||
|
||||
} |
@ -0,0 +1,66 @@
|
||||
<?php |
||||
|
||||
namespace Drupal\islandora\Form\AddChildrenWizard; |
||||
|
||||
use Drupal\Core\Entity\EntityFieldManagerInterface; |
||||
use Drupal\Core\Field\FieldDefinitionInterface; |
||||
|
||||
/** |
||||
* Field lookup helper trait. |
||||
*/ |
||||
trait FieldTrait { |
||||
|
||||
use MediaTypeTrait; |
||||
|
||||
/** |
||||
* The entity field manager service. |
||||
* |
||||
* @var \Drupal\Core\Entity\EntityFieldManagerInterface|null |
||||
*/ |
||||
protected ?EntityFieldManagerInterface $entityFieldManager = NULL; |
||||
|
||||
/** |
||||
* Helper; get field instance, given our required values. |
||||
* |
||||
* @param array $values |
||||
* See ::getMediaType() for which values are required. |
||||
* |
||||
* @return \Drupal\Core\Field\FieldDefinitionInterface |
||||
* The target field. |
||||
* |
||||
* @throws \Drupal\Component\Plugin\Exception\InvalidPluginDefinitionException |
||||
* @throws \Drupal\Component\Plugin\Exception\PluginNotFoundException |
||||
*/ |
||||
protected function getField(array $values): FieldDefinitionInterface { |
||||
$media_type = $this->getMediaType($values); |
||||
$media_source = $media_type->getSource(); |
||||
$source_field = $media_source->getSourceFieldDefinition($media_type); |
||||
|
||||
$fields = $this->entityFieldManager()->getFieldDefinitions('media', $media_type->id()); |
||||
|
||||
return $fields[$source_field->getFieldStorageDefinition()->getName()] ?? |
||||
$media_source->createSourceField($media_type); |
||||
} |
||||
|
||||
/** |
||||
* Lazy-initialization of the entity field manager service. |
||||
* |
||||
* @return \Drupal\Core\Entity\EntityFieldManagerInterface |
||||
* The entity field manager service. |
||||
*/ |
||||
protected function entityFieldManager() : EntityFieldManagerInterface { |
||||
if ($this->entityFieldManager === NULL) { |
||||
$this->setEntityFieldManager(\Drupal::service('entity_field.manager')); |
||||
} |
||||
return $this->entityFieldManager; |
||||
} |
||||
|
||||
/** |
||||
* Setter for entity field manager. |
||||
*/ |
||||
public function setEntityFieldManager(EntityFieldManagerInterface $entity_field_manager) : self { |
||||
$this->entityFieldManager = $entity_field_manager; |
||||
return $this; |
||||
} |
||||
|
||||
} |
@ -0,0 +1,34 @@
|
||||
<?php |
||||
|
||||
namespace Drupal\islandora\Form\AddChildrenWizard; |
||||
|
||||
use Drupal\node\NodeInterface; |
||||
|
||||
/** |
||||
* Media addition batch processor. |
||||
*/ |
||||
class MediaBatchProcessor extends AbstractBatchProcessor { |
||||
|
||||
/** |
||||
* {@inheritdoc} |
||||
*/ |
||||
protected function getNode($info, array $values) : NodeInterface { |
||||
return $this->entityTypeManager->getStorage('node')->load($values['node']); |
||||
} |
||||
|
||||
/** |
||||
* {@inheritdoc} |
||||
*/ |
||||
public function batchProcessFinished($success, $results, $operations): void { |
||||
if ($success) { |
||||
$this->messenger->addMessage($this->formatPlural( |
||||
$results['count'], |
||||
'Added 1 media.', |
||||
'Added @count media.' |
||||
)); |
||||
} |
||||
|
||||
parent::batchProcessFinished($success, $results, $operations); |
||||
} |
||||
|
||||
} |
@ -0,0 +1,32 @@
|
||||
<?php |
||||
|
||||
namespace Drupal\islandora\Form\AddChildrenWizard; |
||||
|
||||
use Drupal\Core\Form\FormStateInterface; |
||||
use Drupal\Core\Url; |
||||
|
||||
/** |
||||
* Media addition wizard's second step. |
||||
*/ |
||||
class MediaFileSelectionForm extends AbstractFileSelectionForm { |
||||
|
||||
public const BATCH_PROCESSOR = 'islandora.upload_media.batch_processor'; |
||||
|
||||
/** |
||||
* {@inheritdoc} |
||||
*/ |
||||
public function getFormId() { |
||||
return 'islandora_add_media_wizard_file_selection'; |
||||
} |
||||
|
||||
/** |
||||
* {@inheritdoc} |
||||
*/ |
||||
public function submitForm(array &$form, FormStateInterface $form_state) { |
||||
parent::submitForm($form, $form_state); |
||||
|
||||
$cached_values = $form_state->getTemporaryValue('wizard'); |
||||
$form_state->setRedirectUrl(Url::fromUri("internal:/node/{$cached_values['node']}/media")); |
||||
} |
||||
|
||||
} |
@ -0,0 +1,24 @@
|
||||
<?php |
||||
|
||||
namespace Drupal\islandora\Form\AddChildrenWizard; |
||||
|
||||
/** |
||||
* Bulk children addition wizard base form. |
||||
*/ |
||||
class MediaForm extends AbstractForm { |
||||
|
||||
const TEMPSTORE_ID = 'islandora.upload_media'; |
||||
const TYPE_SELECTION_FORM = MediaTypeSelectionForm::class; |
||||
const FILE_SELECTION_FORM = MediaFileSelectionForm::class; |
||||
|
||||
/** |
||||
* {@inheritdoc} |
||||
*/ |
||||
public function getMachineName() { |
||||
return strtr("islandora_add_media_wizard__{userid}__{nodeid}", [ |
||||
'{userid}' => $this->currentUser->id(), |
||||
'{nodeid}' => $this->nodeId, |
||||
]); |
||||
} |
||||
|
||||
} |
@ -0,0 +1,227 @@
|
||||
<?php |
||||
|
||||
namespace Drupal\islandora\Form\AddChildrenWizard; |
||||
|
||||
use Drupal\Core\Cache\CacheableMetadata; |
||||
use Drupal\Core\Entity\EntityFieldManagerInterface; |
||||
use Drupal\Core\Entity\EntityTypeBundleInfoInterface; |
||||
use Drupal\Core\Entity\EntityTypeManagerInterface; |
||||
use Drupal\Core\Form\FormBase; |
||||
use Drupal\Core\Form\FormStateInterface; |
||||
use Drupal\islandora\IslandoraUtils; |
||||
use Symfony\Component\DependencyInjection\ContainerInterface; |
||||
|
||||
/** |
||||
* Children addition wizard's first step. |
||||
*/ |
||||
class MediaTypeSelectionForm extends FormBase { |
||||
|
||||
/** |
||||
* Cacheable metadata that is instantiated and used internally. |
||||
* |
||||
* @var \Drupal\Core\Cache\CacheableMetadata|null |
||||
*/ |
||||
protected ?CacheableMetadata $cacheableMetadata = NULL; |
||||
|
||||
/** |
||||
* The entity type bundle info service. |
||||
* |
||||
* @var \Drupal\Core\Entity\EntityTypeBundleInfoInterface|null |
||||
*/ |
||||
protected ?EntityTypeBundleInfoInterface $entityTypeBundleInfo; |
||||
|
||||
/** |
||||
* The entity type manager service. |
||||
* |
||||
* @var \Drupal\Core\Entity\EntityTypeManagerInterface|null |
||||
*/ |
||||
protected ?EntityTypeManagerInterface $entityTypeManager; |
||||
|
||||
/** |
||||
* The entity field manager service. |
||||
* |
||||
* @var \Drupal\Core\Entity\EntityFieldManagerInterface|null |
||||
*/ |
||||
protected ?EntityFieldManagerInterface $entityFieldManager; |
||||
|
||||
/** |
||||
* The Islandora Utils service. |
||||
* |
||||
* @var \Drupal\islandora\IslandoraUtils|null |
||||
*/ |
||||
protected ?IslandoraUtils $utils; |
||||
|
||||
/** |
||||
* {@inheritdoc} |
||||
*/ |
||||
public static function create(ContainerInterface $container) : self { |
||||
$instance = parent::create($container); |
||||
|
||||
$instance->entityTypeBundleInfo = $container->get('entity_type.bundle.info'); |
||||
$instance->entityTypeManager = $container->get('entity_type.manager'); |
||||
$instance->entityFieldManager = $container->get('entity_field.manager'); |
||||
$instance->utils = $container->get('islandora.utils'); |
||||
|
||||
return $instance; |
||||
} |
||||
|
||||
/** |
||||
* {@inheritdoc} |
||||
*/ |
||||
public function getFormId() : string { |
||||
return 'islandora_add_media_type_selection'; |
||||
} |
||||
|
||||
/** |
||||
* Memoization for ::getMediaBundleOptions(). |
||||
* |
||||
* @var array|null |
||||
*/ |
||||
protected ?array $mediaBundleOptions = NULL; |
||||
|
||||
/** |
||||
* Indicate presence of usage field on media bundles. |
||||
* |
||||
* Populated as a side effect in ::getMediaBundleOptions(). |
||||
* |
||||
* @var array|null |
||||
*/ |
||||
protected ?array $mediaBundleUsageField = NULL; |
||||
|
||||
/** |
||||
* Helper; get options for media types. |
||||
* |
||||
* @return array |
||||
* An associative array mapping the machine name of the media type to its |
||||
* human-readable label. |
||||
*/ |
||||
protected function getMediaBundleOptions() : array { |
||||
if ($this->mediaBundleOptions === NULL) { |
||||
$this->mediaBundleOptions = []; |
||||
$this->mediaBundleUsageField = []; |
||||
|
||||
$access_handler = $this->entityTypeManager->getAccessControlHandler('media'); |
||||
foreach ($this->entityTypeBundleInfo->getBundleInfo('media') as $bundle => $info) { |
||||
if (!$this->utils->isIslandoraType('media', $bundle)) { |
||||
continue; |
||||
} |
||||
$access = $access_handler->createAccess( |
||||
$bundle, |
||||
NULL, |
||||
[], |
||||
TRUE |
||||
); |
||||
$this->cacheableMetadata->addCacheableDependency($access); |
||||
if (!$access->isAllowed()) { |
||||
continue; |
||||
} |
||||
$this->mediaBundleOptions[$bundle] = $info['label']; |
||||
$fields = $this->entityFieldManager->getFieldDefinitions('media', $bundle); |
||||
$this->mediaBundleUsageField[$bundle] = array_key_exists(IslandoraUtils::MEDIA_USAGE_FIELD, $fields); |
||||
} |
||||
} |
||||
|
||||
return $this->mediaBundleOptions; |
||||
} |
||||
|
||||
/** |
||||
* Helper; list the terms of the "islandora_media_use" vocabulary. |
||||
* |
||||
* @return \Generator |
||||
* Generates term IDs as keys mapping to term names. |
||||
* |
||||
* @throws \Drupal\Component\Plugin\Exception\InvalidPluginDefinitionException |
||||
* @throws \Drupal\Component\Plugin\Exception\PluginNotFoundException |
||||
*/ |
||||
protected function getMediaUseOptions() : \Generator { |
||||
/** @var \Drupal\taxonomy\TermInterface[] $terms */ |
||||
$terms = $this->entityTypeManager->getStorage('taxonomy_term') |
||||
->loadTree('islandora_media_use', 0, NULL, TRUE); |
||||
|
||||
foreach ($terms as $term) { |
||||
yield $term->id() => $term->getName(); |
||||
} |
||||
} |
||||
|
||||
/** |
||||
* Helper; map media types supporting the usage field for use with #states. |
||||
* |
||||
* @return \Generator |
||||
* Yields associative array mapping the string 'value' to the bundles which |
||||
* have the given field. |
||||
*/ |
||||
protected function mapUseStates(): \Generator { |
||||
$this->getMediaBundleOptions(); |
||||
foreach (array_keys(array_filter($this->mediaBundleUsageField)) as $bundle) { |
||||
yield ['value' => $bundle]; |
||||
} |
||||
} |
||||
|
||||
/** |
||||
* {@inheritdoc} |
||||
*/ |
||||
public function buildForm(array $form, FormStateInterface $form_state) { |
||||
$this->cacheableMetadata = CacheableMetadata::createFromRenderArray($form) |
||||
->addCacheContexts([ |
||||
'url', |
||||
'url.query_args', |
||||
]); |
||||
$cached_values = $form_state->getTemporaryValue('wizard'); |
||||
|
||||
$form['media_type'] = [ |
||||
'#type' => 'select', |
||||
'#title' => $this->t('Media Type'), |
||||
'#description' => $this->t('Each media created will have this type.'), |
||||
'#empty_value' => '', |
||||
'#default_value' => $cached_values['media_type'] ?? '', |
||||
'#options' => $this->getMediaBundleOptions(), |
||||
'#required' => TRUE, |
||||
]; |
||||
$use_states = iterator_to_array($this->mapUseStates()); |
||||
$form['use'] = [ |
||||
'#type' => 'checkboxes', |
||||
'#title' => $this->t('Usage'), |
||||
'#description' => $this->t('Defined by <a target="_blank" href=":url">Portland Common Data Model: Use Extension</a>. "Original File" will trigger creation of derivatives.', [ |
||||
':url' => 'https://pcdm.org/2015/05/12/use', |
||||
]), |
||||
'#options' => iterator_to_array($this->getMediaUseOptions()), |
||||
'#default_value' => $cached_values['use'] ?? [], |
||||
'#states' => [ |
||||
'visible' => [ |
||||
':input[name="media_type"]' => $use_states, |
||||
], |
||||
'required' => [ |
||||
':input[name="media_type"]' => $use_states, |
||||
], |
||||
], |
||||
]; |
||||
|
||||
$this->cacheableMetadata->applyTo($form); |
||||
return $form; |
||||
} |
||||
|
||||
/** |
||||
* Helper; enumerate keys to persist in form state. |
||||
* |
||||
* @return string[] |
||||
* The keys to be persisted in our temp value in form state. |
||||
*/ |
||||
protected static function keysToSave() : array { |
||||
return [ |
||||
'media_type', |
||||
'use', |
||||
]; |
||||
} |
||||
|
||||
/** |
||||
* {@inheritdoc} |
||||
*/ |
||||
public function submitForm(array &$form, FormStateInterface $form_state) { |
||||
$cached_values = $form_state->getTemporaryValue('wizard'); |
||||
foreach (static::keysToSave() as $key) { |
||||
$cached_values[$key] = $form_state->getValue($key); |
||||
} |
||||
$form_state->setTemporaryValue('wizard', $cached_values); |
||||
} |
||||
|
||||
} |
@ -0,0 +1,58 @@
|
||||
<?php |
||||
|
||||
namespace Drupal\islandora\Form\AddChildrenWizard; |
||||
|
||||
use Drupal\Core\Entity\EntityTypeManagerInterface; |
||||
use Drupal\media\MediaTypeInterface; |
||||
|
||||
/** |
||||
* Media type lookup helper trait. |
||||
*/ |
||||
trait MediaTypeTrait { |
||||
|
||||
/** |
||||
* The entity type manager service. |
||||
* |
||||
* @var \Drupal\Core\Entity\EntityTypeManagerInterface|null |
||||
*/ |
||||
protected ?EntityTypeManagerInterface $entityTypeManager = NULL; |
||||
|
||||
/** |
||||
* Helper; get media type, given our required values. |
||||
* |
||||
* @param array $values |
||||
* An associative array which must contain at least: |
||||
* - media_type: The machine name of the media type to load. |
||||
* |
||||
* @return \Drupal\media\MediaTypeInterface |
||||
* The loaded media type. |
||||
* |
||||
* @throws \Drupal\Component\Plugin\Exception\InvalidPluginDefinitionException |
||||
* @throws \Drupal\Component\Plugin\Exception\PluginNotFoundException |
||||
*/ |
||||
protected function getMediaType(array $values): MediaTypeInterface { |
||||
return $this->entityTypeManager()->getStorage('media_type')->load($values['media_type']); |
||||
} |
||||
|
||||
/** |
||||
* Lazy-initialization of the entity type manager service. |
||||
* |
||||
* @return \Drupal\Core\Entity\EntityTypeManagerInterface |
||||
* The entity type manager service. |
||||
*/ |
||||
protected function entityTypeManager() : EntityTypeManagerInterface { |
||||
if ($this->entityTypeManager === NULL) { |
||||
$this->setEntityTypeManager(\Drupal::service('entity_type.manager')); |
||||
} |
||||
return $this->entityTypeManager; |
||||
} |
||||
|
||||
/** |
||||
* Setter for the entity type manager service. |
||||
*/ |
||||
public function setEntityTypeManager(EntityTypeManagerInterface $entity_type_manager) : self { |
||||
$this->entityTypeManager = $entity_type_manager; |
||||
return $this; |
||||
} |
||||
|
||||
} |
@ -0,0 +1,40 @@
|
||||
<?php |
||||
|
||||
namespace Drupal\islandora\Form\AddChildrenWizard; |
||||
|
||||
use Drupal\Component\Plugin\PluginManagerInterface; |
||||
use Drupal\Core\Field\FieldDefinitionInterface; |
||||
use Drupal\Core\Field\WidgetInterface; |
||||
|
||||
/** |
||||
* Wizard/widget lookup helper trait. |
||||
*/ |
||||
trait WizardTrait { |
||||
|
||||
use FieldTrait; |
||||
|
||||
/** |
||||
* The widget plugin manager service. |
||||
* |
||||
* @var \Drupal\Core\Field\WidgetPluginManager |
||||
*/ |
||||
protected PluginManagerInterface $widgetPluginManager; |
||||
|
||||
/** |
||||
* Helper; get the base widget for the given field. |
||||
* |
||||
* @param \Drupal\Core\Field\FieldDefinitionInterface $field |
||||
* The field for which get obtain the widget. |
||||
* |
||||
* @return \Drupal\Core\Field\WidgetInterface |
||||
* The widget. |
||||
*/ |
||||
protected function getWidget(FieldDefinitionInterface $field): WidgetInterface { |
||||
return $this->widgetPluginManager->getInstance([ |
||||
'field_definition' => $field, |
||||
'form_mode' => 'default', |
||||
'prepare' => TRUE, |
||||
]); |
||||
} |
||||
|
||||
} |
Loading…
Reference in new issue