Code Coverage
 
Lines
Branches
Paths
Functions and Methods
Classes and Traits
Total
97.37% covered (success)
97.37%
37 / 38
97.22% covered (success)
97.22%
35 / 36
2.80% covered (danger)
2.80%
4 / 143
80.00% covered (warning)
80.00%
4 / 5
CRAP
0.00% covered (danger)
0.00%
0 / 1
IslandPluginManager
97.37% covered (success)
97.37%
37 / 38
97.22% covered (success)
97.22%
35 / 36
2.80% covered (danger)
2.80%
4 / 143
80.00% covered (warning)
80.00%
4 / 5
315.56
0.00% covered (danger)
0.00%
0 / 1
 __construct
100.00% covered (success)
100.00%
3 / 3
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
 getIslandsByTypes
100.00% covered (success)
100.00%
9 / 9
100.00% covered (success)
100.00%
10 / 10
8.33% covered (danger)
8.33%
1 / 12
100.00% covered (success)
100.00%
1 / 1
24.26
 createInstances
100.00% covered (success)
100.00%
8 / 8
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
 findDefinitions
92.31% covered (success)
92.31%
12 / 13
95.00% covered (success)
95.00%
19 / 20
0.00% covered (danger)
0.00%
0 / 126
0.00% covered (danger)
0.00%
0 / 1
9.04
 sortListByWeight
100.00% covered (success)
100.00%
5 / 5
100.00% covered (success)
100.00%
4 / 4
33.33% covered (danger)
33.33%
1 / 3
100.00% covered (success)
100.00%
1 / 1
3.19
1<?php
2
3declare(strict_types=1);
4
5namespace Drupal\display_builder\Island;
6
7use Drupal\Core\Cache\CacheBackendInterface;
8use Drupal\Core\Extension\ModuleHandlerInterface;
9use Drupal\Core\Plugin\DefaultPluginManager;
10use Drupal\display_builder\Attribute\Island;
11
12/**
13 * Island plugin manager.
14 */
15final class IslandPluginManager extends DefaultPluginManager implements IslandPluginManagerInterface {
16
17  public function __construct(\Traversable $namespaces, CacheBackendInterface $cache_backend, ModuleHandlerInterface $module_handler) {
18    parent::__construct('Plugin/display_builder/Island', $namespaces, $module_handler, IslandInterface::class, Island::class);
19    $this->alterInfo('island_info');
20    $this->setCacheBackend($cache_backend, 'island_plugins');
21  }
22
23  /**
24   * {@inheritdoc}
25   */
26  public function getIslandsByTypes(array $contexts = [], array $configuration = [], ?array $filter_by_island = NULL): array {
27    $result = [];
28
29    foreach ($this->createInstances($this->getDefinitions(), $contexts, $configuration) as $island_id => $island) {
30      if ($filter_by_island && !isset($filter_by_island[$island_id])) {
31        continue;
32      }
33      /** @var \Drupal\display_builder\Island\IslandType $type */
34      $type = $island->getPluginDefinition()['type'];
35      $result[$type->value][$island_id] = $island;
36    }
37
38    if ($filter_by_island) {
39      $result = $this->sortListByWeight($result, $filter_by_island);
40    }
41
42    return $result;
43  }
44
45  /**
46   * Create a plugin instances for each definition.
47   *
48   * @param array $definitions
49   *   An array of definitions.
50   * @param \Drupal\Core\Plugin\Context\ContextInterface[] $contexts
51   *   (Optional) An array of contexts, keyed by context name.
52   * @param array $configuration
53   *   (Optional) An array of configuration.
54   *
55   * @return array
56   *   A list of fully configured plugin instances.
57   */
58  public function createInstances(array $definitions, array $contexts = [], array $configuration = []): array {
59    return \array_map(
60      function ($definition) use ($configuration, $contexts) {
61        $config = $configuration[$definition['id']] ?? [];
62        $config['contexts'] = $contexts;
63
64        return $this->createInstance($definition['id'], $config);
65      },
66      $definitions,
67    );
68  }
69
70  /**
71   * {@inheritdoc}
72   */
73  protected function findDefinitions() {
74    $definitions = $this->getDiscovery()->getDefinitions();
75
76    foreach ($definitions as $plugin_id => &$definition) {
77      $this->processDefinition($definition, $plugin_id);
78    }
79    $this->alterDefinitions($definitions);
80
81    // If this plugin was provided by a module that does not exist, remove the
82    // plugin definition.
83    foreach ($definitions as $plugin_id => $plugin_definition) {
84      $provider = $this->extractProviderFromDefinition($plugin_definition);
85
86      if ($provider && !\in_array($provider, ['core', 'component'], TRUE) && !$this->providerExists($provider)) {
87        unset($definitions[$plugin_id]);
88      }
89
90      if (!empty($plugin_definition['modules'] ?? [])) {
91        foreach ($plugin_definition['modules'] as $module) {
92          if (!$this->moduleHandler->moduleExists($module)) {
93            unset($definitions[$plugin_id]);
94          }
95        }
96      }
97    }
98
99    return $definitions;
100  }
101
102  /**
103   * Sort by comparison a list.
104   *
105   * @param array $list
106   *   The list to sort.
107   * @param array<int,mixed> $weight
108   *   The weigh mapping as id => weight.
109   *
110   * @return array<int,mixed>
111   *   The sorted list.
112   */
113  private function sortListByWeight(array $list, array $weight): array {
114    foreach ($list as &$items) {
115      \uksort($items, static function ($a, $b) use ($weight) {
116        return $weight[$a] <=> $weight[$b];
117      });
118    }
119
120    return $list;
121  }
122
123}