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:----uIef2XBODK5EfG5ZfAy3J22bKppJ0/pOzYvjMFnj94lAFkFVfKOQMP35Kn8kOTkJjioyvDetXgO7YJib09gEgUl4Su3OLgRkhE5+2mOjeBw6559DbDIJYB62CvPU9MNJnNYDt3DC7zBpts9Aixm6AY4NE1OwpwLYWVp8r4uXmUC//PStvjsGYZyo1jmA3BN9ukM4QcTCl4Iw4QtLZI2jscxnStP7sm9BH05vsmFWcxsWXkGRMij8nI5WkLXLKYaoNs8njUxFWLA5WfxaCIlJfwCwets80O9n6yipjcMrUlgKQq9cRrDpWimQproyQIatcy6Yq9xUroGKO2rp9j7tvhtiZ7DQBujJkFAKv1cilW8vBb4mqlghRh7VSzn8k/XMOigeasSMzylD1XZUXs72CbY2w/GkBsfP9vVtMVwDC0llnXqdWTCbvJHyS3woemluu1Mjl0Z/5RRmpyt2v9KamX0a0/4SFKBFPIzlXZMzYJ7igxS6DmpEnu2EA6V4xp0c56kLYD7UVQD7POsvZBTGJmiemg4gCBnwYk49ef1DM+8GfkRMl9S/KMsFdx3EXWRQ7PyZL57yF/QkpU31r86H3OVDUQ5F/rwLmpIxt3tngHpXcSSC9QPj9/ToVob2fqJoXhX7PcxqWeE7Pk11oq43tM24ze6X7zq3RYbqCHYflsg=----ATTACHMENT:----MTg5MTg2ODY4OTU5MDUwMiA3NzA2NDc0ODk4NjY0NjQyIDcwMjc0OTUzOTkwNDM1OA==