diff --git a/modules/ui_patterns_field_formatters/src/Plugin/Derivative/FieldPropertiesSourceSlotDeriver.php b/modules/ui_patterns_field_formatters/src/Plugin/Derivative/FieldFormatterSourceDeriver.php similarity index 88% rename from modules/ui_patterns_field_formatters/src/Plugin/Derivative/FieldPropertiesSourceSlotDeriver.php rename to modules/ui_patterns_field_formatters/src/Plugin/Derivative/FieldFormatterSourceDeriver.php index d71153807de524dc06d351a0f991e23403ee0112..02f32157bf1c495ec8c9570acdc7fa8474795cbb 100644 --- a/modules/ui_patterns_field_formatters/src/Plugin/Derivative/FieldPropertiesSourceSlotDeriver.php +++ b/modules/ui_patterns_field_formatters/src/Plugin/Derivative/FieldFormatterSourceDeriver.php @@ -8,6 +8,7 @@ use Drupal\Core\Field\FieldStorageDefinitionInterface; use Drupal\Core\Field\FormatterPluginManager; use Drupal\Core\TypedData\DataDefinitionInterface; use Drupal\Core\TypedData\TypedDataManagerInterface; +use Drupal\ui_patterns\Plugin\Derivative\FieldPropertiesSourceDeriverBase; use Drupal\ui_patterns\PropTypePluginManager; use Symfony\Component\DependencyInjection\ContainerInterface; @@ -17,7 +18,7 @@ use Symfony\Component\DependencyInjection\ContainerInterface; * @internal * Plugin derivers are internal. */ -class FieldPropertiesSourceSlotDeriver extends FieldPropertiesSourceDeriverBase { +class FieldFormatterSourceDeriver extends FieldPropertiesSourceDeriverBase { /** * Constructs new FieldBlockDeriver. @@ -71,12 +72,14 @@ class FieldPropertiesSourceSlotDeriver extends FieldPropertiesSourceDeriverBase "prop_types" => ["slot"], ] ); - $derivative['ui_patterns_field_formatter'] = array_merge($derivative['ui_patterns_field_formatter'], [ + $derivative['metadata'] = array_merge($derivative['metadata'], [ 'field_formatter' => TRUE, ]); $this->derivatives[$derivative['id']] = $derivative; } - parent::getDerivativeDefinitionsForField($derivative_for_this_field, $field_storage_definition); + // Those will be covered using convert mechanism + // parent::getDerivativeDefinitionsForField( + // $derivative_for_this_field, $field_storage_definition);. } /** diff --git a/modules/ui_patterns_field_formatters/src/Plugin/Field/FieldFormatter/ComponentFormatter.php b/modules/ui_patterns_field_formatters/src/Plugin/Field/FieldFormatter/ComponentFormatter.php index f0d7e6ffcd889c4749a7a49f76f3b03991279be8..7c245f148aaaad54e206010aa60bd5f742654aaf 100644 --- a/modules/ui_patterns_field_formatters/src/Plugin/Field/FieldFormatter/ComponentFormatter.php +++ b/modules/ui_patterns_field_formatters/src/Plugin/Field/FieldFormatter/ComponentFormatter.php @@ -7,7 +7,7 @@ namespace Drupal\ui_patterns_field_formatters\Plugin\Field\FieldFormatter; use Drupal\Core\Field\FieldDefinitionInterface; use Drupal\Core\Field\FieldItemListInterface; use Drupal\Core\Field\FieldStorageDefinitionInterface; -use Drupal\ui_patterns\SourcePluginBase; +use Drupal\ui_patterns\Plugin\Context\RequirementsContext; /** * Plugin implementation of the 'component_all' formatter. @@ -53,7 +53,7 @@ class ComponentFormatter extends ComponentFormatterBase { * Source contexts. */ protected function getComponentSourceContexts(): array { - return SourcePluginBase::addRequirementsToContext(parent::getComponentSourceContexts(), ["field_granularity:items"]); + return RequirementsContext::addToContext(["field_granularity:items"], parent::getComponentSourceContexts()); } } diff --git a/modules/ui_patterns_field_formatters/src/Plugin/Field/FieldFormatter/ComponentFormatterBase.php b/modules/ui_patterns_field_formatters/src/Plugin/Field/FieldFormatter/ComponentFormatterBase.php index 88d46f3a863559fde9326ea1ae1c86c540b07bd6..8807e613a23a8bb57b5e4debb2b46c412c3fed2e 100644 --- a/modules/ui_patterns_field_formatters/src/Plugin/Field/FieldFormatter/ComponentFormatterBase.php +++ b/modules/ui_patterns_field_formatters/src/Plugin/Field/FieldFormatter/ComponentFormatterBase.php @@ -4,13 +4,14 @@ declare(strict_types=1); namespace Drupal\ui_patterns_field_formatters\Plugin\Field\FieldFormatter; +use Drupal\Core\Entity\EntityInterface; use Drupal\Core\Field\FormatterBase; use Drupal\Core\Form\FormStateInterface; use Drupal\Core\Plugin\Context\Context; use Drupal\Core\Plugin\Context\ContextDefinition; use Drupal\Core\Plugin\Context\EntityContext; use Drupal\ui_patterns\Form\ComponentSettingsFormBuilderTrait; -use Drupal\ui_patterns\SourcePluginBase; +use Drupal\ui_patterns\Plugin\Context\RequirementsContext; use Symfony\Component\DependencyInjection\ContainerInterface; /** @@ -45,6 +46,13 @@ abstract class ComponentFormatterBase extends FormatterBase { */ protected $sampleEntityGenerator; + /** + * Entity Field Manager. + * + * @var \Drupal\Core\Entity\EntityFieldManagerInterface + */ + protected $entityFieldManager; + /** * The provided plugin contexts. * @@ -83,6 +91,7 @@ abstract class ComponentFormatterBase extends FormatterBase { $instance->contextRepository = $container->get('context.repository'); $instance->entityTypeManager = $container->get('entity_type.manager'); $instance->sampleEntityGenerator = $container->get('ui_patterns.sample_entity_generator'); + $instance->entityFieldManager = $container->get('entity_field.manager'); return $instance; } @@ -148,7 +157,7 @@ abstract class ComponentFormatterBase extends FormatterBase { // we properly get them especially source plugins // with context_requirements having field_granularity:item. if (is_array($this->context) && array_key_exists("context_requirements", $this->context) && $this->context["context_requirements"]->hasValue("field_granularity:item")) { - $injected_contexts = SourcePluginBase::addRequirementsToContext($injected_contexts, ["field_granularity:item"]); + $injected_contexts = RequirementsContext::addToContext(["field_granularity:item"], $injected_contexts); } return $this->componentSettingsForm($form, $form_state, $injected_contexts); } @@ -165,17 +174,12 @@ abstract class ComponentFormatterBase extends FormatterBase { $field_definition = $this->fieldDefinition; $entity_type_id = $field_definition->getTargetEntityTypeId(); - $contextEntityTypeDefinition = ContextDefinition::create('string'); - $contextEntityTypeDefinition->setLabel("entity_type_id"); - $contextEntityType = new Context($contextEntityTypeDefinition, $entity_type_id); - $contexts['entity_type_id'] = $contextEntityType; - $contextFieldNameDefinition = ContextDefinition::create('string'); $contextFieldNameDefinition->setLabel("field_name"); $contextFieldName = new Context($contextFieldNameDefinition, $field_definition->getName()); $contexts['field_name'] = $contextFieldName; - $contexts = SourcePluginBase::addRequirementsToContext($contexts, ["field_formatter"]); + $contexts = RequirementsContext::addToContext(["field_formatter"], $contexts); $contextBundleDefinition = ContextDefinition::create('string'); $contextBundleDefinition->setLabel("bundle"); @@ -183,12 +187,21 @@ abstract class ComponentFormatterBase extends FormatterBase { if (NULL === $bundle) { // Generate a default bundle when it is missing, // this covers contexts like the display of a field in a view. + // the bundle selected should have the field in defintion... $bundle = $entity_type_id; $bundle_entity_type = $this->entityTypeManager->getDefinition($entity_type_id)->getBundleEntityType(); if (NULL !== $bundle_entity_type) { $bunle_list = $this->entityTypeManager->getStorage($bundle_entity_type)->loadMultiple(); if (count($bunle_list) > 0) { - $bundle = array_values($bunle_list)[0]->id(); + foreach ($bunle_list as $bundle_entity) { + $bundle_to_test = $bundle_entity->id(); + $definitions = $this->entityFieldManager->getFieldDefinitions($entity_type_id, $bundle_to_test); + if (array_key_exists($field_definition->getName(), $definitions)) { + $bundle = $bundle_to_test; + break; + } + } + // $bundle = array_values($bunle_list)[0]->id(); } } } @@ -205,7 +218,12 @@ abstract class ComponentFormatterBase extends FormatterBase { } } - if (!array_key_exists("entity", $contexts)) { + if (!array_key_exists("entity", $contexts) || + (NULL === $contexts['entity']->getContextValue()) || + !($contexts['entity']->getContextValue() instanceof EntityInterface) || + ($contexts['entity']->getContextValue()->getEntityTypeId() !== $entity_type_id) || + ($contexts['entity']->getContextValue()->bundle() !== $bundle) + ) { $contexts['entity'] = EntityContext::fromEntity($this->sampleEntityGenerator->get($entity_type_id, $bundle)); } @@ -213,37 +231,38 @@ abstract class ComponentFormatterBase extends FormatterBase { } /** - * Alter the configuration of the mapping, like index and langcode. + * Store extra data in component configuration for each prop and slot source. * * @param array $specific_config * Array of specific configuration to insert. - * - * @return array - * The configuration array. */ - protected function setComponentSettingsExtra(array $specific_config): array { - $configuration = $this->getComponentSettings(); - if (!array_key_exists('ui_patterns', $configuration)) { - return $configuration; - } - if (!array_key_exists('props', $configuration['ui_patterns']) && !array_key_exists('slots', $configuration['ui_patterns'])) { - return $configuration; - } - // Loop on each ui patterns props. - $prop_ids = array_keys($configuration['ui_patterns']['props']); - foreach ($prop_ids as $prop_id) { - $configuration['ui_patterns']['props'][$prop_id]['source']['ui_patterns_field_formatter'] = $specific_config; - } - foreach ($configuration['ui_patterns']['slots'] as $slots_id => $slots) { - if (empty($slots['sources']) || !is_array($slots['sources'])) { - continue; + protected function setComponentSettingsExtra(array $specific_config): void { + $configuration = $this->getComponentConfiguration(); + $somethingDone = FALSE; + // Loop on each ui patterns props and slots. + if (array_key_exists('props', $configuration)) { + foreach ($configuration['props'] as $prop_id => &$prop_configuration) { + $prop_configuration['source']['extra'] = $specific_config; + $somethingDone = TRUE; } - foreach (array_keys($slots['sources']) as $source_id) { - $configuration['ui_patterns']['slots'][$slots_id]['sources'][$source_id]['source']['ui_patterns_field_formatter'] = $specific_config; + unset($prop_configuration); + } + if (array_key_exists('slots', $configuration)) { + foreach ($configuration['slots'] as $slots_id => &$slots) { + if (empty($slots['sources']) || !is_array($slots['sources'])) { + continue; + } + foreach ($slots['sources'] as $source_id => &$source_configuration) { + $source_configuration['source']['extra'] = $specific_config; + $somethingDone = TRUE; + } + unset($source_configuration); } + unset($slots); + } + if ($somethingDone) { + $this->setComponentConfiguration($configuration); } - $this->setComponentConfiguration($configuration['ui_patterns']); - return $configuration['ui_patterns']; } } diff --git a/modules/ui_patterns_field_formatters/src/Plugin/Field/FieldFormatter/ComponentPerItemFormatter.php b/modules/ui_patterns_field_formatters/src/Plugin/Field/FieldFormatter/ComponentPerItemFormatter.php index a6dedef601269277eac937fe0be1ab25b30f00ef..27256955cfed63d9ced765ef92a860ce770136a0 100644 --- a/modules/ui_patterns_field_formatters/src/Plugin/Field/FieldFormatter/ComponentPerItemFormatter.php +++ b/modules/ui_patterns_field_formatters/src/Plugin/Field/FieldFormatter/ComponentPerItemFormatter.php @@ -5,7 +5,7 @@ declare(strict_types=1); namespace Drupal\ui_patterns_field_formatters\Plugin\Field\FieldFormatter; use Drupal\Core\Field\FieldItemListInterface; -use Drupal\ui_patterns\SourcePluginBase; +use Drupal\ui_patterns\Plugin\Context\RequirementsContext; /** * Plugin implementation of the 'component_each' formatter. @@ -46,7 +46,7 @@ class ComponentPerItemFormatter extends ComponentFormatterBase { * Source contexts. */ protected function getComponentSourceContexts(): array { - return SourcePluginBase::addRequirementsToContext(parent::getComponentSourceContexts(), ["field_granularity:item"]); + return RequirementsContext::addToContext(["field_granularity:item"], parent::getComponentSourceContexts()); } } diff --git a/modules/ui_patterns_field_formatters/src/Plugin/UiPatterns/Source/FieldFormatterFormBase.php b/modules/ui_patterns_field_formatters/src/Plugin/UiPatterns/Source/FieldFormatterSource.php similarity index 76% rename from modules/ui_patterns_field_formatters/src/Plugin/UiPatterns/Source/FieldFormatterFormBase.php rename to modules/ui_patterns_field_formatters/src/Plugin/UiPatterns/Source/FieldFormatterSource.php index 32037673c89296c0dd24eee077f99238a437475f..fa0043524417617b4d2e84350f761b2f4d231e07 100644 --- a/modules/ui_patterns_field_formatters/src/Plugin/UiPatterns/Source/FieldFormatterFormBase.php +++ b/modules/ui_patterns_field_formatters/src/Plugin/UiPatterns/Source/FieldFormatterSource.php @@ -5,20 +5,31 @@ declare(strict_types=1); namespace Drupal\ui_patterns_field_formatters\Plugin\UiPatterns\Source; use Drupal\Component\Utility\Html; +use Drupal\Component\Utility\NestedArray; use Drupal\Core\Field\FieldDefinitionInterface; +use Drupal\Core\Field\FieldItemListInterface; use Drupal\Core\Field\FieldStorageDefinitionInterface; use Drupal\Core\Field\FieldTypePluginManagerInterface; use Drupal\Core\Field\FormatterInterface; use Drupal\Core\Field\FormatterPluginManager; use Drupal\Core\Form\FormStateInterface; use Drupal\Core\Logger\LoggerChannelTrait; +use Drupal\ui_patterns\Plugin\UiPatterns\Source\FieldPropertySourceBase; use Drupal\ui_patterns_field_formatters\Plugin\Field\FieldFormatter\ComponentFormatterBase; use Symfony\Component\DependencyInjection\ContainerInterface; /** - * Component field formatter, manage the form settings. + * Source plugin for field formater. + * + * @Source( + * id = "field_formater", + * label = @Translation("Field Formater"), + * description = @Translation("Entity Field formated with a field formater"), + * deriver = + * "Drupal\ui_patterns_field_formatters\Plugin\Derivative\FieldFormatterSourceDeriver", + * ) */ -abstract class FieldFormatterFormBase extends FieldFormatterSourceBase { +class FieldFormatterSource extends FieldPropertySourceBase { use LoggerChannelTrait; @@ -70,24 +81,6 @@ abstract class FieldFormatterFormBase extends FieldFormatterSourceBase { return $form; } - /** - * Test if we can add the formatter field formatter. - * - * @return bool - * Result of the test. - */ - private function isApplicableFormatterFieldFormatter($plugin_definition) { - $field_formatter_metadata = $this->getCustomPluginMetadata('field_formatter'); - if (!$field_formatter_metadata) { - return FALSE; - } - // Only available for slots. - if (!empty($plugin_definition['prop_types'][0]) && $plugin_definition['prop_types'][0] === 'slot') { - return TRUE; - } - return FALSE; - } - /** * Callback to build field formatter form. * @@ -103,10 +96,6 @@ abstract class FieldFormatterFormBase extends FieldFormatterSourceBase { * @throws \Drupal\Component\Plugin\Exception\PluginNotFoundException */ private function buildFieldFormatterForm(array &$form, FormStateInterface $form_state) { - $plugin_definition = $this->getPluginDefinition(); - if (!$this->isApplicableFormatterFieldFormatter($plugin_definition)) { - return FALSE; - } $field_definition = $this->getFieldDefinition(); if (!$field_definition instanceof FieldDefinitionInterface) { return FALSE; @@ -295,4 +284,83 @@ abstract class FieldFormatterFormBase extends FieldFormatterSourceBase { return $options; } + /** + * Ajax callback for fields with AJAX callback to update form substructure. + * + * @param array $form + * The form. + * @param \Drupal\Core\Form\FormStateInterface $form_state + * The form state. + * + * @return array + * The replaced form substructure. + */ + public static function onFormatterTypeChange(array $form, FormStateInterface $form_state): array { + $triggeringElement = $form_state->getTriggeringElement(); + // Dynamically return the dependent ajax for elements based on the + // triggering element. This shouldn't be done statically because + // settings forms may be different, e.g. for layout builder, core, ... + if (!empty($triggeringElement['#array_parents'])) { + $subformKeys = $triggeringElement['#array_parents']; + // Remove the triggering element itself and add the 'settings' below key. + array_pop($subformKeys); + $subformKeys[] = 'settings'; + // Return the subform: + return NestedArray::getValue($form, $subformKeys); + } + return []; + } + + /** + * Render field item(s) with the field formatter. + * + * @param \Drupal\Core\Field\FieldItemListInterface $items + * Items. + * @param int|null $field_delta + * Field delta. + * + * @return array + * Render array + */ + private function viewFieldItems(FieldItemListInterface $items, $field_delta = NULL): array { + $returned = []; + $configuration = $this->getConfiguration(); + if (empty($configuration['settings']['type'])) { + // No formatter has been configured. + return $returned; + } + for ($delta = 0; $delta < $items->count(); $delta++) { + /** @var \Drupal\Core\Field\FieldItemInterface $item */ + $item = $items->get($delta); + if ($field_delta !== NULL) { + if ($delta !== $field_delta) { + continue; + } + + $returned[] = $item->view([ + 'type' => $configuration['settings']['type'], + 'settings' => $configuration['settings']['settings'] ?? [], + ]); + break; + } + $returned[] = $item->view([ + 'type' => $configuration['settings']['type'], + 'settings' => $configuration['settings']['settings'], + ]); + } + return $returned; + } + + /** + * {@inheritdoc} + */ + public function getPropValue(): mixed { + $items = $this->getEntityFieldItemList(); + if (!$items instanceof FieldItemListInterface) { + return []; + } + $field_index = $this->getConfiguredSettingsExtra('field_index') ?? NULL; + return $this->viewFieldItems($items, $field_index); + } + } diff --git a/modules/ui_patterns_field_formatters/src/Plugin/UiPatterns/Source/FieldFormatterSourceBase.php b/modules/ui_patterns_field_formatters/src/Plugin/UiPatterns/Source/FieldFormatterSourceBase.php deleted file mode 100644 index cdc11fde8cd535dc33bb5a0b76aa8c63086a514a..0000000000000000000000000000000000000000 --- a/modules/ui_patterns_field_formatters/src/Plugin/UiPatterns/Source/FieldFormatterSourceBase.php +++ /dev/null @@ -1,98 +0,0 @@ -<?php - -declare(strict_types=1); - -namespace Drupal\ui_patterns_field_formatters\Plugin\UiPatterns\Source; - -use Drupal\Component\Utility\NestedArray; -use Drupal\Core\Field\FieldItemListInterface; -use Drupal\Core\Form\FormStateInterface; -use Drupal\Core\Logger\LoggerChannelTrait; - -/** - * Component field formatter, handle the data source. - */ -abstract class FieldFormatterSourceBase extends FieldPropertySourceBase { - - use LoggerChannelTrait; - - /** - * Ajax callback for fields with AJAX callback to update form substructure. - * - * @param array $form - * The form. - * @param \Drupal\Core\Form\FormStateInterface $form_state - * The form state. - * - * @return array - * The replaced form substructure. - */ - public static function onFormatterTypeChange(array $form, FormStateInterface $form_state): array { - $triggeringElement = $form_state->getTriggeringElement(); - // Dynamically return the dependent ajax for elements based on the - // triggering element. This shouldn't be done statically because - // settings forms may be different, e.g. for layout builder, core, ... - if (!empty($triggeringElement['#array_parents'])) { - $subformKeys = $triggeringElement['#array_parents']; - // Remove the triggering element itself and add the 'settings' below key. - array_pop($subformKeys); - $subformKeys[] = 'settings'; - // Return the subform: - return NestedArray::getValue($form, $subformKeys); - } - return []; - } - - /** - * Render field item(s) with the field formatter. - * - * @param \Drupal\Core\Field\FieldItemListInterface $items - * Items. - * @param int|null $field_delta - * Field delta. - * - * @return array - * Render array - */ - private function viewFieldItems(FieldItemListInterface $items, $field_delta = NULL): array { - $returned = []; - $configuration = $this->getConfiguration(); - if (empty($configuration['settings']['type'])) { - // No formatter has been configured. - return $returned; - } - for ($delta = 0; $delta < $items->count(); $delta++) { - /** @var \Drupal\Core\Field\FieldItemInterface $item */ - $item = $items->get($delta); - if ($field_delta !== NULL) { - if ($delta !== $field_delta) { - continue; - } - - $returned[] = $item->view([ - 'type' => $configuration['settings']['type'], - 'settings' => $configuration['settings']['settings'] ?? [], - ]); - break; - } - $returned[] = $item->view([ - 'type' => $configuration['settings']['type'], - 'settings' => $configuration['settings']['settings'], - ]); - } - return $returned; - } - - /** - * {@inheritdoc} - */ - public function getPropValue(): mixed { - $items = $this->getEntityFieldItemList(); - if (!$items instanceof FieldItemListInterface) { - return []; - } - $field_index = $this->getConfiguredSettingsExtra('field_index') ?? NULL; - return $this->viewFieldItems($items, $field_index); - } - -} diff --git a/modules/ui_patterns_field_formatters/src/Plugin/UiPatterns/Source/FieldLabelSource.php b/modules/ui_patterns_field_formatters/src/Plugin/UiPatterns/Source/FieldLabelSource.php index e2240b8dc4615ea3a63513e0c763b794f65eb36c..0751ca354e7f4bda255386e9f79d681fb86603b4 100644 --- a/modules/ui_patterns_field_formatters/src/Plugin/UiPatterns/Source/FieldLabelSource.php +++ b/modules/ui_patterns_field_formatters/src/Plugin/UiPatterns/Source/FieldLabelSource.php @@ -4,6 +4,8 @@ declare(strict_types=1); namespace Drupal\ui_patterns_field_formatters\Plugin\UiPatterns\Source; +use Drupal\ui_patterns\Plugin\UiPatterns\Source\FieldSourceBase; + /** * Plugin implementation of the field_label source. * diff --git a/modules/ui_patterns_field_formatters/src/Plugin/UiPatterns/Source/FieldLabelSourceSlot.php b/modules/ui_patterns_field_formatters/src/Plugin/UiPatterns/Source/FieldLabelSourceSlot.php deleted file mode 100644 index d9e36c57d6ea8c6d6323adac2bf1d52341f93b9a..0000000000000000000000000000000000000000 --- a/modules/ui_patterns_field_formatters/src/Plugin/UiPatterns/Source/FieldLabelSourceSlot.php +++ /dev/null @@ -1,28 +0,0 @@ -<?php - -declare(strict_types=1); - -namespace Drupal\ui_patterns_field_formatters\Plugin\UiPatterns\Source; - -/** - * Plugin implementation of the field_label slot source. - * - * @Source( - * id = "field_label_slot", - * label = @Translation("Field label"), - * description = @Translation("Field label source plugin."), - * prop_types = { - * "slot" - * } - * ) - */ -class FieldLabelSourceSlot extends FieldLabelSource { - - /** - * {@inheritdoc} - */ - public function getPropValue(): mixed { - return ["#markup" => parent::getPropValue()]; - } - -} diff --git a/modules/ui_patterns_field_formatters/src/Plugin/UiPatterns/Source/FieldPropertySourceSlot.php b/modules/ui_patterns_field_formatters/src/Plugin/UiPatterns/Source/FieldPropertySourceSlot.php deleted file mode 100644 index ca929da6be132ef7474340c2c05c66265ee315b6..0000000000000000000000000000000000000000 --- a/modules/ui_patterns_field_formatters/src/Plugin/UiPatterns/Source/FieldPropertySourceSlot.php +++ /dev/null @@ -1,73 +0,0 @@ -<?php - -declare(strict_types=1); - -namespace Drupal\ui_patterns_field_formatters\Plugin\UiPatterns\Source; - -use Drupal\Core\Field\FieldItemListInterface; - -/** - * Plugin implementation of the slot source. - * - * @Source( - * id = "field_properties_source_slot", - * label = @Translation("Field Property (Slots)"), - * description = @Translation("Field property source plugin for slot."), - * deriver = - * "Drupal\ui_patterns_field_formatters\Plugin\Derivative\FieldPropertiesSourceSlotDeriver", - * ) - */ -class FieldPropertySourceSlot extends FieldFormatterFormBase { - - /** - * {@inheritdoc} - */ - public function getPropValue(): mixed { - $items = $this->getEntityFieldItemList(); - if (!$items instanceof FieldItemListInterface) { - return []; - } - $field_index = $this->getConfiguredSettingsExtra('field_index') ?? NULL; - // Render using a display formater. - if ($this->getCustomPluginMetadata('field_formatter')) { - return parent::getPropValue(); - } - $property = $this->getCustomPluginMetadata('property'); - if (empty($property)) { - return []; - } - $lang_code = $this->getConfiguredSettingsExtra("lang_code") ?? 'und'; - return $this->getDataItems($items, $property, $lang_code, $field_index); - } - - /** - * Get Data items. - * - * @param \Drupal\Core\Field\FieldItemListInterface $items - * Items. - * @param string $property - * Property. - * @param string $lang_code - * Lang code. - * @param int|null $field_index - * Field index. - * - * @return mixed - * Items. - * - * @throws \Drupal\Core\TypedData\Exception\MissingDataException - */ - private function getDataItems(FieldItemListInterface $items, $property, $lang_code, $field_index = NULL): mixed { - $returned = []; - for ($delta = 0; $delta < $items->count(); $delta++) { - /** @var \Drupal\Core\Field\FieldItemInterface $fieldValue */ - $fieldValue = $items->get($delta); - if ((NULL !== $field_index) && $delta != $field_index) { - continue; - } - $returned[] = ['#markup' => $this->extractPropertyValue($fieldValue, $property, $lang_code)]; - } - return $returned; - } - -} diff --git a/modules/ui_patterns_field_formatters/tests/src/Kernel/PluginTest.php b/modules/ui_patterns_field_formatters/tests/src/Kernel/PluginTest.php index c49e3a8077b07b43085bd9327e4f7303c1af9eee..74888f035595600dd2f48226708404228c1aa537 100644 --- a/modules/ui_patterns_field_formatters/tests/src/Kernel/PluginTest.php +++ b/modules/ui_patterns_field_formatters/tests/src/Kernel/PluginTest.php @@ -6,10 +6,10 @@ use Drupal\Component\Plugin\PluginBase; use Drupal\Core\Field\FieldConfigInterface; use Drupal\Core\Plugin\Context\ContextDefinition; use Drupal\Core\Plugin\Context\EntityContextDefinition; -use Drupal\ui_patterns_field_formatters\Plugin\Derivative\FieldPropertiesSourcePropDeriver; -use Drupal\ui_patterns_field_formatters\Plugin\Derivative\FieldPropertiesSourceSlotDeriver; -use Drupal\ui_patterns_field_formatters\Plugin\UiPatterns\Source\FieldPropertySourceProp; -use Drupal\ui_patterns_field_formatters\Plugin\UiPatterns\Source\FieldPropertySourceSlot; +use Drupal\ui_patterns\Plugin\Derivative\FieldPropertiesSourcePropDeriver; +use Drupal\ui_patterns\Plugin\UiPatterns\Source\FieldPropertySourceProp; +use Drupal\ui_patterns_field_formatters\Plugin\Derivative\FieldFormatterSourceDeriver; +use Drupal\ui_patterns_field_formatters\Plugin\UiPatterns\Source\FieldFormatterSource; /** * Tests the ui_patterns_field_formatters deriver plugin. @@ -97,8 +97,8 @@ class PluginTest extends UIPatternsFieldFormattersTestBase { [ 'deriver_type' => 'slot', 'prop_types' => ['slot'], - 'deriver' => FieldPropertiesSourceSlotDeriver::class, - 'class' => FieldPropertySourceSlot::class, + 'deriver' => FieldFormatterSourceDeriver::class, + 'class' => FieldFormatterSource::class, ], [ 'deriver_type' => 'prop', diff --git a/modules/ui_patterns_views/src/Plugin/UiPatterns/Source/ViewFieldSource.php b/modules/ui_patterns_views/src/Plugin/UiPatterns/Source/ViewFieldSource.php index 3cda012de0d2731374f121fbfcd0afa27e85517f..b54d6a434d705a021ff22ac28c3cb9e8ce19e163 100644 --- a/modules/ui_patterns_views/src/Plugin/UiPatterns/Source/ViewFieldSource.php +++ b/modules/ui_patterns_views/src/Plugin/UiPatterns/Source/ViewFieldSource.php @@ -24,6 +24,9 @@ use Drupal\views\ViewExecutable; * }, * context_requirements = { * "views:row" + * }, + * context_definitions = { + * "entity" = @ContextDefinition("entity:view", label = @Translation("View")) * } * ) */ diff --git a/modules/ui_patterns_views/src/Plugin/UiPatterns/Source/ViewGroupTitleSource.php b/modules/ui_patterns_views/src/Plugin/UiPatterns/Source/ViewGroupTitleSource.php index 9d23ea5101cc4f2d483e0841464dbe988c8a851b..144ea0d5bab8ba481c937235a97c1840b2a21678 100644 --- a/modules/ui_patterns_views/src/Plugin/UiPatterns/Source/ViewGroupTitleSource.php +++ b/modules/ui_patterns_views/src/Plugin/UiPatterns/Source/ViewGroupTitleSource.php @@ -21,8 +21,11 @@ use Drupal\Core\Form\FormStateInterface; * "views" * }, * context_requirements = { - * "views:style", - * "views:group" + * "views:style", + * "views:group" + * }, + * context_definitions = { + * "entity" = @ContextDefinition("entity:view", label = @Translation("View")) * } * ) */ diff --git a/modules/ui_patterns_views/src/Plugin/UiPatterns/Source/ViewRowsSource.php b/modules/ui_patterns_views/src/Plugin/UiPatterns/Source/ViewRowsSource.php index 9cd26351d520735ac2fe4f97b80227d8011fe0b9..2decf9d01f0ed8da112a638c619063d537c55e8c 100644 --- a/modules/ui_patterns_views/src/Plugin/UiPatterns/Source/ViewRowsSource.php +++ b/modules/ui_patterns_views/src/Plugin/UiPatterns/Source/ViewRowsSource.php @@ -19,6 +19,9 @@ namespace Drupal\ui_patterns_views\Plugin\UiPatterns\Source; * }, * context_requirements = { * "views:style", + * }, + * context_definitions = { + * "entity" = @ContextDefinition("entity:view", label = @Translation("View")) * } * * ) diff --git a/modules/ui_patterns_views/src/Plugin/UiPatterns/Source/ViewTitleSource.php b/modules/ui_patterns_views/src/Plugin/UiPatterns/Source/ViewTitleSource.php index a5ee7a1207d977dc5502792c0dbdef18ca507545..96f873e34cfa9458c33a1a1ae366cb602902bb95 100644 --- a/modules/ui_patterns_views/src/Plugin/UiPatterns/Source/ViewTitleSource.php +++ b/modules/ui_patterns_views/src/Plugin/UiPatterns/Source/ViewTitleSource.php @@ -12,11 +12,14 @@ use Drupal\views\ViewExecutable; * @Source( * id = "view_title", * label = @Translation("View title"), - * description = @Translation("The title of the view."), + * description = @Translation("The title of the view."), * prop_types = { - * "string" - * }, - * ) + * "string" + * }, + * context_definitions = { + * "entity" = @ContextDefinition("entity:view", label = @Translation("View")) + * } + * ) */ class ViewTitleSource extends ViewsSourceBase { diff --git a/modules/ui_patterns_views/src/Plugin/UiPatterns/Source/ViewsSourceBase.php b/modules/ui_patterns_views/src/Plugin/UiPatterns/Source/ViewsSourceBase.php index 445fa72188c02084fa5669ff0c3e02c619630d8e..0919227f1924fee1069d30ce941887d87012bdb8 100644 --- a/modules/ui_patterns_views/src/Plugin/UiPatterns/Source/ViewsSourceBase.php +++ b/modules/ui_patterns_views/src/Plugin/UiPatterns/Source/ViewsSourceBase.php @@ -7,7 +7,6 @@ namespace Drupal\ui_patterns_views\Plugin\UiPatterns\Source; use Drupal\Component\Render\MarkupInterface; use Drupal\Component\Utility\NestedArray; use Drupal\Core\Form\FormStateInterface; -use Drupal\Core\Plugin\Context\EntityContextDefinition; use Drupal\ui_patterns\SourcePluginBase; /** @@ -68,16 +67,4 @@ abstract class ViewsSourceBase extends SourcePluginBase { return $output; } - /** - * We add a constraint to require a view for those sources. - */ - public static function getDiscoveryContexts() : array { - // Context for views entity type. - $entity_context = EntityContextDefinition::fromEntityTypeId('view') - ->setLabel('view'); - return [ - 'entity' => $entity_context, - ]; - } - } diff --git a/modules/ui_patterns_views/src/Plugin/views/style/ComponentStyle.php b/modules/ui_patterns_views/src/Plugin/views/style/ComponentStyle.php index 3231694e0b0767e7577b84be63771ea60e1dd848..8d4664a60759df7ec455b64f8d4a662235cd9928 100755 --- a/modules/ui_patterns_views/src/Plugin/views/style/ComponentStyle.php +++ b/modules/ui_patterns_views/src/Plugin/views/style/ComponentStyle.php @@ -148,7 +148,7 @@ class ComponentStyle extends StylePluginBase { $this->removeGroupTitleSource($slots["sources"]); } } - unset($slots, $sources); + unset($slots); // Set value inside form state. $form_state->setValue('style_options', $style_option); $user_input = $form_state->getUserInput(); @@ -162,11 +162,12 @@ class ComponentStyle extends StylePluginBase { foreach ($slots as &$sources) { $this->removeGroupTitleSource($sources); } + unset($sources); } + unset($slots); $user_input['style_options'] = $style_option_input; $form_state->setUserInput($user_input); } - unset($slots, $sources); return $group_title; } diff --git a/modules/ui_patterns_views/src/UiPatternsViewsManager.php b/modules/ui_patterns_views/src/UiPatternsViewsManager.php index 6721dcb274ff8231459f6d605d3a7eb4873435ac..4139c19801168220ecc327a8d58624e3d67d0109 100644 --- a/modules/ui_patterns_views/src/UiPatternsViewsManager.php +++ b/modules/ui_patterns_views/src/UiPatternsViewsManager.php @@ -11,7 +11,7 @@ use Drupal\Core\Plugin\Context\Context; use Drupal\Core\Plugin\Context\ContextDefinition; use Drupal\Core\Plugin\Context\EntityContext; use Drupal\Core\Plugin\PluginBase; -use Drupal\ui_patterns\SourcePluginBase; +use Drupal\ui_patterns\Plugin\Context\RequirementsContext; use Drupal\views\ViewExecutable; /** @@ -50,7 +50,7 @@ class UiPatternsViewsManager { if (is_array($more_context_requirements) && (count($more_context_requirements) > 0)) { $context_requirements = array_merge($context_requirements, $more_context_requirements); } - $context_source = SourcePluginBase::addRequirementsToContext($context_source, $context_requirements); + $context_source = RequirementsContext::addToContext($context_requirements, $context_source); // Build context views id. $context_id = ContextDefinition::create('string'); $context_id->setLabel("views_id"); diff --git a/src/Annotation/Source.php b/src/Annotation/Source.php index 13f8557951d9b0a2b3b118b831a4bf87b2f413a2..aca1c66d5c6a1bbabee1bd81dd09aece8f50f206 100644 --- a/src/Annotation/Source.php +++ b/src/Annotation/Source.php @@ -34,4 +34,11 @@ final class Source extends Plugin { */ public $context_requirements = []; + /** + * An array of metadata. + * + * @var array<string, mixed> + */ + public $metadata = []; + } diff --git a/src/Element/ComponentForm.php b/src/Element/ComponentForm.php index 2624babdeb92b173cd76f4ebe736cb5850a4dc72..ec72a73215b12d0e0b3fdef23c08272c8b4150dc 100644 --- a/src/Element/ComponentForm.php +++ b/src/Element/ComponentForm.php @@ -42,7 +42,8 @@ use Drupal\Core\Plugin\Context\ContextDefinition; * * Additional Configuration: * - * '#component_id' => Optional Component Id. If not set a component selector is set. + * '#component_id' => Optional Component Id. + * If unset a component selector is set. * '#source_contexts' => The context of the sources. * '#tag_filter' => Filter sources based on this tags. * @@ -223,7 +224,7 @@ class ComponentForm extends ComponentFormBase { '#type' => 'component_slots_form', '#component_id' => $component_id, '#source_contexts' => $element['#source_contexts'], - '#tag_filter' =>$element['#tag_filter'], + '#tag_filter' => $element['#tag_filter'], '#ajax_url' => $element['#ajax_url'], '#access' => $element['#render_slots'] ?? TRUE, '#default_value' => [ @@ -241,7 +242,7 @@ class ComponentForm extends ComponentFormBase { '#type' => 'component_props_form', '#component_id' => $component_id, '#source_contexts' => $element['#source_contexts'], - '#tag_filter' =>$element['#tag_filter'], + '#tag_filter' => $element['#tag_filter'], '#ajax_url' => $element['#ajax_url'], '#access' => $element['#render_props'] ?? TRUE, '#default_value' => [ diff --git a/src/Element/ComponentSlotForm.php b/src/Element/ComponentSlotForm.php index ee23efe7fee4d5cdb1a97bcbded7862478b159a8..45e6745d858a2e15c39ea7ec00264c53bf22b6fd 100644 --- a/src/Element/ComponentSlotForm.php +++ b/src/Element/ComponentSlotForm.php @@ -36,12 +36,13 @@ use Drupal\ui_patterns\SourcePluginBase; * * Configuration: * - * '#component_id' => Optional Component ID. A slot can rendered without knowing any context. - * '#slot_id' => Optional Slot ID. - * '#source_contexts' => The context of the sources. - * '#tag_filter' => Filter sources based on these tags. - * '#display_remove' => Display or hide the remove button. Default = true - * '#cardinality_multiple' => Allow or disallow multiple slot items + * '#component_id' =>Optional Component ID. + * A slot can rendered without knowing any context. + * '#slot_id' =>Optional Slot ID. + * '#source_contexts' =>The context of the sources. + * '#tag_filter' =>Filter sources based on these tags. + * '#display_remove' =>Display or hide the remove button. Default = true + * '#cardinality_multiple' =>Allow or disallow multiple slot items * * @FormElement("component_slot_form") */ @@ -91,7 +92,7 @@ class ComponentSlotForm extends ComponentFormBase { /** @var \Drupal\ui_patterns\PropTypePluginManager $prop_type_manager */ $prop_type_manager = \Drupal::service("plugin.manager.ui_patterns_prop_type"); $definition = [ - 'ui_patterns' => $prop_type_manager->createInstance('slot', []) + 'ui_patterns' => $prop_type_manager->createInstance('slot', []), ]; } diff --git a/src/Plugin/Context/RequirementsContext.php b/src/Plugin/Context/RequirementsContext.php index 69408db8bbeee79b74672f69aa13734ddba2d3c9..8bf8dbdc66fc3a7ff1bbda8af11a7b7c6fee61b8 100644 --- a/src/Plugin/Context/RequirementsContext.php +++ b/src/Plugin/Context/RequirementsContext.php @@ -23,16 +23,6 @@ class RequirementsContext extends Context { return new static(RequirementsContextDefinition::fromRequirements([], $label), $values); } - /** - * Adds values to the context. - * - * @param array<string> $values - * Requirements to add to the context. - */ - public function addValues(array $values): void { - $this->contextValue = array_merge(is_array($this->contextValue) ? $this->contextValue : [], $values); - } - /** * Check if a values is present in the context. * @@ -43,7 +33,29 @@ class RequirementsContext extends Context { * True if the value is present in the context. */ public function hasValue(string $value) : bool { - return is_array($this->contextValue) && in_array($value, $this->contextValue); + return in_array($value, $this->getContextValue() ?? []); + } + + /** + * Add values to the context_requirements context. + * + * @param array<string> $values + * The values to add to context_requirements context. + * @param array<\Drupal\Core\Plugin\Context\ContextInterface> $contexts + * The contexts. + * + * @return array<\Drupal\Core\Plugin\Context\ContextInterface> + * The contexts. + */ + public static function addToContext(array $values, array $contexts): array { + if (array_key_exists("context_requirements", $contexts) && $contexts["context_requirements"] instanceof RequirementsContext) { + $contexts["context_requirements"] = static::fromValues(array_merge($contexts["context_requirements"]->getContextValue(), $values)); + } + else { + $contexts["context_requirements"] = static::fromValues($values); + } + + return $contexts; } } diff --git a/modules/ui_patterns_field_formatters/src/Plugin/Derivative/FieldPropertiesSourceDeriverBase.php b/src/Plugin/Derivative/FieldPropertiesSourceDeriverBase.php similarity index 95% rename from modules/ui_patterns_field_formatters/src/Plugin/Derivative/FieldPropertiesSourceDeriverBase.php rename to src/Plugin/Derivative/FieldPropertiesSourceDeriverBase.php index 69f643940bde48399a6a5fab6620238a6d6b8446..f1ddb67841d8ac8384a2288366a6d0c4c0931b29 100644 --- a/modules/ui_patterns_field_formatters/src/Plugin/Derivative/FieldPropertiesSourceDeriverBase.php +++ b/src/Plugin/Derivative/FieldPropertiesSourceDeriverBase.php @@ -1,6 +1,6 @@ <?php -namespace Drupal\ui_patterns_field_formatters\Plugin\Derivative; +namespace Drupal\ui_patterns\Plugin\Derivative; use Drupal\Component\Plugin\Derivative\DeriverBase; use Drupal\Component\Plugin\PluginBase; @@ -65,6 +65,10 @@ abstract class FieldPropertiesSourceDeriverBase extends DeriverBase implements C * {@inheritdoc} */ public function getDerivativeDefinitions($base_plugin_definition): array { + if (!array_key_exists('config_dependencies', $base_plugin_definition) || + !is_array($base_plugin_definition['config_dependencies'])) { + $base_plugin_definition['config_dependencies'] = []; + } // For each fieldable entity type, get the field map. foreach ($this->entityFieldManager->getFieldMap() as $entity_type_id => $entity_field_map) { $entity_type = $this->entityTypeManager->getDefinition($entity_type_id); @@ -128,7 +132,7 @@ abstract class FieldPropertiesSourceDeriverBase extends DeriverBase implements C $field_name, ]), // Partially filled in. - 'ui_patterns_field_formatter' => [ + 'metadata' => [ 'entity_type' => $entity_type_id, 'field_name' => $field_name, ], @@ -139,9 +143,6 @@ abstract class FieldPropertiesSourceDeriverBase extends DeriverBase implements C ], ]); // Add config_dependencies. - if (!array_key_exists("config_dependencies", $derivative_for_this_field)) { - $derivative_for_this_field["config_dependencies"] = []; - } foreach ($bundles as $bundle) { $field_definitions = $this->entityFieldManager->getFieldDefinitions($entity_type_id, $bundle); if (empty($field_definitions[$field_name])) { @@ -192,7 +193,7 @@ abstract class FieldPropertiesSourceDeriverBase extends DeriverBase implements C $derivative['id'], $property_id, ]); - $derivative['ui_patterns_field_formatter'] = array_merge($derivative['ui_patterns_field_formatter'], [ + $derivative['metadata'] = array_merge($derivative['metadata'], [ 'property' => $property_id, ]); // If no compatible prop types were inferred, we discard the plugin. diff --git a/modules/ui_patterns_field_formatters/src/Plugin/Derivative/FieldPropertiesSourcePropDeriver.php b/src/Plugin/Derivative/FieldPropertiesSourcePropDeriver.php similarity index 78% rename from modules/ui_patterns_field_formatters/src/Plugin/Derivative/FieldPropertiesSourcePropDeriver.php rename to src/Plugin/Derivative/FieldPropertiesSourcePropDeriver.php index 84db2f2ed16142f133071fe0a500c9776867a32b..df3fab8fb2dedaa36ba1531801f9460a4cd755ec 100644 --- a/modules/ui_patterns_field_formatters/src/Plugin/Derivative/FieldPropertiesSourcePropDeriver.php +++ b/src/Plugin/Derivative/FieldPropertiesSourcePropDeriver.php @@ -1,11 +1,11 @@ <?php -namespace Drupal\ui_patterns_field_formatters\Plugin\Derivative; +namespace Drupal\ui_patterns\Plugin\Derivative; use Drupal\Core\TypedData\DataDefinitionInterface; /** - * Provides entity field block definitions for every field. + * Provides a source for every field prop. * * @internal * Plugin derivers are internal. diff --git a/modules/ui_patterns_field_formatters/src/Plugin/UiPatterns/Source/FieldPropertySourceBase.php b/src/Plugin/UiPatterns/Source/FieldPropertySourceBase.php similarity index 87% rename from modules/ui_patterns_field_formatters/src/Plugin/UiPatterns/Source/FieldPropertySourceBase.php rename to src/Plugin/UiPatterns/Source/FieldPropertySourceBase.php index f25f8f800848a4f0c309cc23ea8f6b20ab8cf932..30a021985e66faf8c7ee6d64a8b3320759a516e6 100644 --- a/modules/ui_patterns_field_formatters/src/Plugin/UiPatterns/Source/FieldPropertySourceBase.php +++ b/src/Plugin/UiPatterns/Source/FieldPropertySourceBase.php @@ -2,7 +2,7 @@ declare(strict_types=1); -namespace Drupal\ui_patterns_field_formatters\Plugin\UiPatterns\Source; +namespace Drupal\ui_patterns\Plugin\UiPatterns\Source; use Drupal\Component\Utility\NestedArray; use Drupal\Core\Entity\EntityInterface; @@ -68,7 +68,7 @@ abstract class FieldPropertySourceBase extends FieldSourceBase implements Source * The entity */ protected function getEntity(): ?EntityInterface { - $entity = $this->getContextValue('entity'); + $entity = parent::getEntity(); if ($entity instanceof EntityInterface) { return $entity; } @@ -102,12 +102,12 @@ abstract class FieldPropertySourceBase extends FieldSourceBase implements Source /** @var \Drupal\Core\Entity\ContentEntityBase $entity */ $entity = $this->getEntity(); if (!$entity) { - $this->getLogger('ui_patterns_field_formatters') + $this->getLogger('ui_patterns') ->error('Entity not found in context'); return NULL; } if (!$entity->hasField($field_name)) { - $this->getLogger('ui_patterns_field_formatters') + $this->getLogger('ui_patterns') ->error('Entity %entity_type %bundle has no field %field_name', [ '%entity_type' => $entity->getEntityTypeId(), '%bundle' => $entity->bundle() ?? "", @@ -192,26 +192,6 @@ abstract class FieldPropertySourceBase extends FieldSourceBase implements Source return $value; } - /** - * Get ui patterns field formatter metadata stored in the plugin definition. - * - * @param string $key - * The key name of plugin definition to get data. - * - * @return null|mixed - * The data inside plugin definition or false if error. - */ - protected function getCustomPluginMetadata(string $key): mixed { - $plugin_definition = $this->getPluginDefinition(); - if (empty($plugin_definition) || - !is_array($plugin_definition) || - !is_array($plugin_definition['ui_patterns_field_formatter']) || - !array_key_exists($key, $plugin_definition['ui_patterns_field_formatter'])) { - return NULL; - } - return $plugin_definition['ui_patterns_field_formatter'][$key]; - } - /** * Returns part of the plugin config specific to UI patterns field formatter. * @@ -227,7 +207,7 @@ abstract class FieldPropertySourceBase extends FieldSourceBase implements Source * @see setComponentSettingsExtra() */ protected function getConfiguredSettingsExtra(?string $key = NULL): mixed { - $parents = ['settings', 'ui_patterns_field_formatter']; + $parents = ['settings', 'extra']; if ($key) { $parents[] = $key; } diff --git a/modules/ui_patterns_field_formatters/src/Plugin/UiPatterns/Source/FieldPropertySourceProp.php b/src/Plugin/UiPatterns/Source/FieldPropertySourceProp.php similarity index 88% rename from modules/ui_patterns_field_formatters/src/Plugin/UiPatterns/Source/FieldPropertySourceProp.php rename to src/Plugin/UiPatterns/Source/FieldPropertySourceProp.php index 8af604a19b2c042dee511f96cb621fc16233bd9d..7bf9bf148e9d1bf68ab6a65f82fd35f7d338c272 100644 --- a/modules/ui_patterns_field_formatters/src/Plugin/UiPatterns/Source/FieldPropertySourceProp.php +++ b/src/Plugin/UiPatterns/Source/FieldPropertySourceProp.php @@ -2,7 +2,7 @@ declare(strict_types=1); -namespace Drupal\ui_patterns_field_formatters\Plugin\UiPatterns\Source; +namespace Drupal\ui_patterns\Plugin\UiPatterns\Source; /** * Plugin implementation of the prop source. @@ -12,7 +12,7 @@ namespace Drupal\ui_patterns_field_formatters\Plugin\UiPatterns\Source; * label = @Translation("Field Property (Props)"), * description = @Translation("Field property source plugin for props."), * deriver = - * "Drupal\ui_patterns_field_formatters\Plugin\Derivative\FieldPropertiesSourcePropDeriver" + * "Drupal\ui_patterns\Plugin\Derivative\FieldPropertiesSourcePropDeriver" * ) */ class FieldPropertySourceProp extends FieldPropertySourceBase { @@ -22,7 +22,6 @@ class FieldPropertySourceProp extends FieldPropertySourceBase { */ public function getPropValue(): mixed { $items = $this->getEntityFieldItemList(); - // Get field index or 0 (first if formatter all). $delta = $this->getConfiguredSettingsExtra("field_index") ?? 0; $lang_code = $this->getConfiguredSettingsExtra("lang_code") ?? "und"; $property = $this->getCustomPluginMetadata('property'); diff --git a/modules/ui_patterns_field_formatters/src/Plugin/UiPatterns/Source/FieldSourceBase.php b/src/Plugin/UiPatterns/Source/FieldSourceBase.php similarity index 74% rename from modules/ui_patterns_field_formatters/src/Plugin/UiPatterns/Source/FieldSourceBase.php rename to src/Plugin/UiPatterns/Source/FieldSourceBase.php index c2ac51eec2866fad4e7b85821340eb54c440acfe..7bc1b66cbf59fe80d61c1371b9fbdea889f6e0fe 100644 --- a/modules/ui_patterns_field_formatters/src/Plugin/UiPatterns/Source/FieldSourceBase.php +++ b/src/Plugin/UiPatterns/Source/FieldSourceBase.php @@ -2,8 +2,10 @@ declare(strict_types=1); -namespace Drupal\ui_patterns_field_formatters\Plugin\UiPatterns\Source; +namespace Drupal\ui_patterns\Plugin\UiPatterns\Source; +use Drupal\Component\Plugin\Exception\ContextException; +use Drupal\Core\Entity\EntityInterface; use Drupal\Core\Field\FieldDefinitionInterface; use Drupal\Core\Form\FormStateInterface; use Drupal\Core\Logger\LoggerChannelTrait; @@ -12,7 +14,7 @@ use Drupal\ui_patterns\SourcePluginBase; use Symfony\Component\DependencyInjection\ContainerInterface; /** - * Base class for all ui_patterns_field_formatter source plugins. + * Base class for all field source plugins. */ abstract class FieldSourceBase extends SourcePluginBase implements SourceInterface { @@ -62,6 +64,8 @@ abstract class FieldSourceBase extends SourcePluginBase implements SourceInterfa * * @return string * The field name. + * + * @throws \Drupal\Component\Plugin\Exception\ContextException */ protected function getFieldName(): string { return $this->getContextValue('field_name'); @@ -72,6 +76,8 @@ abstract class FieldSourceBase extends SourcePluginBase implements SourceInterfa * * @return string * The bundle. + * + * @throws \Drupal\Component\Plugin\Exception\ContextException */ protected function getBundle(): string { return $this->getContextValue('bundle'); @@ -82,9 +88,26 @@ abstract class FieldSourceBase extends SourcePluginBase implements SourceInterfa * * @return string|null * The entity type id. + * + * @throws \Drupal\Component\Plugin\Exception\ContextException */ protected function getEntityTypeId(): ?string { - return $this->getContextValue('entity_type_id'); + if ($entity = $this->getEntity()) { + return $entity->getEntityTypeId(); + } + throw new ContextException("Entity not found"); + } + + /** + * Returns the entity from context. + * + * @return \Drupal\Core\Entity\EntityInterface|null + * The entity + * + * @throws \Drupal\Component\Plugin\Exception\ContextException + */ + protected function getEntity(): ?EntityInterface { + return $this->getContextValue('entity'); } /** diff --git a/src/SourceInterface.php b/src/SourceInterface.php index b161a0eb9d3728b12100937a302f241c5451e789..38e6551a4708c333a5deb23f6486d2613cd242da 100644 --- a/src/SourceInterface.php +++ b/src/SourceInterface.php @@ -38,11 +38,14 @@ interface SourceInterface extends ConfigurableInterface, PluginInspectionInterfa public function alterComponent(array $element): array; /** - * Returns contexts used to restrict plugin discovery. + * Get metadata stored in the plugin definition. * - * @return array - * An array of context definitions. + * @param string $key + * The key name of plugin definition to get data. + * + * @return null|mixed + * The data inside plugin definition or false if error. */ - public static function getDiscoveryContexts(): array; + public function getCustomPluginMetadata(string $key): mixed; } diff --git a/src/SourcePluginBase.php b/src/SourcePluginBase.php index b1dc2defb965419103e7406953f8ab8398df355e..d1051c66c75d3a5d0a2c07cf1c8bdd6b0ff3ff54 100644 --- a/src/SourcePluginBase.php +++ b/src/SourcePluginBase.php @@ -13,7 +13,6 @@ use Drupal\Core\Plugin\ContextAwarePluginAssignmentTrait; use Drupal\Core\Plugin\ContextAwarePluginInterface; use Drupal\Core\Plugin\ContextAwarePluginTrait; use Drupal\Core\StringTranslation\StringTranslationTrait; -use Drupal\ui_patterns\Plugin\Context\RequirementsContext; use Symfony\Component\DependencyInjection\ContainerInterface; /** @@ -281,37 +280,15 @@ abstract class SourcePluginBase extends PluginBase implements /** * {@inheritdoc} */ - public function getContextDefinitions() { - return static::getDiscoveryContexts(); - } - - /** - * {@inheritdoc} - */ - public static function getDiscoveryContexts() : array { - return []; - } - - /** - * Add values to the context_requirements context. - * - * @param array<\Drupal\Core\Plugin\Context\ContextInterface> $context - * The contexts. - * @param array<string> $values - * The values to add to context_requirements context. - * - * @return array<\Drupal\Core\Plugin\Context\ContextInterface> - * The contexts. - */ - public static function addRequirementsToContext(array $context, array $values): array { - if (array_key_exists("context_requirements", $context) && $context["context_requirements"] instanceof RequirementsContext) { - $context["context_requirements"]->addValues($values); - } - else { - $context["context_requirements"] = RequirementsContext::fromValues($values); + public function getCustomPluginMetadata(string $key): mixed { + $plugin_definition = $this->getPluginDefinition(); + if (empty($plugin_definition) || + !is_array($plugin_definition) || + !is_array($plugin_definition['metadata']) || + !array_key_exists($key, $plugin_definition['metadata'])) { + return NULL; } - - return $context; + return $plugin_definition['metadata'][$key]; } } diff --git a/src/SourcePluginManager.php b/src/SourcePluginManager.php index b262279020511c14cdc1506112bcef7f03ff822c..50071fa05dbd05d7b35aa9cd148d499610a0c279 100644 --- a/src/SourcePluginManager.php +++ b/src/SourcePluginManager.php @@ -4,7 +4,6 @@ declare(strict_types=1); namespace Drupal\ui_patterns; -use Drupal\Component\Plugin\Definition\PluginDefinitionInterface; use Drupal\Core\Cache\CacheBackendInterface; use Drupal\Core\Extension\ModuleHandlerInterface; use Drupal\Core\Plugin\Context\ContextAwarePluginManagerInterface; @@ -50,13 +49,6 @@ class SourcePluginManager extends DefaultPluginManager implements ContextAwarePl */ public function processDefinition(&$definition, $plugin_id) { parent::processDefinition($definition, $plugin_id); - $pluginClass = ($definition instanceof PluginDefinitionInterface) ? $definition->getClass() : $definition['class']; - if (method_exists($pluginClass, 'getDiscoveryContexts')) { - $definition["context_definitions"] = array_merge( - array_key_exists("context_definitions", $definition) ? $definition["context_definitions"] : [], - $pluginClass::getDiscoveryContexts() - ); - } if (array_key_exists("context_requirements", $definition) && count($definition["context_requirements"]) > 0) { $definition["context_definitions"]["context_requirements"] = RequirementsContextDefinition::fromRequirements($definition["context_requirements"]); } @@ -68,7 +60,8 @@ class SourcePluginManager extends DefaultPluginManager implements ContextAwarePl public function getDefinitionsForPropType(string $prop_type_id, array $contexts = [], array $tag_filter = []): array { $definitions = $this->getDefinitionsForContexts($contexts); $definitions = array_filter($definitions, function ($definition) use ($prop_type_id, $tag_filter) { - if (!in_array($prop_type_id, $definition['prop_types'])) { + $supported_prop_types = array_key_exists("prop_types", $definition) ? $definition['prop_types'] : []; + if (is_array($supported_prop_types) && (count($supported_prop_types) > 0) && !in_array($prop_type_id, $supported_prop_types)) { return FALSE; } if (count($tag_filter) > 0) { @@ -88,18 +81,24 @@ class SourcePluginManager extends DefaultPluginManager implements ContextAwarePl /** * Returns the default source identifier for a prop type. */ - public function getPropTypeDefault(string $prop_type_id, array $contexts = []): ?string { + public function getPropTypeDefault(string $prop_type_id, array $contexts = [], array $tag_filter = []): ?string { // First try with prop type default source. $prop_type_definition = $this->prop_type_manager->getDefinition($prop_type_id); - $source_id = $prop_type_definition["default_source"] ?? NULL; - if ($source_id && $this->isApplicable($source_id, $contexts)) { - return $source_id; + $default_source_id = $prop_type_definition["default_source"] ?? NULL; + if (!$tag_filter && $default_source_id && $this->isApplicable($default_source_id, $contexts)) { + return $default_source_id; } // If no default source, take the first one. - $definitions = $this->getDefinitionsForPropType($prop_type_id, $contexts); - $source_id = array_key_first($definitions) ?? NULL; - if ($source_id && $this->isApplicable($source_id, $contexts)) { - return $source_id; + $definitions = $this->getDefinitionsForPropType($prop_type_id, $contexts, $tag_filter); + if ($tag_filter && $default_source_id && array_key_exists($default_source_id, $definitions) && + $this->isApplicable($default_source_id, $contexts)) { + return $default_source_id; + } + $source_ids = array_keys($definitions); + foreach ($source_ids as $source_id) { + if ($source_id && $this->isApplicable($source_id, $contexts)) { + return $source_id; + } } return NULL; }