5

After creating a Link field and use the Link with service icon format, I find out that there is no option to restrict external URLs to external domains that I want

For example, if I only want to allow Twitter links, something like add https://www.twitter.com/*.

Someone already asked here, but it seems that the Advanced Link module is not available for my Drupal version.

With what module and how can I filter my desired URLs in Drupal 9?

1
4

There is a now a new module on drupal.org: Link Allowed Hosts – Will be working on this during the week so next week we can finally restrict the allowed hosts for link fields.

2
4
+50

You need to write your own custom validation contraint and add this constraint to your field.

Docs: https://www.drupal.org/docs/drupal-apis/entity-api/entity-validation-api/providing-a-custom-validation-constraint

I've used that example to create a "force HTTPS" link field constraint

src/Plugin/Validation/Constraint/Https.php

<?php

namespace Drupal\MYMODULE\Plugin\Validation\Constraint;

use Symfony\Component\Validator\Constraint;

/**
 * Checks that the submitted URL is starting with https://
 *
 * @Constraint(
 *   id = "MY_CONSTRAINT_ID",
 *   label = @Translation("Https", context = "Validation"),
 *   type = "string"
 * )
 */
class Https extends Constraint {
  public $notHttps = '%uri is not a secure site (not starting with https://)';
}

src/Plugin/Validation/Constraint/HttpsValidator.php

<?php

namespace Drupal\MYMODULE\Plugin\Validation\Constraint;

use Symfony\Component\Validator\Constraint;
use Symfony\Component\Validator\ConstraintValidator;

/**
 * Validates the Https constraint.
 */
class HttpsValidator extends ConstraintValidator {

  /**
   * {@inheritdoc}
   */
  public function validate($items, Constraint $constraint) {
    $item = $items->first();
    if (!isset($item)) {
      return NULL;
    }

    foreach ($items as $item) {
      /* CHANGE THIS, e.g. here you can check for domain names */
      if (strpos($item->uri, 'https://') !== 0) {
        $this->context->addViolation($constraint->notHttps, ['%uri' => $item->uri]);
      }
    }
  }
}

MYMODULE.module

<?php

use Drupal\Core\Entity\EntityTypeInterface;

function MYMODULE_entity_bundle_field_info_alter(&$fields, EntityTypeInterface $entity_type, $bundle) {
  if ($bundle === 'MY_ENTITY_BUNDLE' && $entity_type->id() == 'MY_ENTITY_TYPE') {
    if (isset($fields['MY_FIELD'])) {
      $fields['MY_FIELD']->addConstraint('MY_CONSTRAINT_ID', []);
    }
  }
}

3
  • Uh wow that's nice! Much, much better than hooking into the form!
    – leymannx
    Feb 17 at 10:19
  • Let me ask you Hudri. 1: The Constraint ID is the name I want to choose or there is a list of valid IDs to use? 2: When you say in the 2nd file here you can check for domain names, I got to make an array for the domains only, or maintaining the code under that line? If so, where the array for the domains goes exactly? 3: In the 3rd file, `'MY_ENTITY_BUNDLE' what exactly is a bundle? Thanks for your share, I don't have programming skills but it is a short code so maybe I can try with some help. Think that I am only a Site Builder always looking for using core or contributed modules.
    – MrIssue
    Feb 17 at 12:16
  • Everything written in uppercase MY_SOMETHING is intented to be replaced with custom names/config/module from your own project. But you won't get around coding, at the very least you have to code your own validation logic, which will be quite different than my example (following the lines after ` CHANGE THIS`)
    – Hudri
    Feb 17 at 15:19
0

A module exists with that capability, perhaps try https://www.drupal.org/sandbox/wombatbuddy/3183996

1
  • I think that problem needs to get solved on another level since that feature does not only relate to social media providers.
    – yannickoo
    Feb 17 at 21:27

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.