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