Chris@0
|
1 <?php
|
Chris@0
|
2
|
Chris@0
|
3 namespace Drupal\block\Controller;
|
Chris@0
|
4
|
Chris@0
|
5 use Drupal\Component\Serialization\Json;
|
Chris@0
|
6 use Drupal\Core\Block\BlockManagerInterface;
|
Chris@0
|
7 use Drupal\Core\Controller\ControllerBase;
|
Chris@0
|
8 use Drupal\Core\EventSubscriber\MainContentViewSubscriber;
|
Chris@0
|
9 use Drupal\Core\Menu\LocalActionManagerInterface;
|
Chris@0
|
10 use Drupal\Core\Plugin\Context\LazyContextRepository;
|
Chris@0
|
11 use Drupal\Core\Routing\RouteMatchInterface;
|
Chris@0
|
12 use Drupal\Core\Url;
|
Chris@0
|
13 use Symfony\Component\DependencyInjection\ContainerInterface;
|
Chris@0
|
14 use Symfony\Component\HttpFoundation\Request;
|
Chris@0
|
15
|
Chris@0
|
16 /**
|
Chris@0
|
17 * Provides a list of block plugins to be added to the layout.
|
Chris@0
|
18 */
|
Chris@0
|
19 class BlockLibraryController extends ControllerBase {
|
Chris@0
|
20
|
Chris@0
|
21 /**
|
Chris@0
|
22 * The block manager.
|
Chris@0
|
23 *
|
Chris@0
|
24 * @var \Drupal\Core\Block\BlockManagerInterface
|
Chris@0
|
25 */
|
Chris@0
|
26 protected $blockManager;
|
Chris@0
|
27
|
Chris@0
|
28 /**
|
Chris@0
|
29 * The context repository.
|
Chris@0
|
30 *
|
Chris@0
|
31 * @var \Drupal\Core\Plugin\Context\LazyContextRepository
|
Chris@0
|
32 */
|
Chris@0
|
33 protected $contextRepository;
|
Chris@0
|
34
|
Chris@0
|
35 /**
|
Chris@0
|
36 * The route match.
|
Chris@0
|
37 *
|
Chris@0
|
38 * @var \Drupal\Core\Routing\RouteMatchInterface
|
Chris@0
|
39 */
|
Chris@0
|
40 protected $routeMatch;
|
Chris@0
|
41
|
Chris@0
|
42 /**
|
Chris@0
|
43 * The local action manager.
|
Chris@0
|
44 *
|
Chris@0
|
45 * @var \Drupal\Core\Menu\LocalActionManagerInterface
|
Chris@0
|
46 */
|
Chris@0
|
47 protected $localActionManager;
|
Chris@0
|
48
|
Chris@0
|
49 /**
|
Chris@0
|
50 * Constructs a BlockLibraryController object.
|
Chris@0
|
51 *
|
Chris@0
|
52 * @param \Drupal\Core\Block\BlockManagerInterface $block_manager
|
Chris@0
|
53 * The block manager.
|
Chris@0
|
54 * @param \Drupal\Core\Plugin\Context\LazyContextRepository $context_repository
|
Chris@0
|
55 * The context repository.
|
Chris@0
|
56 * @param \Drupal\Core\Routing\RouteMatchInterface $route_match
|
Chris@0
|
57 * The current route match.
|
Chris@0
|
58 * @param \Drupal\Core\Menu\LocalActionManagerInterface $local_action_manager
|
Chris@0
|
59 * The local action manager.
|
Chris@0
|
60 */
|
Chris@0
|
61 public function __construct(BlockManagerInterface $block_manager, LazyContextRepository $context_repository, RouteMatchInterface $route_match, LocalActionManagerInterface $local_action_manager) {
|
Chris@0
|
62 $this->blockManager = $block_manager;
|
Chris@0
|
63 $this->routeMatch = $route_match;
|
Chris@0
|
64 $this->localActionManager = $local_action_manager;
|
Chris@0
|
65 $this->contextRepository = $context_repository;
|
Chris@0
|
66 }
|
Chris@0
|
67
|
Chris@0
|
68 /**
|
Chris@0
|
69 * {@inheritdoc}
|
Chris@0
|
70 */
|
Chris@0
|
71 public static function create(ContainerInterface $container) {
|
Chris@0
|
72 return new static(
|
Chris@0
|
73 $container->get('plugin.manager.block'),
|
Chris@0
|
74 $container->get('context.repository'),
|
Chris@0
|
75 $container->get('current_route_match'),
|
Chris@0
|
76 $container->get('plugin.manager.menu.local_action')
|
Chris@0
|
77 );
|
Chris@0
|
78 }
|
Chris@0
|
79
|
Chris@0
|
80 /**
|
Chris@0
|
81 * Shows a list of blocks that can be added to a theme's layout.
|
Chris@0
|
82 *
|
Chris@0
|
83 * @param \Symfony\Component\HttpFoundation\Request $request
|
Chris@0
|
84 * The current request.
|
Chris@0
|
85 * @param string $theme
|
Chris@0
|
86 * Theme key of the block list.
|
Chris@0
|
87 *
|
Chris@0
|
88 * @return array
|
Chris@0
|
89 * A render array as expected by the renderer.
|
Chris@0
|
90 */
|
Chris@0
|
91 public function listBlocks(Request $request, $theme) {
|
Chris@0
|
92 // Since modals do not render any other part of the page, we need to render
|
Chris@0
|
93 // them manually as part of this listing.
|
Chris@0
|
94 if ($request->query->get(MainContentViewSubscriber::WRAPPER_FORMAT) === 'drupal_modal') {
|
Chris@0
|
95 $build['local_actions'] = $this->buildLocalActions();
|
Chris@0
|
96 }
|
Chris@0
|
97
|
Chris@0
|
98 $headers = [
|
Chris@0
|
99 ['data' => $this->t('Block')],
|
Chris@0
|
100 ['data' => $this->t('Category')],
|
Chris@0
|
101 ['data' => $this->t('Operations')],
|
Chris@0
|
102 ];
|
Chris@0
|
103
|
Chris@17
|
104 $region = $request->query->get('region');
|
Chris@17
|
105 $weight = $request->query->get('weight');
|
Chris@17
|
106
|
Chris@0
|
107 // Only add blocks which work without any available context.
|
Chris@17
|
108 $definitions = $this->blockManager->getFilteredDefinitions('block_ui', $this->contextRepository->getAvailableContexts(), [
|
Chris@17
|
109 'theme' => $theme,
|
Chris@17
|
110 'region' => $region,
|
Chris@17
|
111 ]);
|
Chris@0
|
112 // Order by category, and then by admin label.
|
Chris@0
|
113 $definitions = $this->blockManager->getSortedDefinitions($definitions);
|
Chris@14
|
114 // Filter out definitions that are not intended to be placed by the UI.
|
Chris@14
|
115 $definitions = array_filter($definitions, function (array $definition) {
|
Chris@14
|
116 return empty($definition['_block_ui_hidden']);
|
Chris@14
|
117 });
|
Chris@0
|
118
|
Chris@0
|
119 $rows = [];
|
Chris@0
|
120 foreach ($definitions as $plugin_id => $plugin_definition) {
|
Chris@0
|
121 $row = [];
|
Chris@0
|
122 $row['title']['data'] = [
|
Chris@0
|
123 '#type' => 'inline_template',
|
Chris@0
|
124 '#template' => '<div class="block-filter-text-source">{{ label }}</div>',
|
Chris@0
|
125 '#context' => [
|
Chris@0
|
126 'label' => $plugin_definition['admin_label'],
|
Chris@0
|
127 ],
|
Chris@0
|
128 ];
|
Chris@0
|
129 $row['category']['data'] = $plugin_definition['category'];
|
Chris@0
|
130 $links['add'] = [
|
Chris@0
|
131 'title' => $this->t('Place block'),
|
Chris@0
|
132 'url' => Url::fromRoute('block.admin_add', ['plugin_id' => $plugin_id, 'theme' => $theme]),
|
Chris@0
|
133 'attributes' => [
|
Chris@0
|
134 'class' => ['use-ajax'],
|
Chris@0
|
135 'data-dialog-type' => 'modal',
|
Chris@0
|
136 'data-dialog-options' => Json::encode([
|
Chris@0
|
137 'width' => 700,
|
Chris@0
|
138 ]),
|
Chris@0
|
139 ],
|
Chris@0
|
140 ];
|
Chris@0
|
141 if ($region) {
|
Chris@0
|
142 $links['add']['query']['region'] = $region;
|
Chris@0
|
143 }
|
Chris@0
|
144 if (isset($weight)) {
|
Chris@0
|
145 $links['add']['query']['weight'] = $weight;
|
Chris@0
|
146 }
|
Chris@0
|
147 $row['operations']['data'] = [
|
Chris@0
|
148 '#type' => 'operations',
|
Chris@0
|
149 '#links' => $links,
|
Chris@0
|
150 ];
|
Chris@0
|
151 $rows[] = $row;
|
Chris@0
|
152 }
|
Chris@0
|
153
|
Chris@0
|
154 $build['#attached']['library'][] = 'block/drupal.block.admin';
|
Chris@0
|
155
|
Chris@0
|
156 $build['filter'] = [
|
Chris@0
|
157 '#type' => 'search',
|
Chris@0
|
158 '#title' => $this->t('Filter'),
|
Chris@0
|
159 '#title_display' => 'invisible',
|
Chris@0
|
160 '#size' => 30,
|
Chris@0
|
161 '#placeholder' => $this->t('Filter by block name'),
|
Chris@0
|
162 '#attributes' => [
|
Chris@0
|
163 'class' => ['block-filter-text'],
|
Chris@0
|
164 'data-element' => '.block-add-table',
|
Chris@0
|
165 'title' => $this->t('Enter a part of the block name to filter by.'),
|
Chris@0
|
166 ],
|
Chris@0
|
167 ];
|
Chris@0
|
168
|
Chris@0
|
169 $build['blocks'] = [
|
Chris@0
|
170 '#type' => 'table',
|
Chris@0
|
171 '#header' => $headers,
|
Chris@0
|
172 '#rows' => $rows,
|
Chris@0
|
173 '#empty' => $this->t('No blocks available.'),
|
Chris@0
|
174 '#attributes' => [
|
Chris@0
|
175 'class' => ['block-add-table'],
|
Chris@0
|
176 ],
|
Chris@0
|
177 ];
|
Chris@0
|
178
|
Chris@0
|
179 return $build;
|
Chris@0
|
180 }
|
Chris@0
|
181
|
Chris@0
|
182 /**
|
Chris@0
|
183 * Builds the local actions for this listing.
|
Chris@0
|
184 *
|
Chris@0
|
185 * @return array
|
Chris@0
|
186 * An array of local actions for this listing.
|
Chris@0
|
187 */
|
Chris@0
|
188 protected function buildLocalActions() {
|
Chris@0
|
189 $build = $this->localActionManager->getActionsForRoute($this->routeMatch->getRouteName());
|
Chris@0
|
190 // Without this workaround, the action links will be rendered as <li> with
|
Chris@0
|
191 // no wrapping <ul> element.
|
Chris@0
|
192 if (!empty($build)) {
|
Chris@0
|
193 $build['#prefix'] = '<ul class="action-links">';
|
Chris@0
|
194 $build['#suffix'] = '</ul>';
|
Chris@0
|
195 }
|
Chris@0
|
196 return $build;
|
Chris@0
|
197 }
|
Chris@0
|
198
|
Chris@0
|
199 }
|