DomainNavBlock.php 6.7 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217
  1. <?php
  2. namespace Drupal\domain\Plugin\Block;
  3. use Drupal\Core\Access\AccessResult;
  4. use Drupal\Core\Form\FormStateInterface;
  5. use Drupal\Core\Session\AccountInterface;
  6. use Drupal\Core\Link;
  7. use Drupal\Core\Url;
  8. /**
  9. * Provides a block that links to all active domains.
  10. *
  11. * @Block(
  12. * id = "domain_nav_block",
  13. * admin_label = @Translation("Domain navigation")
  14. * )
  15. */
  16. class DomainNavBlock extends DomainBlockBase {
  17. /**
  18. * An array of settings.
  19. *
  20. * @var string[]
  21. */
  22. public $settings = [];
  23. /**
  24. * {@inheritdoc}
  25. */
  26. public function getCacheContexts() {
  27. // By default, all domain blocks are per-url. This block, though, can be
  28. // cached by url.site if we are printing the homepage path, not the request.
  29. if ($this->getSetting('link_options') == 'home') {
  30. return ['url.site'];
  31. }
  32. return ['url'];
  33. }
  34. /**
  35. * {@inheritdoc}
  36. */
  37. public function blockForm($form, FormStateInterface $form_state) {
  38. $defaults = $this->defaultConfiguration();
  39. $elements['link_options'] = [
  40. '#title' => $this->t('Link paths'),
  41. '#type' => 'radios',
  42. '#required' => TRUE,
  43. '#options' => ['active' => $this->t('Link to active url'), 'home' => $this->t('Link to site home page')],
  44. '#default_value' => !empty($this->configuration['link_options']) ? $this->configuration['link_options'] : $defaults['link_options'],
  45. '#description' => $this->t('Determines how links to each domain will be written. Note that some paths may not be accessible on all domains.'),
  46. ];
  47. $options = [
  48. 'select' => $this->t('JavaScript select list'),
  49. 'menus' => $this->t('Menu-style tab links'),
  50. 'ul' => $this->t('Unordered list of links'),
  51. ];
  52. $elements['link_theme'] = [
  53. '#type' => 'radios',
  54. '#title' => t('Link theme'),
  55. '#default_value' => !empty($this->configuration['link_theme']) ? $this->configuration['link_theme'] : $defaults['link_theme'],
  56. '#options' => $options,
  57. '#description' => $this->t('Select how to display the block output.'),
  58. ];
  59. $options = [
  60. 'name' => $this->t('The domain display name'),
  61. 'hostname' => $this->t('The raw hostname'),
  62. 'url' => $this->t('The domain base URL'),
  63. ];
  64. $elements['link_label'] = [
  65. '#type' => 'radios',
  66. '#title' => $this->t('Link text'),
  67. '#default_value' => !empty($this->configuration['link_label']) ? $this->configuration['link_label'] : $defaults['link_label'],
  68. '#options' => $options,
  69. '#description' => $this->t('Select the text to display for each link.'),
  70. ];
  71. return $elements;
  72. }
  73. /**
  74. * {@inheritdoc}
  75. */
  76. public function blockSubmit($form, FormStateInterface $form_state) {
  77. // Process the block's submission handling if no errors occurred only.
  78. if (!$form_state->getErrors()) {
  79. foreach (array_keys($this->defaultConfiguration()) as $element) {
  80. $this->configuration[$element] = $form_state->getValue($element);
  81. }
  82. }
  83. }
  84. /**
  85. * Overrides \Drupal\block\BlockBase::access().
  86. */
  87. public function access(AccountInterface $account, $return_as_object = FALSE) {
  88. $access = AccessResult::allowedIfHasPermissions($account, ['administer domains', 'use domain nav block'], 'OR');
  89. return $return_as_object ? $access : $access->isAllowed();
  90. }
  91. /**
  92. * Build the output.
  93. */
  94. public function build() {
  95. /** @var \Drupal\domain\DomainInterface $active_domain */
  96. $active_domain = \Drupal::service('domain.negotiator')->getActiveDomain();
  97. $access_handler = \Drupal::entityTypeManager()->getAccessControlHandler('domain');
  98. $account = \Drupal::currentUser();
  99. // Determine the visible domain list.
  100. $items = [];
  101. $add_path = ($this->getSetting('link_options') == 'active');
  102. /** @var \Drupal\domain\DomainInterface $domain */
  103. foreach (\Drupal::entityTypeManager()->getStorage('domain')->loadMultipleSorted() as $domain) {
  104. // Set the URL.
  105. $options = ['absolute' => TRUE, 'https' => ($domain->getScheme() == 'https')];
  106. if ($add_path) {
  107. $url = Url::fromUri($domain->getUrl(), $options);
  108. }
  109. else {
  110. $url = Url::fromUri($domain->getPath(), $options);
  111. }
  112. // Set the label text.
  113. $label = $domain->label();
  114. if ($this->getSetting('link_label') == 'hostname') {
  115. $label = $domain->getHostname();
  116. }
  117. elseif ($this->getSetting('link_label') == 'url') {
  118. $label = $domain->getPath();
  119. }
  120. // Handles menu links.
  121. if ($domain->status() || $account->hasPermission('access inactive domains')) {
  122. if ($this->getSetting('link_theme') == 'menus') {
  123. // @TODO: active trail isn't working properly, likely because this
  124. // isn't really a menu.
  125. $items[] = [
  126. 'title' => $label,
  127. 'url' => $url,
  128. 'attributes' => [],
  129. 'below' => [],
  130. 'is_expanded' => FALSE,
  131. 'is_collapsed' => FALSE,
  132. 'in_active_trail' => $domain->isActive(),
  133. ];
  134. }
  135. elseif ($this->getSetting('link_theme') == 'select') {
  136. $items[] = [
  137. 'label' => $label,
  138. 'url' => $url->toString(),
  139. 'active' => $domain->isActive(),
  140. ];
  141. }
  142. else {
  143. $items[] = ['#markup' => Link::fromTextAndUrl($label, $url)->toString()];
  144. }
  145. }
  146. }
  147. // Set the proper theme.
  148. switch ($this->getSetting('link_theme')) {
  149. case 'select':
  150. $build['#theme'] = 'domain_nav_block';
  151. $build['#items'] = $items;
  152. break;
  153. case 'menus':
  154. // Map the $items params to what menu.html.twig expects.
  155. $build['#items'] = $items;
  156. $build['#menu_name'] = 'domain-nav';
  157. $build['#sorted'] = TRUE;
  158. $build['#theme'] = 'menu__' . strtr($build['#menu_name'], '-', '_');
  159. break;
  160. case 'ul':
  161. default:
  162. $build['#theme'] = 'item_list';
  163. $build['#items'] = $items;
  164. break;
  165. }
  166. return $build;
  167. }
  168. /**
  169. * {@inheritdoc}
  170. */
  171. public function defaultConfiguration() {
  172. return [
  173. 'link_options' => 'home',
  174. 'link_theme' => 'ul',
  175. 'link_label' => 'name',
  176. ];
  177. }
  178. /**
  179. * Gets the configuration for the block, loading defaults if not set.
  180. *
  181. * @param string $key
  182. * The setting key to retrieve, a string.
  183. *
  184. * @return string
  185. * The setting value, a string.
  186. */
  187. public function getSetting($key) {
  188. if (isset($this->settings[$key])) {
  189. return $this->settings[$key];
  190. }
  191. $defaults = $this->defaultConfiguration();
  192. if (isset($this->configuration[$key])) {
  193. $this->settings[$key] = $this->configuration[$key];
  194. }
  195. else {
  196. $this->settings[$key] = $defaults[$key];
  197. }
  198. return $this->settings[$key];
  199. }
  200. }