Loading core/modules/layout_builder/src/Plugin/Block/FieldBlock.php +31 −7 Original line number Diff line number Diff line Loading @@ -22,6 +22,7 @@ use Drupal\Core\Plugin\ContextAwarePluginInterface; use Drupal\Core\Session\AccountInterface; use Drupal\Core\StringTranslation\TranslatableMarkup; use Drupal\field\FieldConfigInterface; use Drupal\layout_builder\Plugin\Derivative\FieldBlockDeriver; use Psr\Log\LoggerInterface; use Symfony\Component\DependencyInjection\ContainerInterface; Loading Loading @@ -212,13 +213,7 @@ protected function blockAccess(AccountInterface $account) { } // Check to see if the field has any values or a default value. if ($field->isEmpty() && !$field->getFieldDefinition()->getDefaultValue($entity)) { // @todo Remove special handling of image fields after // https://www.drupal.org/project/drupal/issues/3005528. if ($field->getFieldDefinition()->getType() === 'image' && !empty($field->getFieldDefinition()->getSetting('default_image')['uuid'])) { return $access; } if ($field->isEmpty() && !$this->entityFieldHasDefaultValue()) { return $access->andIf(AccessResult::forbidden()); } return $access; Loading Loading @@ -414,4 +409,33 @@ protected function getFormatter(array $parents, FormStateInterface $form_state) ]); } /** * Checks whether there is a default value set on the field. * * @return bool * TRUE if default value set, FALSE otherwise. */ protected function entityFieldHasDefaultValue(): bool { $entity = $this->getEntity(); $field = $entity->get($this->fieldName); $definition = $field->getFieldDefinition(); if ($definition->getDefaultValue($entity)) { return TRUE; } // @todo Remove special handling of image fields after // https://www.drupal.org/project/drupal/issues/3005528. if ($definition->getType() !== 'image') { return FALSE; } $default_image = $definition->getSetting('default_image'); // If we are dealing with a configurable field, look in both instance-level // and field-level settings. if (empty($default_image['uuid']) && ($definition instanceof FieldConfigInterface)) { $default_image = $definition->getFieldStorageDefinition()->getSetting('default_image'); } return !empty($default_image['uuid']); } } core/modules/layout_builder/tests/src/Functional/LayoutBuilderDefaultValuesTest.php +87 −18 Original line number Diff line number Diff line Loading @@ -66,14 +66,22 @@ protected function setUp(): void { 'field_string_with_default' => 'It is ok to be different', 'field_string_with_callback' => 'Not from a callback', 'field_string_late_default' => 'I am way ahead of you.', 'field_image_with_default' => [ 'target_id' => 2, 'alt' => 'My different alt text', ], 'field_image_no_default' => [ 'field_image_storage_default' => [ 'target_id' => 3, 'alt' => 'My third alt text', ], 'field_image_instance_default' => [ 'target_id' => 4, 'alt' => 'My fourth alt text', ], 'field_image_both_defaults' => [ 'target_id' => 5, 'alt' => 'My fifth alt text', ], 'field_image_no_default' => [ 'target_id' => 6, 'alt' => 'My sixth alt text', ], ]); // Create node 2 relying on defaults. Loading Loading @@ -127,16 +135,31 @@ protected function assertNodeWithValues() { $assert_session->pageTextContains('field_string_late_default'); $assert_session->pageTextNotContains('Too late!'); $assert_session->pageTextContains('I am way ahead of you'); // Image field with default should render non-default value. $assert_session->pageTextContains('field_image_with_default'); $assert_session->responseNotContains('My default alt text'); // Image field with storage default should render non-default value. $assert_session->pageTextContains('field_image_storage_default'); $assert_session->responseNotContains('My storage default alt text'); $assert_session->responseNotContains('test-file-1'); $assert_session->responseContains('My different alt text'); $assert_session->responseContains('test-file-2'); // Image field with no default should render a value. $assert_session->pageTextContains('field_image_no_default'); $assert_session->responseContains('My third alt text'); $assert_session->responseContains('test-file-3'); // Image field with instance default should render non-default value. $assert_session->pageTextContains('field_image_instance_default'); $assert_session->responseNotContains('My instance default alt text'); $assert_session->responseNotContains('test-file-1'); $assert_session->responseContains('My fourth alt text'); $assert_session->responseContains('test-file-4'); // Image field with both storage and instance defaults should render // non-default value. $assert_session->pageTextContains('field_image_both_defaults'); $assert_session->responseNotContains('My storage default alt text'); $assert_session->responseNotContains('My instance default alt text'); $assert_session->responseNotContains('test-file-1'); $assert_session->responseNotContains('test-file-2'); $assert_session->responseContains('My fifth alt text'); $assert_session->responseContains('test-file-5'); // Image field with no default should render a value. $assert_session->pageTextContains('field_image_no_default'); $assert_session->responseContains('My sixth alt text'); $assert_session->responseContains('test-file-6'); } /** Loading Loading @@ -166,9 +189,15 @@ protected function assertNodeWithDefaultValues() { $assert_session->pageTextNotContains('field_string_late_default'); $assert_session->pageTextNotContains('Too late!'); // Image field with default should render default value. $assert_session->pageTextContains('field_image_with_default'); $assert_session->responseContains('My default alt text'); $assert_session->pageTextContains('field_image_storage_default'); $assert_session->responseContains('My storage default alt text'); $assert_session->responseContains('test-file-1'); $assert_session->pageTextContains('field_image_instance_default'); $assert_session->responseContains('My instance default alt text'); $assert_session->responseContains('test-file-1'); $assert_session->pageTextContains('field_image_both_defaults'); $assert_session->responseContains('My instance default alt text'); $assert_session->responseContains('test-file-2'); // Image field with no default should not render. $assert_session->pageTextNotContains('field_image_no_default'); // Confirm that there is no DOM element for the field_image_with_no_default Loading Loading @@ -259,7 +288,7 @@ protected function addImageFields() { // Create files to use as the default images. $files = $this->drupalGetTestFiles('image'); $images = []; for ($i = 1; $i <= 3; $i++) { for ($i = 1; $i <= 6; $i++) { $filename = "test-file-$i"; $desired_filepath = 'public://' . $filename; \Drupal::service('file_system')->copy($files[0]->uri, $desired_filepath, FileSystemInterface::EXISTS_ERROR); Loading @@ -272,17 +301,57 @@ protected function addImageFields() { $images[] = $file; } $field_name = 'field_image_with_default'; $field_name = 'field_image_storage_default'; $storage_settings['default_image'] = [ 'uuid' => $images[0]->uuid(), 'alt' => 'My default alt text', 'alt' => 'My storage default alt text', 'title' => '', 'width' => 0, 'height' => 0, ]; $field_settings['default_image'] = [ 'uuid' => NULL, 'alt' => '', 'title' => '', 'width' => NULL, 'height' => NULL, ]; $widget_settings = [ 'preview_image_style' => 'medium', ]; $this->createImageField($field_name, 'test_node_type', $storage_settings, $field_settings, $widget_settings); $field_name = 'field_image_instance_default'; $storage_settings['default_image'] = [ 'uuid' => NULL, 'alt' => '', 'title' => '', 'width' => NULL, 'height' => NULL, ]; $field_settings['default_image'] = [ 'uuid' => $images[0]->uuid(), 'alt' => 'My default alt text', 'alt' => 'My instance default alt text', 'title' => '', 'width' => 0, 'height' => 0, ]; $widget_settings = [ 'preview_image_style' => 'medium', ]; $this->createImageField($field_name, 'test_node_type', $storage_settings, $field_settings, $widget_settings); $field_name = 'field_image_both_defaults'; $storage_settings['default_image'] = [ 'uuid' => $images[0]->uuid(), 'alt' => 'My storage default alt text', 'title' => '', 'width' => 0, 'height' => 0, ]; $field_settings['default_image'] = [ 'uuid' => $images[1]->uuid(), 'alt' => 'My instance default alt text', 'title' => '', 'width' => 0, 'height' => 0, Loading Loading
core/modules/layout_builder/src/Plugin/Block/FieldBlock.php +31 −7 Original line number Diff line number Diff line Loading @@ -22,6 +22,7 @@ use Drupal\Core\Plugin\ContextAwarePluginInterface; use Drupal\Core\Session\AccountInterface; use Drupal\Core\StringTranslation\TranslatableMarkup; use Drupal\field\FieldConfigInterface; use Drupal\layout_builder\Plugin\Derivative\FieldBlockDeriver; use Psr\Log\LoggerInterface; use Symfony\Component\DependencyInjection\ContainerInterface; Loading Loading @@ -212,13 +213,7 @@ protected function blockAccess(AccountInterface $account) { } // Check to see if the field has any values or a default value. if ($field->isEmpty() && !$field->getFieldDefinition()->getDefaultValue($entity)) { // @todo Remove special handling of image fields after // https://www.drupal.org/project/drupal/issues/3005528. if ($field->getFieldDefinition()->getType() === 'image' && !empty($field->getFieldDefinition()->getSetting('default_image')['uuid'])) { return $access; } if ($field->isEmpty() && !$this->entityFieldHasDefaultValue()) { return $access->andIf(AccessResult::forbidden()); } return $access; Loading Loading @@ -414,4 +409,33 @@ protected function getFormatter(array $parents, FormStateInterface $form_state) ]); } /** * Checks whether there is a default value set on the field. * * @return bool * TRUE if default value set, FALSE otherwise. */ protected function entityFieldHasDefaultValue(): bool { $entity = $this->getEntity(); $field = $entity->get($this->fieldName); $definition = $field->getFieldDefinition(); if ($definition->getDefaultValue($entity)) { return TRUE; } // @todo Remove special handling of image fields after // https://www.drupal.org/project/drupal/issues/3005528. if ($definition->getType() !== 'image') { return FALSE; } $default_image = $definition->getSetting('default_image'); // If we are dealing with a configurable field, look in both instance-level // and field-level settings. if (empty($default_image['uuid']) && ($definition instanceof FieldConfigInterface)) { $default_image = $definition->getFieldStorageDefinition()->getSetting('default_image'); } return !empty($default_image['uuid']); } }
core/modules/layout_builder/tests/src/Functional/LayoutBuilderDefaultValuesTest.php +87 −18 Original line number Diff line number Diff line Loading @@ -66,14 +66,22 @@ protected function setUp(): void { 'field_string_with_default' => 'It is ok to be different', 'field_string_with_callback' => 'Not from a callback', 'field_string_late_default' => 'I am way ahead of you.', 'field_image_with_default' => [ 'target_id' => 2, 'alt' => 'My different alt text', ], 'field_image_no_default' => [ 'field_image_storage_default' => [ 'target_id' => 3, 'alt' => 'My third alt text', ], 'field_image_instance_default' => [ 'target_id' => 4, 'alt' => 'My fourth alt text', ], 'field_image_both_defaults' => [ 'target_id' => 5, 'alt' => 'My fifth alt text', ], 'field_image_no_default' => [ 'target_id' => 6, 'alt' => 'My sixth alt text', ], ]); // Create node 2 relying on defaults. Loading Loading @@ -127,16 +135,31 @@ protected function assertNodeWithValues() { $assert_session->pageTextContains('field_string_late_default'); $assert_session->pageTextNotContains('Too late!'); $assert_session->pageTextContains('I am way ahead of you'); // Image field with default should render non-default value. $assert_session->pageTextContains('field_image_with_default'); $assert_session->responseNotContains('My default alt text'); // Image field with storage default should render non-default value. $assert_session->pageTextContains('field_image_storage_default'); $assert_session->responseNotContains('My storage default alt text'); $assert_session->responseNotContains('test-file-1'); $assert_session->responseContains('My different alt text'); $assert_session->responseContains('test-file-2'); // Image field with no default should render a value. $assert_session->pageTextContains('field_image_no_default'); $assert_session->responseContains('My third alt text'); $assert_session->responseContains('test-file-3'); // Image field with instance default should render non-default value. $assert_session->pageTextContains('field_image_instance_default'); $assert_session->responseNotContains('My instance default alt text'); $assert_session->responseNotContains('test-file-1'); $assert_session->responseContains('My fourth alt text'); $assert_session->responseContains('test-file-4'); // Image field with both storage and instance defaults should render // non-default value. $assert_session->pageTextContains('field_image_both_defaults'); $assert_session->responseNotContains('My storage default alt text'); $assert_session->responseNotContains('My instance default alt text'); $assert_session->responseNotContains('test-file-1'); $assert_session->responseNotContains('test-file-2'); $assert_session->responseContains('My fifth alt text'); $assert_session->responseContains('test-file-5'); // Image field with no default should render a value. $assert_session->pageTextContains('field_image_no_default'); $assert_session->responseContains('My sixth alt text'); $assert_session->responseContains('test-file-6'); } /** Loading Loading @@ -166,9 +189,15 @@ protected function assertNodeWithDefaultValues() { $assert_session->pageTextNotContains('field_string_late_default'); $assert_session->pageTextNotContains('Too late!'); // Image field with default should render default value. $assert_session->pageTextContains('field_image_with_default'); $assert_session->responseContains('My default alt text'); $assert_session->pageTextContains('field_image_storage_default'); $assert_session->responseContains('My storage default alt text'); $assert_session->responseContains('test-file-1'); $assert_session->pageTextContains('field_image_instance_default'); $assert_session->responseContains('My instance default alt text'); $assert_session->responseContains('test-file-1'); $assert_session->pageTextContains('field_image_both_defaults'); $assert_session->responseContains('My instance default alt text'); $assert_session->responseContains('test-file-2'); // Image field with no default should not render. $assert_session->pageTextNotContains('field_image_no_default'); // Confirm that there is no DOM element for the field_image_with_no_default Loading Loading @@ -259,7 +288,7 @@ protected function addImageFields() { // Create files to use as the default images. $files = $this->drupalGetTestFiles('image'); $images = []; for ($i = 1; $i <= 3; $i++) { for ($i = 1; $i <= 6; $i++) { $filename = "test-file-$i"; $desired_filepath = 'public://' . $filename; \Drupal::service('file_system')->copy($files[0]->uri, $desired_filepath, FileSystemInterface::EXISTS_ERROR); Loading @@ -272,17 +301,57 @@ protected function addImageFields() { $images[] = $file; } $field_name = 'field_image_with_default'; $field_name = 'field_image_storage_default'; $storage_settings['default_image'] = [ 'uuid' => $images[0]->uuid(), 'alt' => 'My default alt text', 'alt' => 'My storage default alt text', 'title' => '', 'width' => 0, 'height' => 0, ]; $field_settings['default_image'] = [ 'uuid' => NULL, 'alt' => '', 'title' => '', 'width' => NULL, 'height' => NULL, ]; $widget_settings = [ 'preview_image_style' => 'medium', ]; $this->createImageField($field_name, 'test_node_type', $storage_settings, $field_settings, $widget_settings); $field_name = 'field_image_instance_default'; $storage_settings['default_image'] = [ 'uuid' => NULL, 'alt' => '', 'title' => '', 'width' => NULL, 'height' => NULL, ]; $field_settings['default_image'] = [ 'uuid' => $images[0]->uuid(), 'alt' => 'My default alt text', 'alt' => 'My instance default alt text', 'title' => '', 'width' => 0, 'height' => 0, ]; $widget_settings = [ 'preview_image_style' => 'medium', ]; $this->createImageField($field_name, 'test_node_type', $storage_settings, $field_settings, $widget_settings); $field_name = 'field_image_both_defaults'; $storage_settings['default_image'] = [ 'uuid' => $images[0]->uuid(), 'alt' => 'My storage default alt text', 'title' => '', 'width' => 0, 'height' => 0, ]; $field_settings['default_image'] = [ 'uuid' => $images[1]->uuid(), 'alt' => 'My instance default alt text', 'title' => '', 'width' => 0, 'height' => 0, Loading