View source
<?php
namespace Drupal\inline_entity_form\Plugin\Field\FieldWidget;
use Drupal\Core\Entity\EntityDisplayRepositoryInterface;
use Drupal\Core\Entity\EntityInterface;
use Drupal\Core\Entity\EntityTypeBundleInfoInterface;
use Drupal\Core\Entity\EntityTypeManagerInterface;
use Drupal\Core\Field\FieldDefinitionInterface;
use Drupal\Core\Field\FieldItemListInterface;
use Drupal\Core\Field\WidgetBase;
use Drupal\Core\Form\FormStateInterface;
use Drupal\Core\Plugin\ContainerFactoryPluginInterface;
use Drupal\inline_entity_form\TranslationHelper;
use Symfony\Component\DependencyInjection\ContainerInterface;
abstract class InlineEntityFormBase extends WidgetBase implements ContainerFactoryPluginInterface {
protected $iefId;
protected $entityTypeBundleInfo;
protected $entityTypeManager;
protected $inlineFormHandler;
protected $entityDisplayRepository;
public function __construct($plugin_id, $plugin_definition, FieldDefinitionInterface $field_definition, array $settings, array $third_party_settings, EntityTypeBundleInfoInterface $entity_type_bundle_info, EntityTypeManagerInterface $entity_type_manager, EntityDisplayRepositoryInterface $entity_display_repository) {
parent::__construct($plugin_id, $plugin_definition, $field_definition, $settings, $third_party_settings);
$this->entityTypeBundleInfo = $entity_type_bundle_info;
$this->entityTypeManager = $entity_type_manager;
$this->entityDisplayRepository = $entity_display_repository;
$this
->createInlineFormHandler();
}
public static function create(ContainerInterface $container, array $configuration, $plugin_id, $plugin_definition) {
return new static($plugin_id, $plugin_definition, $configuration['field_definition'], $configuration['settings'], $configuration['third_party_settings'], $container
->get('entity_type.bundle.info'), $container
->get('entity_type.manager'), $container
->get('entity_display.repository'));
}
protected function createInlineFormHandler() {
if (!isset($this->inlineFormHandler)) {
$target_type = $this
->getFieldSetting('target_type');
$this->inlineFormHandler = $this->entityTypeManager
->getHandler($target_type, 'inline_form');
}
}
public function __sleep() {
$keys = array_diff(parent::__sleep(), [
'inlineFormHandler',
]);
return $keys;
}
public function __wakeup() {
parent::__wakeup();
$this
->createInlineFormHandler();
}
protected function setIefId($ief_id) {
$this->iefId = $ief_id;
}
protected function getIefId() {
return $this->iefId;
}
protected function makeIefId(array $parents) {
$iefId = implode('-', $parents);
$iefId = preg_replace('#-inline_entity_form-entities-([0-9]+)-form-#', '-$1-', $iefId);
return $iefId;
}
protected function getTargetBundles() {
$settings = $this
->getFieldSettings();
if (!empty($settings['handler_settings']['target_bundles'])) {
$target_bundles = array_values($settings['handler_settings']['target_bundles']);
$existing_bundles = array_keys($this->entityTypeBundleInfo
->getBundleInfo($settings['target_type']));
$target_bundles = array_intersect($target_bundles, $existing_bundles);
}
else {
$target_bundles = array_keys($this->entityTypeBundleInfo
->getBundleInfo($settings['target_type']));
}
return $target_bundles;
}
protected function getCreateBundles() {
$create_bundles = [];
foreach ($this
->getTargetBundles() as $bundle) {
if ($this
->getAccessHandler()
->createAccess($bundle)) {
$create_bundles[] = $bundle;
}
}
return $create_bundles;
}
public static function defaultSettings() {
return [
'form_mode' => 'default',
'revision' => FALSE,
'override_labels' => FALSE,
'label_singular' => '',
'label_plural' => '',
'collapsible' => FALSE,
'collapsed' => FALSE,
];
}
public function settingsForm(array $form, FormStateInterface $form_state) {
$entity_type_id = $this
->getFieldSetting('target_type');
$states_prefix = 'fields[' . $this->fieldDefinition
->getName() . '][settings_edit_form][settings]';
$element = [];
$element['form_mode'] = [
'#type' => 'select',
'#title' => $this
->t('Form mode'),
'#default_value' => $this
->getSetting('form_mode'),
'#options' => $this->entityDisplayRepository
->getFormModeOptions($entity_type_id),
'#required' => TRUE,
];
$element['revision'] = [
'#type' => 'checkbox',
'#title' => $this
->t('Create new revision'),
'#default_value' => $this
->getSetting('revision'),
];
$element['override_labels'] = [
'#type' => 'checkbox',
'#title' => $this
->t('Override labels'),
'#default_value' => $this
->getSetting('override_labels'),
];
$element['label_singular'] = [
'#type' => 'textfield',
'#title' => $this
->t('Singular label'),
'#default_value' => $this
->getSetting('label_singular'),
'#states' => [
'visible' => [
':input[name="' . $states_prefix . '[override_labels]"]' => [
'checked' => TRUE,
],
],
],
];
$element['label_plural'] = [
'#type' => 'textfield',
'#title' => $this
->t('Plural label'),
'#default_value' => $this
->getSetting('label_plural'),
'#states' => [
'visible' => [
':input[name="' . $states_prefix . '[override_labels]"]' => [
'checked' => TRUE,
],
],
],
];
$element['collapsible'] = [
'#type' => 'checkbox',
'#title' => $this
->t('Collapsible'),
'#default_value' => $this
->getSetting('collapsible'),
];
$element['collapsed'] = [
'#type' => 'checkbox',
'#title' => $this
->t('Collapsed by default'),
'#default_value' => $this
->getSetting('collapsed'),
'#states' => [
'visible' => [
':input[name="' . $states_prefix . '[collapsible]"]' => [
'checked' => TRUE,
],
],
],
];
return $element;
}
public function settingsSummary() {
$summary = [];
if ($entity_form_mode = $this
->getEntityFormMode()) {
$form_mode_label = $entity_form_mode
->label();
}
else {
$form_mode_label = $this
->t('Default');
}
$summary[] = $this
->t('Form mode: @mode', [
'@mode' => $form_mode_label,
]);
if ($this
->getSetting('override_labels')) {
$summary[] = $this
->t('Overriden labels are used: %singular and %plural', [
'%singular' => $this
->getSetting('label_singular'),
'%plural' => $this
->getSetting('label_plural'),
]);
}
else {
$summary[] = $this
->t('Default labels are used.');
}
if ($this
->getSetting('revision')) {
$summary[] = $this
->t('Create new revision');
}
if ($this
->getSetting('collapsible')) {
$summary[] = $this
->t($this
->getSetting('collapsed') ? 'Collapsible, collapsed by default' : 'Collapsible');
}
return $summary;
}
protected function getEntityTypeLabels() {
if ($this
->getSetting('override_labels')) {
return [
'singular' => $this
->getSetting('label_singular'),
'plural' => $this
->getSetting('label_plural'),
];
}
else {
$this
->createInlineFormHandler();
return $this->inlineFormHandler
->getEntityTypeLabels();
}
}
protected function canBuildForm(FormStateInterface $form_state) {
if ($this
->isDefaultValueWidget($form_state)) {
return FALSE;
}
if (!$this->inlineFormHandler) {
return FALSE;
}
return TRUE;
}
protected function prepareFormState(FormStateInterface $form_state, FieldItemListInterface $items, $translating = FALSE) {
$widget_state = $form_state
->get([
'inline_entity_form',
$this->iefId,
]);
if (empty($widget_state)) {
$widget_state = [
'instance' => $this->fieldDefinition,
'form' => NULL,
'delete' => [],
'entities' => [],
];
foreach ($items
->referencedEntities() as $delta => $entity) {
if ($translating) {
$entity = TranslationHelper::prepareEntity($entity, $form_state);
}
$widget_state['entities'][$delta] = [
'entity' => $entity,
'weight' => $delta,
'form' => NULL,
'needs_save' => $entity
->isNew(),
];
}
$form_state
->set([
'inline_entity_form',
$this->iefId,
], $widget_state);
}
}
protected function getInlineEntityForm($operation, $bundle, $langcode, $delta, array $parents, EntityInterface $entity = NULL) {
$element = [
'#type' => 'inline_entity_form',
'#entity_type' => $this
->getFieldSetting('target_type'),
'#bundle' => $bundle,
'#langcode' => $langcode,
'#default_value' => $entity,
'#op' => $operation,
'#form_mode' => $this
->getSetting('form_mode'),
'#revision' => $this
->getSetting('revision'),
'#save_entity' => FALSE,
'#ief_row_delta' => $delta,
'#parents' => $parents,
'#ief_labels' => $this
->getEntityTypeLabels(),
'#ief_id' => $this
->getIefId(),
];
return $element;
}
protected function isTranslating(FormStateInterface $form_state) {
if (TranslationHelper::isTranslating($form_state)) {
$translation_manager = \Drupal::service('content_translation.manager');
$target_type = $this
->getFieldSetting('target_type');
foreach ($this
->getTargetBundles() as $bundle) {
if ($translation_manager
->isEnabled($target_type, $bundle)) {
return TRUE;
}
}
}
return FALSE;
}
public static function removeTranslatabilityClue(array $element, FormStateInterface $form_state) {
$element['#title'] = $element['#field_title'];
return $element;
}
public static function addIefSubmitCallbacks($element) {
$element['#ief_element_submit'][] = [
get_called_class(),
'submitSaveEntity',
];
return $element;
}
public static function submitSaveEntity($entity_form, FormStateInterface $form_state) {
$ief_id = $entity_form['#ief_id'];
$entity = $entity_form['#entity'];
if (in_array($entity_form['#op'], [
'add',
'duplicate',
])) {
$weight = 0;
$entities = $form_state
->get([
'inline_entity_form',
$ief_id,
'entities',
]);
if (!empty($entities)) {
$weight = max(array_keys($entities)) + 1;
}
$entities[] = [
'entity' => $entity,
'weight' => $weight,
'form' => NULL,
'needs_save' => TRUE,
];
$form_state
->set([
'inline_entity_form',
$ief_id,
'entities',
], $entities);
}
else {
$delta = $entity_form['#ief_row_delta'];
$entities = $form_state
->get([
'inline_entity_form',
$ief_id,
'entities',
]);
$entities[$delta]['entity'] = $entity;
$entities[$delta]['needs_save'] = TRUE;
$form_state
->set([
'inline_entity_form',
$ief_id,
'entities',
], $entities);
}
}
public function calculateDependencies() {
$dependencies = parent::calculateDependencies();
if ($entity_form_mode = $this
->getEntityFormMode()) {
$dependencies['config'][] = $entity_form_mode
->getConfigDependencyName();
}
return $dependencies;
}
protected function getEntityFormMode() {
$form_mode = $this
->getSetting('form_mode');
if ($form_mode != 'default') {
$entity_type_id = $this
->getFieldSetting('target_type');
return $this->entityTypeManager
->getStorage('entity_form_mode')
->load($entity_type_id . '.' . $form_mode);
}
return NULL;
}
protected function getAccessHandler() {
$entity_type_id = $this
->getFieldSetting('target_type');
return $this->entityTypeManager
->getAccessControlHandler($entity_type_id);
}
public function form(FieldItemListInterface $items, array &$form, FormStateInterface $form_state, $get_delta = NULL) {
if ($this
->canBuildForm($form_state)) {
return parent::form($items, $form, $form_state, $get_delta);
}
return [];
}
protected function canAddNew() {
$create_bundles = $this
->getCreateBundles();
return !empty($create_bundles);
}
}