use Symfony\Component\Validator\ConstraintViolation;
use Symfony\Component\Validator\ConstraintViolationListInterface;
use Drupal\Core\Extension\ModuleHandlerInterface;
+use Drupal\Core\Session\AccountInterface;
/**
* Plugin implementation of the 'entity_reference' widget for entity browser.
*/
protected $moduleHandler;
+ /**
+ * The current user.
+ *
+ * @var \Drupal\Core\Session\AccountInterface
+ */
+ protected $currentUser;
+
/**
* Constructs widget plugin.
*
* Field widget display plugin manager.
* @param \Drupal\Core\Extension\ModuleHandlerInterface $module_handler
* The module handler service.
+ * @param \Drupal\Core\Session\AccountInterface $current_user
+ * The current user.
*/
- public function __construct($plugin_id, $plugin_definition, FieldDefinitionInterface $field_definition, array $settings, array $third_party_settings, EntityTypeManagerInterface $entity_type_manager, EventDispatcherInterface $event_dispatcher, FieldWidgetDisplayManager $field_display_manager, ModuleHandlerInterface $module_handler) {
+ public function __construct($plugin_id, $plugin_definition, FieldDefinitionInterface $field_definition, array $settings, array $third_party_settings, EntityTypeManagerInterface $entity_type_manager, EventDispatcherInterface $event_dispatcher, FieldWidgetDisplayManager $field_display_manager, ModuleHandlerInterface $module_handler, AccountInterface $current_user) {
parent::__construct($plugin_id, $plugin_definition, $field_definition, $settings, $third_party_settings);
$this->entityTypeManager = $entity_type_manager;
$this->fieldDisplayManager = $field_display_manager;
$this->moduleHandler = $module_handler;
+ $this->currentUser = $current_user;
}
/**
$container->get('entity_type.manager'),
$container->get('event_dispatcher'),
$container->get('plugin.manager.entity_browser.field_widget_display'),
- $container->get('module_handler')
+ $container->get('module_handler'),
+ $container->get('current_user')
);
}
* {@inheritdoc}
*/
public static function defaultSettings() {
- return array(
+ return [
'entity_browser' => NULL,
'open' => FALSE,
'field_widget_display' => 'label',
'field_widget_edit' => TRUE,
'field_widget_remove' => TRUE,
+ 'field_widget_replace' => FALSE,
'field_widget_display_settings' => [],
'selection_mode' => EntityBrowserElement::SELECTION_MODE_APPEND,
- ) + parent::defaultSettings();
+ ] + parent::defaultSettings();
}
/**
'#default_value' => $this->getSetting('field_widget_display'),
'#options' => $displays,
'#ajax' => [
- 'callback' => array($this, 'updateSettingsAjax'),
+ 'callback' => [$this, 'updateSettingsAjax'],
'wrapper' => $id,
],
];
'#default_value' => $this->getSetting('field_widget_remove'),
];
+ $element['field_widget_replace'] = [
+ '#title' => $this->t('Display Replace button'),
+ '#description' => $this->t('This button will only be displayed if there is a single entity in the current selection.'),
+ '#type' => 'checkbox',
+ '#default_value' => $this->getSetting('field_widget_replace'),
+ ];
+
$element['open'] = [
'#title' => $this->t('Show widget details as open by default'),
'#description' => $this->t('If marked, the fieldset container that wraps the browser on the entity form will be loaded initially expanded.'),
// Enable entity browser if requirements for that are fulfilled.
if (EntityBrowserElement::isEntityBrowserAvailable($selection_mode, $cardinality, count($ids))) {
+ $persistentData = $this->getPersistentData();
+
$element['entity_browser'] = [
'#type' => 'entity_browser',
'#entity_browser' => $this->getSetting('entity_browser'),
'#cardinality' => $cardinality,
'#selection_mode' => $selection_mode,
'#default_value' => $entities,
- '#entity_browser_validators' => ['entity_type' => ['type' => $entity_type]],
+ '#entity_browser_validators' => $persistentData['validators'],
+ '#widget_context' => $persistentData['widget_context'],
'#custom_hidden_id' => $hidden_id,
'#process' => [
['\Drupal\entity_browser\Element\EntityBrowserElement', 'processEntityBrowser'],
[get_called_class(), 'processEntityBrowser'],
],
];
-
}
+
$element['#attached']['library'][] = 'entity_browser/entity_reference';
$field_parents = $element['#field_parents'];
*/
public static function updateWidgetCallback(array &$form, FormStateInterface $form_state) {
$trigger = $form_state->getTriggeringElement();
+ $reopen_browser = FALSE;
// AJAX requests can be triggered by hidden "target_id" element when
// entities are added or by one of the "Remove" buttons. Depending on that
// we need to figure out where root of the widget is in the form structure
// and use this information to return correct part of the form.
+ $parents = [];
if (!empty($trigger['#ajax']['event']) && $trigger['#ajax']['event'] == 'entity_browser_value_updated') {
$parents = array_slice($trigger['#array_parents'], 0, -1);
}
elseif ($trigger['#type'] == 'submit' && strpos($trigger['#name'], '_remove_')) {
$parents = array_slice($trigger['#array_parents'], 0, -static::$deleteDepth);
}
+ elseif ($trigger['#type'] == 'submit' && strpos($trigger['#name'], '_replace_')) {
+ $parents = array_slice($trigger['#array_parents'], 0, -static::$deleteDepth);
+ // We need to re-open the browser. Instead of just passing "TRUE", send
+ // to the JS the unique part of the button's name that needs to be clicked
+ // on to relaunch the browser.
+ $reopen_browser = implode("-", array_slice($trigger['#parents'], 0, -static::$deleteDepth));
+ }
- return NestedArray::getValue($form, $parents);
+ $parents = NestedArray::getValue($form, $parents);
+ $parents['#attached']['drupalSettings']['entity_browser_reopen_browser'] = $reopen_browser;
+ return $parents;
}
/**
$this->getSetting('field_widget_display_settings') + ['entity_type' => $this->fieldDefinition->getFieldStorageDefinition()->getSetting('target_type')]
);
+ $classes = ['entities-list'];
+ if ($this->fieldDefinition->getFieldStorageDefinition()->getCardinality() != 1) {
+ $classes[] = 'sortable';
+ }
+
+ // The "Replace" button will only be shown if this setting is enabled in the
+ // widget, and there is only one entity in the current selection.
+ $replace_button_access = $this->getSetting('field_widget_replace') && (count($entities) === 1);
+
return [
'#theme_wrappers' => ['container'],
- '#attributes' => ['class' => ['entities-list']],
+ '#attributes' => ['class' => $classes],
'items' => array_map(
- function (ContentEntityInterface $entity, $row_id) use ($field_widget_display, $details_id, $field_parents) {
+ function (ContentEntityInterface $entity, $row_id) use ($field_widget_display, $details_id, $field_parents, $replace_button_access) {
$display = $field_widget_display->view($entity);
- $edit_button_access = $this->getSetting('field_widget_edit');
+ $edit_button_access = $this->getSetting('field_widget_edit') && $entity->access('update', $this->currentUser);
if ($entity->getEntityTypeId() == 'file') {
// On file entities, the "edit" button shouldn't be visible unless
// the module "file_entity" is present, which will allow them to be
'#attributes' => [
'data-entity-id' => $entity->getEntityTypeId() . ':' . $entity->id(),
'data-row-id' => $row_id,
+ 'class' => ['remove-button'],
],
'#access' => (bool) $this->getSetting('field_widget_remove'),
],
+ 'replace_button' => [
+ '#type' => 'submit',
+ '#value' => $this->t('Replace'),
+ '#ajax' => [
+ 'callback' => [get_class($this), 'updateWidgetCallback'],
+ 'wrapper' => $details_id,
+ ],
+ '#submit' => [[get_class($this), 'removeItemSubmit']],
+ '#name' => $this->fieldDefinition->getName() . '_replace_' . $entity->id() . '_' . $row_id . '_' . md5(json_encode($field_parents)),
+ '#limit_validation_errors' => [array_merge($field_parents, [$this->fieldDefinition->getName()])],
+ '#attributes' => [
+ 'data-entity-id' => $entity->getEntityTypeId() . ':' . $entity->id(),
+ 'data-row-id' => $row_id,
+ 'class' => ['replace-button'],
+ ],
+ '#access' => $replace_button_access,
+ ],
'edit_button' => [
'#type' => 'submit',
'#value' => $this->t('Edit'),
],
],
],
+ '#attributes' => [
+ 'class' => ['edit-button'],
+ ],
'#access' => $edit_button_access,
],
];
'validators' => [
'entity_type' => ['type' => $this->fieldDefinition->getFieldStorageDefinition()->getSetting('target_type')],
],
+ 'widget_context' => [],
];
}