Issue #3386313 by kksandr, mxr576, smustgrave, longwave, catch: The entity link label formatter should check URL access
(cherry picked from commit 85dc67bfa7
)
merge-requests/10102/head
parent
0bc0cb23a1
commit
e6525b08a6
|
@ -2,6 +2,7 @@
|
|||
|
||||
namespace Drupal\Core\Field\Plugin\Field\FieldFormatter;
|
||||
|
||||
use Drupal\Core\Cache\CacheableMetadata;
|
||||
use Drupal\Core\Entity\EntityInterface;
|
||||
use Drupal\Core\Entity\Exception\UndefinedLinkTemplateException;
|
||||
use Drupal\Core\Field\Attribute\FieldFormatter;
|
||||
|
@ -61,7 +62,9 @@ class EntityReferenceLabelFormatter extends EntityReferenceFormatterBase {
|
|||
$output_as_link = $this->getSetting('link');
|
||||
|
||||
foreach ($this->getEntitiesToView($items, $langcode) as $delta => $entity) {
|
||||
$elements[$delta] = ['#entity' => $entity];
|
||||
$label = $entity->label();
|
||||
$cacheability = CacheableMetadata::createFromObject($entity);
|
||||
// If the link is to be displayed and the entity has a uri, display a
|
||||
// link.
|
||||
if ($output_as_link && !$entity->isNew()) {
|
||||
|
@ -74,31 +77,38 @@ class EntityReferenceLabelFormatter extends EntityReferenceFormatterBase {
|
|||
// entity type doesn't have a link template nor a valid
|
||||
// "uri_callback", so don't bother trying to output a link for the
|
||||
// rest of the referenced entities.
|
||||
$output_as_link = FALSE;
|
||||
$elements[$delta]['#plain_text'] = $label;
|
||||
$cacheability->applyTo($elements[$delta]);
|
||||
continue;
|
||||
}
|
||||
}
|
||||
|
||||
if ($output_as_link && isset($uri) && !$entity->isNew()) {
|
||||
$elements[$delta] = [
|
||||
'#type' => 'link',
|
||||
'#title' => $label,
|
||||
'#url' => $uri,
|
||||
'#options' => $uri->getOptions(),
|
||||
];
|
||||
$uri_access = $uri->access(return_as_object: TRUE);
|
||||
$cacheability->addCacheableDependency($uri_access);
|
||||
if ($uri_access->isAllowed()) {
|
||||
$elements[$delta] += [
|
||||
'#type' => 'link',
|
||||
'#title' => $label,
|
||||
'#url' => $uri,
|
||||
'#options' => $uri->getOptions(),
|
||||
];
|
||||
|
||||
if (!empty($items[$delta]->_attributes)) {
|
||||
$elements[$delta]['#options'] += ['attributes' => []];
|
||||
$elements[$delta]['#options']['attributes'] += $items[$delta]->_attributes;
|
||||
// Unset field item attributes since they have been included in the
|
||||
// formatter output and shouldn't be rendered in the field template.
|
||||
unset($items[$delta]->_attributes);
|
||||
if (!empty($items[$delta]->_attributes)) {
|
||||
$elements[$delta]['#options'] += ['attributes' => []];
|
||||
$elements[$delta]['#options']['attributes'] += $items[$delta]->_attributes;
|
||||
// Unset field item attributes since they have been included in the
|
||||
// formatter output and shouldn't be rendered in the field template.
|
||||
unset($items[$delta]->_attributes);
|
||||
}
|
||||
}
|
||||
else {
|
||||
$elements[$delta]['#plain_text'] = $label;
|
||||
}
|
||||
}
|
||||
else {
|
||||
$elements[$delta] = ['#plain_text' => $label];
|
||||
$elements[$delta]['#plain_text'] = $label;
|
||||
}
|
||||
$elements[$delta]['#entity'] = $entity;
|
||||
$elements[$delta]['#cache']['tags'] = $entity->getCacheTags();
|
||||
|
||||
$cacheability->applyTo($elements[$delta]);
|
||||
}
|
||||
|
||||
return $elements;
|
||||
|
|
|
@ -8,6 +8,7 @@ use Drupal\Core\Cache\Cache;
|
|||
use Drupal\Core\Cache\CacheableMetadata;
|
||||
use Drupal\Core\Field\FieldStorageDefinitionInterface;
|
||||
use Drupal\Core\Field\Plugin\Field\FieldFormatter\EntityReferenceEntityFormatter;
|
||||
use Drupal\entity_test\Entity\EntityTest;
|
||||
use Drupal\field\Entity\FieldConfig;
|
||||
use Drupal\field\Entity\FieldStorageConfig;
|
||||
use Drupal\filter\Entity\FilterFormat;
|
||||
|
@ -349,6 +350,13 @@ class EntityReferenceFormatterTest extends EntityKernelTestBase {
|
|||
$renderer = $this->container->get('renderer');
|
||||
$formatter = 'entity_reference_label';
|
||||
|
||||
// We need to create an anonymous user for access checks in the formatter.
|
||||
$this->createUser(values: [
|
||||
'uid' => 0,
|
||||
'status' => 0,
|
||||
'name' => '',
|
||||
]);
|
||||
|
||||
// The 'link' settings is TRUE by default.
|
||||
$build = $this->buildRenderArray([$this->referencedEntity, $this->unsavedReferencedEntity], $formatter);
|
||||
|
||||
|
@ -405,6 +413,15 @@ class EntityReferenceFormatterTest extends EntityKernelTestBase {
|
|||
|
||||
$build = $this->buildRenderArray([$referenced_entity_with_no_link_template], $formatter, ['link' => TRUE]);
|
||||
$this->assertEquals($referenced_entity_with_no_link_template->label(), $build[0]['#plain_text'], sprintf('The markup returned by the %s formatter is correct for an entity type with no valid link template.', $formatter));
|
||||
|
||||
// Test link visibility if the URL is not accessible.
|
||||
$entity_with_user = EntityTest::create([
|
||||
'name' => $this->randomMachineName(),
|
||||
'user_id' => $this->createUser(),
|
||||
]);
|
||||
$entity_with_user->save();
|
||||
$build = $entity_with_user->get('user_id')->view(['type' => $formatter, 'settings' => ['link' => TRUE]]);
|
||||
$this->assertEquals($build[0]['#plain_text'], $entity_with_user->get('user_id')->entity->label(), 'For inaccessible links, the label should be displayed in plain text.');
|
||||
}
|
||||
|
||||
/**
|
||||
|
|
|
@ -220,6 +220,7 @@ class MediaAccessTest extends MediaFunctionalTestBase {
|
|||
$mediaOverviewRole = $this->createRole(['access content overview', 'access media overview']);
|
||||
$this->nonAdminUser->addRole($mediaOverviewRole)->save();
|
||||
|
||||
$this->grantPermissions($role, ['access user profiles']);
|
||||
$this->drupalGet('admin/content');
|
||||
$assert_session->linkByHrefExists('/admin/content/media');
|
||||
$this->clickLink('Media');
|
||||
|
|
Loading…
Reference in New Issue