Code Coverage
 
Lines
Branches
Paths
Functions and Methods
Classes and Traits
Total
89.47% covered (warning)
89.47%
17 / 19
85.71% covered (warning)
85.71%
12 / 14
60.00% covered (warning)
60.00%
6 / 10
60.00% covered (warning)
60.00%
3 / 5
CRAP
0.00% covered (danger)
0.00%
0 / 1
InstanceAccessControlHandler
89.47% covered (warning)
89.47%
17 / 19
85.71% covered (warning)
85.71%
12 / 14
60.00% covered (warning)
60.00%
6 / 10
60.00% covered (warning)
60.00%
3 / 5
14.18
0.00% covered (danger)
0.00%
0 / 1
 __construct
100.00% covered (success)
100.00%
1 / 1
100.00% covered (success)
100.00%
1 / 1
100.00% covered (success)
100.00%
1 / 1
100.00% covered (success)
100.00%
1 / 1
1
 createInstance
100.00% covered (success)
100.00%
4 / 4
100.00% covered (success)
100.00%
1 / 1
100.00% covered (success)
100.00%
1 / 1
100.00% covered (success)
100.00%
1 / 1
1
 checkAccess
80.00% covered (warning)
80.00%
4 / 5
66.67% covered (warning)
66.67%
2 / 3
50.00% covered (danger)
50.00%
1 / 2
0.00% covered (danger)
0.00%
0 / 1
2.50
 checkProfileAccess
66.67% covered (warning)
66.67%
2 / 3
66.67% covered (warning)
66.67%
2 / 3
50.00% covered (danger)
50.00%
1 / 2
0.00% covered (danger)
0.00%
0 / 1
2.50
 checkBuildableAccess
100.00% covered (success)
100.00%
6 / 6
100.00% covered (success)
100.00%
6 / 6
50.00% covered (danger)
50.00%
2 / 4
100.00% covered (success)
100.00%
1 / 1
4.12
1<?php
2
3declare(strict_types=1);
4
5namespace Drupal\display_builder;
6
7use Drupal\Core\Access\AccessResult;
8use Drupal\Core\Access\AccessResultInterface;
9use Drupal\Core\Entity\EntityAccessControlHandler;
10use Drupal\Core\Entity\EntityHandlerInterface;
11use Drupal\Core\Entity\EntityInterface;
12use Drupal\Core\Entity\EntityTypeInterface;
13use Drupal\Core\Session\AccountInterface;
14use Symfony\Component\DependencyInjection\ContainerInterface;
15
16/**
17 * Defines the access control handler for the instance entity type.
18 */
19final class InstanceAccessControlHandler extends EntityAccessControlHandler implements EntityHandlerInterface {
20
21  /**
22   * {@inheritdoc}
23   */
24  public function __construct(
25    EntityTypeInterface $entity_type,
26    protected readonly DisplayBuildablePluginManager $displayBuildableManager,
27  ) {
28    parent::__construct($entity_type);
29  }
30
31  /**
32   * {@inheritdoc}
33   */
34  public static function createInstance(ContainerInterface $container, EntityTypeInterface $entity_type): static {
35    return new self(
36      $entity_type,
37      $container->get('plugin.manager.display_buildable'),
38    );
39  }
40
41  /**
42   * {@inheritdoc}
43   */
44  protected function checkAccess(EntityInterface $entity, $operation, AccountInterface $account): AccessResultInterface {
45    /** @var \Drupal\display_builder\InstanceInterface $entity */
46    // 1. Profile-related access.
47    $profile_result = $this->checkProfileAccess($entity, $account);
48
49    if ($profile_result->isForbidden()) {
50      return $profile_result;
51    }
52    // 2. Access to DisplayBuildableInterface implementation.
53    $buildable_result = $this->checkBuildableAccess($entity, $account);
54
55    return $profile_result->andIf($buildable_result);
56  }
57
58  /**
59   * Checks permission to use the profile.
60   *
61   * @param \Drupal\display_builder\InstanceInterface $instance
62   *   The entity for which to check access.
63   * @param \Drupal\Core\Session\AccountInterface $account
64   *   The user session for which to check access.
65   *
66   * @return \Drupal\Core\Access\AccessResultInterface
67   *   The access result.
68   */
69  private function checkProfileAccess(InstanceInterface $instance, AccountInterface $account): AccessResultInterface {
70    if ($profile = $instance->getProfile()) {
71      return $profile->access('view', $account, TRUE);
72    }
73
74    // If the profile does not exist, forbid access to this instance.
75    return AccessResult::forbidden('Invalid profileId on display_builder_instance.');
76  }
77
78  /**
79   * Checks access based on instance prefix/type.
80   *
81   * @param \Drupal\display_builder\InstanceInterface $instance
82   *   The entity for which to check access.
83   * @param \Drupal\Core\Session\AccountInterface $account
84   *   The user session for which to check access.
85   *
86   * @return \Drupal\Core\Access\AccessResultInterface
87   *   The access result.
88   */
89  private function checkBuildableAccess(InstanceInterface $instance, AccountInterface $account): AccessResultInterface {
90    $instance_id = (string) $instance->id();
91    $providers = $this->displayBuildableManager->getDefinitions();
92
93    foreach ($providers as $provider) {
94      if (\str_starts_with($instance_id, $provider['instance_prefix'])) {
95        return $provider['class']::checkAccess($instance_id, $account);
96      }
97    }
98
99    // If an instance is not managed by a provider (for example: a demo or a
100    // test), we allow.
101    return AccessResult::allowed();
102  }
103
104}