From 7a4a8c97c2ecb6cf67013305663167e05de920d2 Mon Sep 17 00:00:00 2001
From: Nathaniel Catchpole <catch@35733.no-reply.drupal.org>
Date: Wed, 9 May 2018 14:18:36 +0100
Subject: [PATCH] Issue #2923496 by mark_fullmer, dpfitzsi, krina.addweb: [Link
 module] Validation for title but no link, when title optional

---
 .../Plugin/Field/FieldWidget/LinkWidget.php   | 21 +++++++++++++++++++
 .../tests/src/Functional/LinkFieldTest.php    |  8 +++++++
 2 files changed, 29 insertions(+)

diff --git a/core/modules/link/src/Plugin/Field/FieldWidget/LinkWidget.php b/core/modules/link/src/Plugin/Field/FieldWidget/LinkWidget.php
index 56f65218e5ac..281634c46c8c 100644
--- a/core/modules/link/src/Plugin/Field/FieldWidget/LinkWidget.php
+++ b/core/modules/link/src/Plugin/Field/FieldWidget/LinkWidget.php
@@ -157,6 +157,17 @@ public static function validateTitleElement(&$element, FormStateInterface $form_
     }
   }
 
+  /**
+   * Form element validation handler for the 'title' element.
+   *
+   * Requires the URL value if a link title was filled in.
+   */
+  public static function validateTitleNoLink(&$element, FormStateInterface $form_state, $form) {
+    if ($element['uri']['#value'] === '' && $element['title']['#value'] !== '') {
+      $form_state->setError($element['uri'], t('The @uri field is required when the @title field is specified.', ['@title' => $element['title']['#title'], '@uri' => $element['uri']['#title']]));
+    }
+  }
+
   /**
    * {@inheritdoc}
    */
@@ -222,8 +233,12 @@ public function formElement(FieldItemListInterface $items, $delta, array $elemen
     // Post-process the title field to make it conditionally required if URL is
     // non-empty. Omit the validation on the field edit form, since the field
     // settings cannot be saved otherwise.
+    //
+    // Validate that title field is filled out (regardless of uri) when it is a
+    // required field.
     if (!$this->isDefaultValueWidget($form_state) && $this->getFieldSetting('title') === DRUPAL_REQUIRED) {
       $element['#element_validate'][] = [get_called_class(), 'validateTitleElement'];
+      $element['#element_validate'][] = [get_called_class(), 'validateTitleNoLink'];
 
       if (!$element['title']['#required']) {
         // Make title required on the front-end when URI filled-in.
@@ -242,6 +257,12 @@ public function formElement(FieldItemListInterface $items, $delta, array $elemen
       }
     }
 
+    // Ensure that a URI is always entered when an optional title field is
+    // submitted.
+    if (!$this->isDefaultValueWidget($form_state) && $this->getFieldSetting('title') == DRUPAL_OPTIONAL) {
+      $element['#element_validate'][] = [get_called_class(), 'validateTitleNoLink'];
+    }
+
     // Exposing the attributes array in the widget is left for alternate and more
     // advanced field widgets.
     $element['attributes'] = [
diff --git a/core/modules/link/tests/src/Functional/LinkFieldTest.php b/core/modules/link/tests/src/Functional/LinkFieldTest.php
index 32ea380a2741..e5c8cb3fa171 100644
--- a/core/modules/link/tests/src/Functional/LinkFieldTest.php
+++ b/core/modules/link/tests/src/Functional/LinkFieldTest.php
@@ -281,6 +281,14 @@ public function testLinkTitle() {
         $this->assertRaw('placeholder="Enter the text for this link"');
 
         $this->assertFieldByName("{$field_name}[0][title]", '', 'Link text field found.');
+        if ($title_setting === DRUPAL_OPTIONAL) {
+          // Verify that the URL is required, if the link text is non-empty.
+          $edit = [
+            "{$field_name}[0][title]" => 'Example',
+          ];
+          $this->drupalPostForm(NULL, $edit, t('Save'));
+          $this->assertText(t('The URL field is required when the @title field is specified.', ['@title' => t('Link text')]));
+        }
         if ($title_setting === DRUPAL_REQUIRED) {
           // Verify that the link text is required, if the URL is non-empty.
           $edit = [
-- 
GitLab