diff --git a/core/modules/contact/contact.module b/core/modules/contact/contact.module index f6fc4cd..93a8ec0 100644 --- a/core/modules/contact/contact.module +++ b/core/modules/contact/contact.module @@ -7,6 +7,7 @@ use Drupal\Core\Form\FormStateInterface; use Drupal\Core\Routing\RouteMatchInterface; +use Drupal\Core\Url; /** * Implements hook_help(). @@ -31,9 +32,13 @@ function contact_help($route_name, RouteMatchInterface $route_match) { return $output; case 'contact.form_list': - $output = '

' . t('Add one or more forms on this page to set up your site-wide contact form.', array('@form' => \Drupal::url('contact.site_page'))) . '

'; - $output .= '

' . t('A Contact menu item is added to the Footer menu, which you can modify on the Menus administration page.', array('@menu-settings' => \Drupal::url('menu_ui.overview_page'))) . '

'; + $output = '

' . t('Create seperate contact forms for different purposes.') . '

'; $output .= '

' . t('If you would like additional text to appear on the site-wide contact page, use a block. You can create and edit blocks on the Blocks administration page.', array('@blocks' => \Drupal::url('block.admin_display'))) . '

'; + if (\Drupal::moduleHandler()->moduleExists('block')) { + $output .= '

' . t('Each form gets a link in the Contact forms block. You can enable this block on the Block layout page.', array( + '@block' => Url::fromRoute('block.admin_display')->toString(), + )); + } return $output; } } diff --git a/core/modules/contact/src/ContactFormListBuilder.php b/core/modules/contact/src/ContactFormListBuilder.php index 883ad9a..6de4c27 100644 --- a/core/modules/contact/src/ContactFormListBuilder.php +++ b/core/modules/contact/src/ContactFormListBuilder.php @@ -10,6 +10,8 @@ use Drupal\Component\Utility\String; use Drupal\Core\Config\Entity\ConfigEntityListBuilder; use Drupal\Core\Entity\EntityInterface; +use Drupal\Core\Routing\LinkGeneratorTrait; +use Drupal\Core\Url; /** * Defines a class to build a listing of contact form entities. @@ -24,7 +26,7 @@ class ContactFormListBuilder extends ConfigEntityListBuilder { public function buildHeader() { $header['form'] = t('Form'); $header['recipients'] = t('Recipients'); - $header['selected'] = t('Selected'); + $header['default'] = t('Default'); return $header + parent::buildHeader(); } @@ -32,16 +34,17 @@ public function buildHeader() { * {@inheritdoc} */ public function buildRow(EntityInterface $entity) { - $row['form'] = $this->getLabel($entity); // Special case the personal form. if ($entity->id() == 'personal') { + $row['form'] = $this->getLabel($entity); $row['recipients'] = t('Selected user'); - $row['selected'] = t('No'); + $row['default'] = t('No'); } else { + $row['form'] = $entity->link($this->getLabel($entity), 'submit-form'); $row['recipients'] = String::checkPlain(implode(', ', $entity->getRecipients())); $default_form = \Drupal::config('contact.settings')->get('default_form'); - $row['selected'] = ($default_form == $entity->id() ? t('Yes') : t('No')); + $row['default'] = ($default_form == $entity->id() ? t('Yes') : t('No')); } return $row + parent::buildRow($entity); } diff --git a/core/modules/contact/src/Entity/ContactForm.php b/core/modules/contact/src/Entity/ContactForm.php index 2dd7ce3..0cad8e3 100644 --- a/core/modules/contact/src/Entity/ContactForm.php +++ b/core/modules/contact/src/Entity/ContactForm.php @@ -7,9 +7,11 @@ namespace Drupal\contact\Entity; +use Drupal\Core\Cache\Cache; use Drupal\Core\Config\Entity\ConfigEntityBundleBase; use Drupal\contact\ContactFormInterface; use Drupal\Core\Config\Entity\ThirdPartySettingsTrait; +use Drupal\Core\Entity\EntityStorageInterface; /** * Defines the contact form entity. @@ -35,7 +37,8 @@ * }, * links = { * "delete-form" = "entity.contact_form.delete_form", - * "edit-form" = "entity.contact_form.edit_form" + * "edit-form" = "entity.contact_form.edit_form", + * "submit-form" = "contact.site_page_form", * } * ) */ diff --git a/core/modules/contact/src/Plugin/Block/ContactNavigationBlock.php b/core/modules/contact/src/Plugin/Block/ContactNavigationBlock.php new file mode 100644 index 0000000..fadbd93 --- /dev/null +++ b/core/modules/contact/src/Plugin/Block/ContactNavigationBlock.php @@ -0,0 +1,232 @@ +storage = $storage; + } + + /** + * {@inheritdoc} + */ + public static function create(ContainerInterface $container, array $configuration, $plugin_id, $plugin_definition) { + return new static( + $configuration, + $plugin_id, + $plugin_definition, + $container->get('entity.manager')->getStorage('contact_form') + ); + } + + /** + * {@inheritdoc} + */ + public function defaultConfiguration() { + return [ + 'forms' => [], + 'cache' => ['max_age' => Cache::PERMANENT], + ]; + } + + /** + * {@inheritdoc} + */ + public function getCacheTags() { + $cache_tags = parent::getCacheTags(); + if ($forms = array_keys($this->configuration['forms'])) { + foreach ($this->storage->loadMultiple($forms) as $form) { + $cache_tags = Cache::mergeTags($cache_tags, $form->getCacheTags()); + } + } + return $cache_tags; + } + + /** + * {@inheritdoc} + */ + protected function getRequiredCacheContexts() { + // This blocks must be cached per role: different roles may have access to + // contact forms. + return ['cache_context.user.roles']; + } + + /** + * {@inheritdoc} + */ + protected function blockAccess(AccountInterface $account) { + // Only grant access to users with the 'access site-wide contact form' + // permission. + return $account->hasPermission('access site-wide contact form'); + } + + /** + * {@inheritdoc} + */ + public function blockForm($form, FormStateInterface $form_state) { + $form['forms'] = [ + '#type' => 'table', + '#header' => [ + 'label' => $this->t('Form'), + 'display' => $this->t('Display'), + 'weight' => $this->t('Weight'), + ], + '#empty' => $this->t('There is no contact forms yet. Create one.'), + '#tabledrag' => [ + [ + 'action' => 'order', + 'relationship' => 'sibling', + 'group' => 'weight', + ], + ], + ]; + + $contact_forms = $this->configuration['forms']; + $rows = []; + $min_weight = 0; + /** @var \Drupal\contact\ContactFormInterface $contact_form */ + foreach ($this->storage->loadMultiple() as $id => $contact_form) { + // Do not list personal contact form. + if ($id == 'personal') { + continue; + } + + $row_label = $contact_form->label(); + $row_weight = $contact_form->getWeight(); + $row_display = TRUE; + + if ($contact_forms) { + // Display only selected forms by default if there are any. + $row_display = isset($contact_forms[$id]); + // Find lowest weight to display selected forms first. + $min_weight = min($min_weight, $row_weight); + } + $row = [ + 'label' => ['#markup' => String::checkPlain($row_label)], + 'display' => [ + '#type' => 'checkbox', + '#default_value' => $row_display, + '#title' => t('Display the @title', ['@title' => $row_label]), + '#title_display' => 'invisible', + ], + // Add weight column. + 'weight' => [ + '#type' => 'weight', + '#title' => $this->t('Weight for @title', ['@title' => $row_label]), + '#title_display' => 'invisible', + '#default_value' => $row_weight, + '#attributes' => ['class' => ['weight']], + ], + ]; + $row['#attributes']['class'][] = 'draggable'; + $row['#weight'] = $row_weight; + $rows[$contact_form->id()] = $row; + } + + if ($contact_forms) { + // Move selected categories to the top of the list. + $min_weight = $min_weight - count($contact_forms); + foreach ($contact_forms as $id => $data) { + if (isset($rows[$id])) { + $rows[$id]['#weight'] = $min_weight; + $rows[$id]['weight']['#default_value'] = $min_weight++; + } + } + } + + uasort($rows, '\Drupal\Component\Utility\SortArray::sortByWeightProperty'); + $form['forms'] += $rows; + + return $form; + } + + /** + * {@inheritdoc} + */ + public function blockValidate($form, FormStateInterface $form_state) { + $contact_forms = []; + foreach ($form_state->getValue('forms') as $id => $value) { + if ($value['display']) { + $contact_forms[$id] = $value['weight']; + } + } + if (empty($contact_forms)) { + $form_state->setErrorByName('forms', $this->t('At least one category should be selected.')); + } + $form_state->setValue('forms', $contact_forms); + } + + /** + * {@inheritdoc} + */ + public function blockSubmit($form, FormStateInterface $form_state) { + $this->configuration['forms'] = $form_state->getValue('forms'); + } + + /** + * {@inheritdoc} + */ + public function build() { + $links = []; + /** @var \Drupal\contact\ContactFormInterface $contact_form */ + foreach ($this->storage->loadMultiple(array_keys($this->configuration['forms'])) as $id => $contact_form) { + $links[$id] = $contact_form->link($contact_form->label(), 'submit-form', [ + 'set_active_class' => TRUE, + ]); + } + return [ + '#theme' => 'item_list__contact', + '#items' => $links, + '#attributes' => [ + 'class' => ['menu'], + ] + ]; + } + +} diff --git a/core/modules/contact/src/Tests/ContactSitewideTest.php b/core/modules/contact/src/Tests/ContactSitewideTest.php index 7e6207f..26a39d7 100644 --- a/core/modules/contact/src/Tests/ContactSitewideTest.php +++ b/core/modules/contact/src/Tests/ContactSitewideTest.php @@ -234,7 +234,7 @@ function testSiteWideContact() { // Find out in which row the form we want to add a field to is. $i = 0; foreach($this->xpath('//table/tbody/tr') as $row) { - if (((string)$row->td[0]) == $label) { + if (((string)$row->td[0]->a) == $label) { break; } $i++;