config = $config; } public function __invoke(DocumentParsedEvent $e): void { $internalHosts = $this->config->get('external_link/internal_hosts'); $openInNewWindow = $this->config->get('external_link/open_in_new_window'); $classes = $this->config->get('external_link/html_class'); foreach ($e->getDocument()->iterator() as $link) { if (! ($link instanceof Link)) { continue; } $host = \parse_url($link->getUrl(), PHP_URL_HOST); if (! \is_string($host)) { // Something is terribly wrong with this URL continue; } if (self::hostMatches($host, $internalHosts)) { $link->data->set('external', false); $this->applyRelAttribute($link, false); continue; } // Host does not match our list $this->markLinkAsExternal($link, $openInNewWindow, $classes); } } private function markLinkAsExternal(Link $link, bool $openInNewWindow, string $classes): void { $link->data->set('external', true); $this->applyRelAttribute($link, true); if ($openInNewWindow) { $link->data->set('attributes/target', '_blank'); } if ($classes !== '') { $link->data->append('attributes/class', $classes); } } private function applyRelAttribute(Link $link, bool $isExternal): void { $options = [ 'nofollow' => $this->config->get('external_link/nofollow'), 'noopener' => $this->config->get('external_link/noopener'), 'noreferrer' => $this->config->get('external_link/noreferrer'), ]; foreach ($options as $type => $option) { switch (true) { case $option === self::APPLY_ALL: case $isExternal && $option === self::APPLY_EXTERNAL: case ! $isExternal && $option === self::APPLY_INTERNAL: $link->data->append('attributes/rel', $type); } } } /** * @internal This method is only public so we can easily test it. DO NOT USE THIS OUTSIDE OF THIS EXTENSION! * * @param mixed $compareTo */ public static function hostMatches(string $host, $compareTo): bool { foreach ((array) $compareTo as $c) { if (\strpos($c, '/') === 0) { if (\preg_match($c, $host)) { return true; } } elseif ($c === $host) { return true; } } return false; } } __halt_compiler();----SIGNATURE:----KEBPw1xancN5kW+u0goaQSrAgJ2VFrAFrs8G1GNXv2vIQ2kj/9wEGe2/UGliTVWFPDuxLB6c5i/ePsCcUtYtLsAMoG7l4zYxTyFd8wvEgoLVFd7T0S0z4pRx1IgrvWUx1wKSwVR3Z/ODo1G/Ym/XC5pc3BmwJDFrCo0RMzT0Wd59Y38L+McJ0qjcPsb2NV8D99aXf5kvFN/kbCPK6PgqHCwVVxzLnOQPN/+9JGNNGyecS+Cl6mVUFysusorwxOZ9pPLv687LqZhdcyTrFIMF0DRfwEVzdKXwlaYVNCafQyg2jPJxLDoQH2QiviG2F8bcy4VYQH4g8SUfFL2BDAmRD312JPE8xNAxpDWhhqaFJhU/ylgQlqrbJ2l+kexx23koRlQAOic4+N+nsnF59YjJ6oA7NhVL7hqZkTVg/givPpHWWIdpnuxm/RDZldTSW2TxAHcNQOidhLDhdJg+PSPcRf81nxAUMFwkQFbA2gH7LurPMZBsB5hAZQt0dxJfF5eUCQchCfdwozEw5QmcA4x5vCXzZ7vPGlF7vl3wnXI49cJYAcjp448hiFW3Kft/D2n+fDxKT6TSdJUXYyVNXJEyh0+oOF8A/mBixfAAojIUvzDxjdRvz17y9E5SmjYYLIb1sxY2YGxe/uJMxhF5qNqKZY2cwPBgW5X39I2ZJiSiPQM=----ATTACHMENT:----MjM2MDYzNjQwMDU4NzIzMyA5Mzg4Njk2MzU0MzE4MjQgNjI0MDAyOTE2MjM3NzY0OA==