0

I am trying to come up with a solution to fix the D8 Link module to allow URLs like example.com (the most common use case, imho). I was thinking it would be simple enough to modify the submit value during a custom validate function; but regardless of what I set the value to it still validates on the original value.

In a form alter I have done this:

$form['field_linktest']['widget'][0]['#element_validate'][] = '_fix_link_field_value';

and then in that validate function I set the url uri value:

function _fix_link_field_value(&$element, FormStateInterface $form_state, &$complete_form) {
  $url = $form_state->getValue('field_linktest');
  $url[0]['uri'] = 'http://example.com';
  $form_state->setValue('field_linktest', $url);
}

But I still get the error: Manually entered paths should start with one of the following characters: / ? #

11
  • You need to also remove the original validation handler. – Jaypan Feb 24 at 3:29
  • Try using //example.com and it should auto go to http if https isn't available. – No Sssweat Feb 24 at 4:54
  • @ns.. Do you mean adjust the input in my validate to add // or do you mean type it in the form? Because the 2nd idea is silly. Sorry, but that seems to be the approach on the various issues re: this on d.org; but who would ever enter a url like that? – liquidcms Feb 24 at 5:13
  • 1
    Best not to call other people's ideas silly. We're all working through text here, and we don't know the requirements of your system. It's not going to endear some people to want to help you further. – Jaypan Feb 24 at 6:22
  • 1
    @jaypan, technically i wasn't calling NS's idea silly.. i was asking if he was suggesting the solution that the people on d.org seem to be suggesting.. and their idea of UX for this is pretty silly. But point taken. NS, i had tried just removing the validate and that didnt seem to do anything.. but i'll try your idea of just placing mine ahead. Thanks. – liquidcms Feb 24 at 15:12
0

Thanks to those who provided answers; I couldn't quite get those to work, but they got me to my answer. My final solution ended up being this:

function my_module_form_alter(&$form, $form_state, $form_id) {
  // add a global validator to fix stupid Link fields - add to all Link fields
  // only worry about entity forms
  if (isset($form['#entity_type'])) {
    $bundle = $form_state->getFormObject()->getEntity()->bundle();
    $entity_type = $form['#entity_type'];
    $entityFieldManager = \Drupal::service('entity_field.manager');
    $fields = $entityFieldManager->getFieldDefinitions($entity_type, $bundle);
    foreach ($fields as $field) {
      if ($field->getType() == 'link') {
        $field_name = $field->getName();
        $form[$field_name]['widget'][0]['#element_validate'][] = '_fix_link_field_value';
        array_unshift($form[$field_name]['widget'][0]['uri']['#element_validate'][0], '_fix_link_field_value');
        $form[$field_name]["widget"][0]["uri"]["#description"] = t('This must be an external URL such as http://example.com, https://example.com, example.com, www.example.com.');
      }
    }
  }
}

and then the validator/fixer:

function _fix_link_field_value(&$element, FormStateInterface $form_state, &$complete_form) {
  $url = $form_state->getValue($element['#parents'][0]);
  $urlOriginal = $url[0]['uri'];
  if (!$urlOriginal) return;

  if (!stristr($url[0]['uri'], '//')) {
    $url[0]['uri'] = 'http://' . $url[0]['uri'];
  }
  if (filter_var($url[0]['uri'], FILTER_VALIDATE_URL) === FALSE) {
    $form_state->setErrorByName($element['#parents'][0], t('%url is not a valid URL format. This must be in a format like
      http://example.com, https://example.com, example.com, www.example.com.',
      ['%url' => $urlOriginal])
    );
  }
  else {
    $form_state->setValue($element['#parents'][0], $url);
  }
}

The array_unshift isn't right but doing an unset() didn't seem to cut it. I am sure all this is doing is preventing the original validator from running; which is good as the error message it generates is stupid. Not sure why 5 years into D8 they still don't have this fixed.

Also, this will need an extra loop if you are dealing with multi-valued fields.

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.