Skip to content
Snippets Groups Projects
Commit 3e1b5698 authored by Jürgen Haas's avatar Jürgen Haas
Browse files

Issue #3369325 by mxh, jurgenhaas, freelock, bradjones1: ECA Access with...

Issue #3369325 by mxh, jurgenhaas, freelock, bradjones1: ECA Access with JSONAPI - "The controller result claims to be providing relevant cache metadata, but leaked metadata was detected. Please ensure you are not rendering content too early. Returned object class: Drupal\\jsonapi\\CacheableResourceResponse."
parent 0ced8f9e
No related branches found
No related tags found
No related merge requests found
......@@ -10,6 +10,7 @@ use Drupal\Core\Cache\RefinableCacheableDependencyInterface;
use Drupal\Core\Entity\EntityInterface;
use Drupal\Core\Field\FieldDefinitionInterface;
use Drupal\Core\Field\FieldItemListInterface;
use Drupal\Core\Render\RenderContext;
use Drupal\Core\Session\AccountInterface;
use Drupal\eca_access\HookHandler;
......@@ -27,15 +28,30 @@ function _eca_access_hook_handler(): HookHandler {
* Implements hook_entity_access().
*/
function eca_access_entity_access(EntityInterface $entity, $operation, AccountInterface $account) {
/**
* @var \Drupal\Core\Render\RendererInterface $renderer
*/
$renderer = \Drupal::service('renderer');
$render_context = new RenderContext();
/** @var \Drupal\eca_access\Event\EntityAccess $event */
if ($event = _eca_access_hook_handler()->entityAccess($entity, $operation, $account)) {
if ($result = $event->getAccessResult()) {
if ($result instanceof RefinableCacheableDependencyInterface) {
// Disable caching on dynamically determined access.
$result->mergeCacheMaxAge(0);
$event = $renderer->executeInRenderContext($render_context, static function () use ($entity, $operation, $account) {
// ECA may use parts of the rendering system to evaluate access, such as
// token replacement. Cacheability metadata coming from there need to be
// collected, by wrapping the event dispatching with a render context.
return _eca_access_hook_handler()->entityAccess($entity, $operation, $account);
});
if ($event && $result = $event->getAccessResult()) {
if ($result instanceof RefinableCacheableDependencyInterface) {
// If available, add the cacheability metadata from the render context.
if (!$render_context->isEmpty()) {
$result->addCacheableDependency($render_context->pop());
}
return $result;
// Disable caching on dynamically determined access.
$result->mergeCacheMaxAge(0);
}
return $result;
}
return AccessResult::neutral();
......@@ -45,11 +61,27 @@ function eca_access_entity_access(EntityInterface $entity, $operation, AccountIn
* Implements hook_entity_field_access().
*/
function eca_access_entity_field_access($operation, FieldDefinitionInterface $field_definition, AccountInterface $account, FieldItemListInterface $items = NULL) {
// Need the field item list to retreive the according entity.
/** @var \Drupal\eca_access\Event\EntityAccess $event */
if ($items && ($event = _eca_access_hook_handler()->fieldAccess($items->getEntity(), $operation, $account, $field_definition->getName()))) {
if ($result = $event->getAccessResult()) {
if ($items) {
/**
* @var \Drupal\Core\Render\RendererInterface $renderer
*/
$renderer = \Drupal::service('renderer');
$render_context = new RenderContext();
// Need the field item list to retreive the according entity.
/** @var \Drupal\eca_access\Event\EntityAccess $event */
$event = $renderer->executeInRenderContext($render_context, static function () use ($items, $operation, $account, $field_definition) {
// ECA may use parts of the rendering system to evaluate access, such as
// token replacement. Cacheability metadata coming from there need to be
// collected, by wrapping the event dispatching with a render context.
return _eca_access_hook_handler()->fieldAccess($items->getEntity(), $operation, $account, $field_definition->getName());
});
if ($event && $result = $event->getAccessResult()) {
if ($result instanceof RefinableCacheableDependencyInterface) {
// If available, add the cacheability metadata from the render context.
if (!$render_context->isEmpty()) {
$result->addCacheableDependency($render_context->pop());
}
// Disable caching on dynamically determined access.
$result->mergeCacheMaxAge(0);
}
......@@ -68,16 +100,30 @@ function eca_access_entity_create_access(AccountInterface $account, array $conte
// Entities without bundles usually use the entity type ID, e.g. users.
$entity_bundle = $context['entity_type_id'];
}
/**
* @var \Drupal\Core\Render\RendererInterface $renderer
*/
$renderer = \Drupal::service('renderer');
$render_context = new RenderContext();
/** @var \Drupal\eca_access\Event\CreateAccess $event */
if ($event = _eca_access_hook_handler()->createAccess($context, $entity_bundle, $account)) {
if ($result = $event->getAccessResult()) {
if ($result instanceof RefinableCacheableDependencyInterface) {
// Disable caching on dynamically determined access.
$result->mergeCacheMaxAge(0);
$event = $renderer->executeInRenderContext($render_context, static function () use ($context, $entity_bundle, $account) {
// ECA may use parts of the rendering system to evaluate access, such as
// token replacement. Cacheability metadata coming from there need to be
// collected, by wrapping the event dispatching with a render context.
return _eca_access_hook_handler()->createAccess($context, $entity_bundle, $account);
});
if ($event && $result = $event->getAccessResult()) {
if ($result instanceof RefinableCacheableDependencyInterface) {
// If available, add the cacheability metadata from the render context.
if (!$render_context->isEmpty()) {
$result->addCacheableDependency($render_context->pop());
}
return $result;
// Disable caching on dynamically determined access.
$result->mergeCacheMaxAge(0);
}
return $result;
}
return AccessResult::neutral();
......
0% Loading or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment