Loading modules/custom_elements_ui/custom_elements_ui.services.yml +0 −4 Original line number Diff line number Diff line Loading @@ -4,7 +4,3 @@ services: arguments: [ '@entity_type.manager' ] tags: - { name: event_subscriber } custom_elements_ui.processor.default_content_entity_ui: class: Drupal\custom_elements_ui\Processor\DefaultContentEntityUiProcessor tags: - { name: custom_elements_processor, priority: 100 } modules/custom_elements_ui/src/Form/EntityCustomElementsDisplayForm.php +25 −52 Original line number Diff line number Diff line Loading @@ -78,22 +78,31 @@ class EntityCustomElementsDisplayForm extends EntityDisplayFormBase { ], ]; // Add custom formatter field with needed options. $formatter_options = [ 'auto' => $this->t('Auto'), 'raw' => $this->t('Raw'), ]; $formatters = [ 'formatter' => [ '#type' => 'select', '#title' => $this->t('Formatter'), '#title_display' => 'invisible', '#options' => $formatter_options, '#default_value' => $display_options['type'] ?? 'auto', ], ]; // Insert additional fields. $label_position = array_search('plugin', array_keys($field_row)); $field_row = array_slice($field_row, 0, $label_position, TRUE) + $label + array_slice($field_row, $label_position, count($field_row) - 1, TRUE); $field_row = array_slice($field_row, 0, $label_position + 1, TRUE) + $is_slot + array_slice($field_row, $label_position, count($field_row) - 1, TRUE); $field_row = array_slice($field_row, 0, $label_position + 2, TRUE) + $formatters + array_slice($field_row, $label_position, count($field_row) - 1, TRUE); // Update the (invisible) title of the 'plugin' column. $field_row['plugin']['#title'] = $this->t('Formatter for @title', ['@title' => $field_definition->getLabel()]); // @todo Activate when implemented. $field_row['plugin']['#disabled'] = TRUE; $field_row["settings_edit"]['#access'] = FALSE; // @todo Needed? if (!empty($field_row['plugin']['settings_edit_form']) && ($plugin = $this->entity->getRenderer($field_name))) { $plugin_type_info = $plugin->getPluginDefinition(); $field_row['plugin']['settings_edit_form']['label']['#markup'] = $this->t('Format settings:') . ' <span class="plugin-name">' . $plugin_type_info['label'] . '</span>'; } // Hide plugin field as it was replaced with custom one. $field_row['plugin']['#access'] = FALSE; $field_row['settings_edit']['#access'] = FALSE; $field_row['settings_summary']['#access'] = FALSE; return $field_row; } Loading @@ -112,11 +121,6 @@ class EntityCustomElementsDisplayForm extends EntityDisplayFormBase { } $ce_fields = $entity->getThirdPartySetting('custom_elements', 'custom_element_fields', []); if ($this->entity instanceof EntityWithPluginCollectionInterface) { // Do not manually update values represented by plugin collections. $form_values = array_diff_key($form_values, $this->entity->getPluginCollections()); } // Collect data for 'regular' fields. foreach ($form['#fields'] as $field_name) { $values = $form_values['fields'][$field_name]; Loading @@ -125,17 +129,7 @@ class EntityCustomElementsDisplayForm extends EntityDisplayFormBase { } else { $options = $ce_fields[$field_name] ?? []; // Update field settings only if the submit handler told us to. if ($form_state->get('plugin_settings_update') === $field_name) { // Only store settings actually used by the selected plugin. $default_settings = $this->pluginManager->getDefaultSettings($options['type']); $options['settings'] = isset($values['settings_edit_form']['settings']) ? array_intersect_key($values['settings_edit_form']['settings'], $default_settings) : []; $options['third_party_settings'] = $values['settings_edit_form']['third_party_settings'] ?? []; $form_state->set('plugin_settings_update', NULL); } $options['type'] = $values['type']; $options['type'] = $values['formatter'] ?? 'auto'; $options['weight'] = (int) $values['weight']; $options['region'] = $values['region']; // Only formatters have configurable label visibility. Loading Loading @@ -197,7 +191,8 @@ class EntityCustomElementsDisplayForm extends EntityDisplayFormBase { $bundle = $route_parameters['bundle']; } return $this->entityTypeManager->getStorage('entity_view_display')->load($route_parameters['entity_type_id'] . '.' . $bundle . '.' . $route_parameters['view_mode_name']); return $this->entityTypeManager->getStorage('entity_view_display') ->load($route_parameters['entity_type_id'] . '.' . $bundle . '.' . $route_parameters['view_mode_name']); } /** Loading @@ -211,8 +206,7 @@ class EntityCustomElementsDisplayForm extends EntityDisplayFormBase { * {@inheritdoc} */ protected function getDefaultPlugin($field_type) { // @todo Implement with ce formatters. return NULL; return 'auto'; } /** Loading Loading @@ -254,34 +248,13 @@ class EntityCustomElementsDisplayForm extends EntityDisplayFormBase { * {@inheritdoc} */ protected function thirdPartySettingsForm(PluginSettingsInterface $plugin, FieldDefinitionInterface $field_definition, array $form, FormStateInterface $form_state) { $settings_form = []; // Invoke hook_field_formatter_third_party_settings_form(), keying resulting // subforms by module name. $this->moduleHandler->invokeAllWith( 'field_formatter_third_party_settings_form', function (callable $hook, string $module) use (&$settings_form, &$plugin, &$field_definition, &$form, &$form_state) { $settings_form[$module] = $hook( $plugin, $field_definition, $this->entity->getMode(), $form, $form_state, ); } ); return $settings_form; return []; } /** * {@inheritdoc} */ protected function alterSettingsSummary(array &$summary, PluginSettingsInterface $plugin, FieldDefinitionInterface $field_definition) { $context = [ 'formatter' => $plugin, 'field_definition' => $field_definition, 'view_mode' => $this->entity->getMode(), ]; $this->moduleHandler->alter('field_formatter_settings_summary', $summary, $context); } } src/Processor/DefaultContentEntityProcessor.php +85 −16 Original line number Diff line number Diff line Loading @@ -7,6 +7,8 @@ use Drupal\Core\Entity\Display\EntityViewDisplayInterface; use Drupal\Core\Entity\Entity\EntityViewDisplay; use Drupal\Core\Entity\EntityInterface; use Drupal\Core\Entity\EntityTypeManagerInterface; use Drupal\Core\Field\EntityReferenceFieldItemListInterface; use Drupal\Core\Field\FieldItemListInterface; use Drupal\Core\Render\BubbleableMetadata; use Drupal\Core\Render\Element; use Drupal\custom_elements\CustomElement; Loading Loading @@ -168,22 +170,16 @@ class DefaultContentEntityProcessor implements CustomElementProcessorInterface { $ce_display_fields = $display->getThirdPartySetting('custom_elements', 'custom_element_fields', []); foreach ($ce_display_fields as $field_name => $field_options) { if ($this->fieldIsAccessible($entity, $field_name, $custom_element)) { if ($field_options['is_slot']) { $nested_elements = []; foreach ($entity->get($field_name) as $field_item) { $nested_element = new CustomElement(); $nested_element->setTagPrefix('field'); $nested_element->setTag($entity->get($field_name)->getFieldDefinition()->getType()); // @todo Check if $display->id() returns expected value. $this->getCustomElementGenerator()->process($field_item, $nested_element, $display->id()); $nested_elements[] = $nested_element; } $custom_element->setSlotFromNestedElements($field_options['label'], $nested_elements); } else { $field_items = $entity->get($field_name); $property = $field_items->getFieldDefinition()->getFieldStorageDefinition()->getMainPropertyName(); $custom_element->setAttribute($field_options['label'], $field_items->{$property}); switch ($field_options['type']) { // @todo Move implementation to separate service/plugin. case 'auto': $this->processAuto($field_items, $custom_element, $field_options['is_slot'], $field_options['label'], $display->getMode()); break; case 'raw': default: $this->processRaw($field_items, $custom_element, $field_options['is_slot'], $field_options['label']); break; } } } Loading Loading @@ -225,4 +221,77 @@ class DefaultContentEntityProcessor implements CustomElementProcessorInterface { return $elements; } /** * Automatically process field items and adds to the custom element. * * @param \Drupal\Core\Field\FieldItemListInterface $field_items * Field item list object. * @param \Drupal\custom_elements\CustomElement $custom_element * The custom element to which to add it. * @param bool $is_slot * Whether it should be rendered as slot. * @param string $element_name * Configured element name. * @param string $view_mode * The current view-mode. */ protected function processAuto(FieldItemListInterface $field_items, CustomElement $custom_element, bool $is_slot, string $element_name, string $view_mode) { if ($is_slot) { $nested_elements = []; foreach ($field_items as $field_item) { $nested_element = new CustomElement(); $nested_element->setTagPrefix('field'); $nested_element->setTag($field_items->getFieldDefinition()->getType()); $this->getCustomElementGenerator()->process($field_item, $nested_element, $view_mode); $nested_elements[] = $nested_element; } $custom_element->setSlotFromNestedElements($element_name, $nested_elements); } else { if ($field_items instanceof EntityReferenceFieldItemListInterface) { $entities = $field_items->referencedEntities(); array_filter($entities, function ($entity) { return $entity->access('view'); }); $values = array_map(function ($entity) { return $entity->label(); }, $entities); } else { $property = $field_items->getFieldDefinition()->getFieldStorageDefinition()->getMainPropertyName(); $values = array_column($field_items->getValue(), $property); } if (count($values) === 1) { $values = reset($values); } $custom_element->setAttribute($element_name, $values); } } /** * Fetch raw field items data and adds to the custom element. * * @param \Drupal\Core\Field\FieldItemListInterface $field_items * Field item list object. * @param \Drupal\custom_elements\CustomElement $custom_element * The custom element to which to add it. * @param bool $is_slot * Whether it should be rendered as slot. * @param string $element_name * Configured element name. */ protected function processRaw(FieldItemListInterface $field_items, CustomElement $custom_element, bool $is_slot, string $element_name) { $property = $field_items->getFieldDefinition()->getFieldStorageDefinition()->getMainPropertyName(); $values = array_column($field_items->getValue(), $property); if (count($values) === 1) { $values = reset($values); } if ($is_slot) { $custom_element->addSlot($element_name, $values); } else { $custom_element->setAttribute($element_name, $values); } } } Loading
modules/custom_elements_ui/custom_elements_ui.services.yml +0 −4 Original line number Diff line number Diff line Loading @@ -4,7 +4,3 @@ services: arguments: [ '@entity_type.manager' ] tags: - { name: event_subscriber } custom_elements_ui.processor.default_content_entity_ui: class: Drupal\custom_elements_ui\Processor\DefaultContentEntityUiProcessor tags: - { name: custom_elements_processor, priority: 100 }
modules/custom_elements_ui/src/Form/EntityCustomElementsDisplayForm.php +25 −52 Original line number Diff line number Diff line Loading @@ -78,22 +78,31 @@ class EntityCustomElementsDisplayForm extends EntityDisplayFormBase { ], ]; // Add custom formatter field with needed options. $formatter_options = [ 'auto' => $this->t('Auto'), 'raw' => $this->t('Raw'), ]; $formatters = [ 'formatter' => [ '#type' => 'select', '#title' => $this->t('Formatter'), '#title_display' => 'invisible', '#options' => $formatter_options, '#default_value' => $display_options['type'] ?? 'auto', ], ]; // Insert additional fields. $label_position = array_search('plugin', array_keys($field_row)); $field_row = array_slice($field_row, 0, $label_position, TRUE) + $label + array_slice($field_row, $label_position, count($field_row) - 1, TRUE); $field_row = array_slice($field_row, 0, $label_position + 1, TRUE) + $is_slot + array_slice($field_row, $label_position, count($field_row) - 1, TRUE); $field_row = array_slice($field_row, 0, $label_position + 2, TRUE) + $formatters + array_slice($field_row, $label_position, count($field_row) - 1, TRUE); // Update the (invisible) title of the 'plugin' column. $field_row['plugin']['#title'] = $this->t('Formatter for @title', ['@title' => $field_definition->getLabel()]); // @todo Activate when implemented. $field_row['plugin']['#disabled'] = TRUE; $field_row["settings_edit"]['#access'] = FALSE; // @todo Needed? if (!empty($field_row['plugin']['settings_edit_form']) && ($plugin = $this->entity->getRenderer($field_name))) { $plugin_type_info = $plugin->getPluginDefinition(); $field_row['plugin']['settings_edit_form']['label']['#markup'] = $this->t('Format settings:') . ' <span class="plugin-name">' . $plugin_type_info['label'] . '</span>'; } // Hide plugin field as it was replaced with custom one. $field_row['plugin']['#access'] = FALSE; $field_row['settings_edit']['#access'] = FALSE; $field_row['settings_summary']['#access'] = FALSE; return $field_row; } Loading @@ -112,11 +121,6 @@ class EntityCustomElementsDisplayForm extends EntityDisplayFormBase { } $ce_fields = $entity->getThirdPartySetting('custom_elements', 'custom_element_fields', []); if ($this->entity instanceof EntityWithPluginCollectionInterface) { // Do not manually update values represented by plugin collections. $form_values = array_diff_key($form_values, $this->entity->getPluginCollections()); } // Collect data for 'regular' fields. foreach ($form['#fields'] as $field_name) { $values = $form_values['fields'][$field_name]; Loading @@ -125,17 +129,7 @@ class EntityCustomElementsDisplayForm extends EntityDisplayFormBase { } else { $options = $ce_fields[$field_name] ?? []; // Update field settings only if the submit handler told us to. if ($form_state->get('plugin_settings_update') === $field_name) { // Only store settings actually used by the selected plugin. $default_settings = $this->pluginManager->getDefaultSettings($options['type']); $options['settings'] = isset($values['settings_edit_form']['settings']) ? array_intersect_key($values['settings_edit_form']['settings'], $default_settings) : []; $options['third_party_settings'] = $values['settings_edit_form']['third_party_settings'] ?? []; $form_state->set('plugin_settings_update', NULL); } $options['type'] = $values['type']; $options['type'] = $values['formatter'] ?? 'auto'; $options['weight'] = (int) $values['weight']; $options['region'] = $values['region']; // Only formatters have configurable label visibility. Loading Loading @@ -197,7 +191,8 @@ class EntityCustomElementsDisplayForm extends EntityDisplayFormBase { $bundle = $route_parameters['bundle']; } return $this->entityTypeManager->getStorage('entity_view_display')->load($route_parameters['entity_type_id'] . '.' . $bundle . '.' . $route_parameters['view_mode_name']); return $this->entityTypeManager->getStorage('entity_view_display') ->load($route_parameters['entity_type_id'] . '.' . $bundle . '.' . $route_parameters['view_mode_name']); } /** Loading @@ -211,8 +206,7 @@ class EntityCustomElementsDisplayForm extends EntityDisplayFormBase { * {@inheritdoc} */ protected function getDefaultPlugin($field_type) { // @todo Implement with ce formatters. return NULL; return 'auto'; } /** Loading Loading @@ -254,34 +248,13 @@ class EntityCustomElementsDisplayForm extends EntityDisplayFormBase { * {@inheritdoc} */ protected function thirdPartySettingsForm(PluginSettingsInterface $plugin, FieldDefinitionInterface $field_definition, array $form, FormStateInterface $form_state) { $settings_form = []; // Invoke hook_field_formatter_third_party_settings_form(), keying resulting // subforms by module name. $this->moduleHandler->invokeAllWith( 'field_formatter_third_party_settings_form', function (callable $hook, string $module) use (&$settings_form, &$plugin, &$field_definition, &$form, &$form_state) { $settings_form[$module] = $hook( $plugin, $field_definition, $this->entity->getMode(), $form, $form_state, ); } ); return $settings_form; return []; } /** * {@inheritdoc} */ protected function alterSettingsSummary(array &$summary, PluginSettingsInterface $plugin, FieldDefinitionInterface $field_definition) { $context = [ 'formatter' => $plugin, 'field_definition' => $field_definition, 'view_mode' => $this->entity->getMode(), ]; $this->moduleHandler->alter('field_formatter_settings_summary', $summary, $context); } }
src/Processor/DefaultContentEntityProcessor.php +85 −16 Original line number Diff line number Diff line Loading @@ -7,6 +7,8 @@ use Drupal\Core\Entity\Display\EntityViewDisplayInterface; use Drupal\Core\Entity\Entity\EntityViewDisplay; use Drupal\Core\Entity\EntityInterface; use Drupal\Core\Entity\EntityTypeManagerInterface; use Drupal\Core\Field\EntityReferenceFieldItemListInterface; use Drupal\Core\Field\FieldItemListInterface; use Drupal\Core\Render\BubbleableMetadata; use Drupal\Core\Render\Element; use Drupal\custom_elements\CustomElement; Loading Loading @@ -168,22 +170,16 @@ class DefaultContentEntityProcessor implements CustomElementProcessorInterface { $ce_display_fields = $display->getThirdPartySetting('custom_elements', 'custom_element_fields', []); foreach ($ce_display_fields as $field_name => $field_options) { if ($this->fieldIsAccessible($entity, $field_name, $custom_element)) { if ($field_options['is_slot']) { $nested_elements = []; foreach ($entity->get($field_name) as $field_item) { $nested_element = new CustomElement(); $nested_element->setTagPrefix('field'); $nested_element->setTag($entity->get($field_name)->getFieldDefinition()->getType()); // @todo Check if $display->id() returns expected value. $this->getCustomElementGenerator()->process($field_item, $nested_element, $display->id()); $nested_elements[] = $nested_element; } $custom_element->setSlotFromNestedElements($field_options['label'], $nested_elements); } else { $field_items = $entity->get($field_name); $property = $field_items->getFieldDefinition()->getFieldStorageDefinition()->getMainPropertyName(); $custom_element->setAttribute($field_options['label'], $field_items->{$property}); switch ($field_options['type']) { // @todo Move implementation to separate service/plugin. case 'auto': $this->processAuto($field_items, $custom_element, $field_options['is_slot'], $field_options['label'], $display->getMode()); break; case 'raw': default: $this->processRaw($field_items, $custom_element, $field_options['is_slot'], $field_options['label']); break; } } } Loading Loading @@ -225,4 +221,77 @@ class DefaultContentEntityProcessor implements CustomElementProcessorInterface { return $elements; } /** * Automatically process field items and adds to the custom element. * * @param \Drupal\Core\Field\FieldItemListInterface $field_items * Field item list object. * @param \Drupal\custom_elements\CustomElement $custom_element * The custom element to which to add it. * @param bool $is_slot * Whether it should be rendered as slot. * @param string $element_name * Configured element name. * @param string $view_mode * The current view-mode. */ protected function processAuto(FieldItemListInterface $field_items, CustomElement $custom_element, bool $is_slot, string $element_name, string $view_mode) { if ($is_slot) { $nested_elements = []; foreach ($field_items as $field_item) { $nested_element = new CustomElement(); $nested_element->setTagPrefix('field'); $nested_element->setTag($field_items->getFieldDefinition()->getType()); $this->getCustomElementGenerator()->process($field_item, $nested_element, $view_mode); $nested_elements[] = $nested_element; } $custom_element->setSlotFromNestedElements($element_name, $nested_elements); } else { if ($field_items instanceof EntityReferenceFieldItemListInterface) { $entities = $field_items->referencedEntities(); array_filter($entities, function ($entity) { return $entity->access('view'); }); $values = array_map(function ($entity) { return $entity->label(); }, $entities); } else { $property = $field_items->getFieldDefinition()->getFieldStorageDefinition()->getMainPropertyName(); $values = array_column($field_items->getValue(), $property); } if (count($values) === 1) { $values = reset($values); } $custom_element->setAttribute($element_name, $values); } } /** * Fetch raw field items data and adds to the custom element. * * @param \Drupal\Core\Field\FieldItemListInterface $field_items * Field item list object. * @param \Drupal\custom_elements\CustomElement $custom_element * The custom element to which to add it. * @param bool $is_slot * Whether it should be rendered as slot. * @param string $element_name * Configured element name. */ protected function processRaw(FieldItemListInterface $field_items, CustomElement $custom_element, bool $is_slot, string $element_name) { $property = $field_items->getFieldDefinition()->getFieldStorageDefinition()->getMainPropertyName(); $values = array_column($field_items->getValue(), $property); if (count($values) === 1) { $values = reset($values); } if ($is_slot) { $custom_element->addSlot($element_name, $values); } else { $custom_element->setAttribute($element_name, $values); } } }