Улучшитель для плагина WP No External Links

Более 100 000 раз с сайта WordPress.org скачан плагин «WP No External Links», который автоматически превращает все внешние ссылки блога во внутренние, вида: http://your.site/goto/%3A%2F%2Fanother.site%2F, а при клике на такую ссылку произойдёт редирект на адрес http://another.site/ с кодом 302. Такой код ответа сервера означает: «Это перенаправление на другой адрес, но не факт, что оно постоянное». Таким образом, ПС не «склеивают» перенаправление с внешним адресом и не передают вес по ссылке внешнему адресу. Иными словами, так мы не передаём вес своих страниц тем страницам, на которые ссылаемся.

Теоретическая польза (для SEO) от этого сомнительная, но на практике оптимизаторы предпочитают покупать ссылки со страниц, на которых нет других внешних ссылок. Значит, можно больше заработать, замаскировав внешние ссылки.

Само собой, мы иногда хотим поставить и открытую прямую ссылку, даже если автоматически скрываем все внешние ссылки. Плагин «WP No External Links» предлагает для этого 2 способа:

  • Установить переключатель «Не маскировать ссылки» на странице редактирования поста;
    не маскировать ссылки
  • Добавить ссылку в исключение в настройках плагина.

Первый способ не подходит, когда мы хотим снять маскировку только с одной ссылки на странице и оставить замаскированными другие. Второй способ неудобен тем, что надо постоянно совершать дополнительные телодвижения при желании опубликовать открытую прямую ссылку.

Сегодня я для себя написал третий способ. Публикую — может и вам пригодится.

Важно! Описанный ниже способ совместим с версией плагина 3.4. На версии 3.5.9 не работает — ещё не нашёл причину.

Мой способ заключается в том, чтобы добавить в подписи к ссылке (атрибут title) кодовое слово {follow}:

dofollow

Текст {follow} автоматически вырезается при генерации страницы, а ссылка не маскируется.

Теперь надо поколдовать и заставить плагин обходить стороной ссылки, у которых в title указано кодовое слово. 2 года назад я придумал для этого специальную вставку в файл wp-noexternallinks-parser.php плагина:

if (strpos ($matches[0], '{follow}')) return str_replace ('{follow}', '', $matches[0]);

Этот код надо вставить сразу после строк:

function wp_noextrenallinks_parser($matches)
{
  global $wp_rewrite,$wpdb;

Решение простое, но, разумеется, прекращает работать каждый раз после обновления плагина. И каждый раз надо снова вписывать этот код. А плагин обновляется чуть ли не каждый месяц. Можно и не обновлять, но глаза мозолит информация о имеющихся обновлениях. Можно ещё сильней расковырять плагин и отрубить ему обновление, но это не элегантное решение.

И вот сегодня я придумал такой код для functions.php:

function hs_links_dofollow( $m ) {
	$s = $m[0];
	$p = parse_url( get_option( 'siteurl' ) );
	if ( strpos( $s, '#hs#' ) ) return str_replace( array ( $p[host].'/#hs#', '{follow}' ), '', $s );
	else return preg_replace( '|href=(["\']?(?:.*//)?)|i', 'href=\\1'.$p[host].'/#hs#', $s );
}
function hs_links_filter( $c ) {
	if ( ! strpos( $c, 'title="{follow}' ) ) return $c;
	$p = '|<a\s[^>]*?title="\{follow\}[^>]*>|Ui';
	return preg_replace_callback( $p, 'hs_links_dofollow', $c );
}
function hs_links_nofollow( $c ) {
	if ( ! strpos( $c, 'title="{nofollow}' ) ) return $c;
	$p = '|<a (.*?)href=["\'](.*?)//(.*?)["\'](.*?)>(.*?)</a>|i';
	return preg_replace_callback( $p, function( $m ) {
		if ( ! strpos( $m[0], '{nofollow}' ) ) return $m[0];
		$m[1] = str_replace( '{nofollow}', '', $m[1] );
		$m[4] = str_replace( '{nofollow}', '', $m[4] );
		global $wp_noexternallinks_parser;
		return $wp_noexternallinks_parser->wp_noextrenallinks_parser( $m );
	}, $c );
}
if ( @ $wp_noexternallinks_parser->options ) {
	if( $wp_noexternallinks_parser->options['mask_mine'] ) {
		add_filter( 'the_content', 'hs_links_filter', -1 );
		add_filter( 'the_content', 'hs_links_filter', 131313 );
		add_filter( 'the_excerpt', 'hs_links_filter', -1 );
		add_filter( 'the_excerpt', 'hs_links_filter', 131313 );
	} else {
		add_filter( 'the_content', 'hs_links_nofollow', -1 );
		add_filter( 'the_excerpt', 'hs_links_nofollow', -1 );
	}
 	if($wp_noexternallinks_parser->options['mask_comment'])
	{
		add_filter( 'comment_text', 'hs_links_filter', -1 );
		add_filter( 'comment_text', 'hs_links_filter', 131313 );
		add_filter( 'comment_text_rss', 'hs_links_filter', -1 );
		add_filter( 'comment_text_rss', 'hs_links_filter', 131313 );
	} else {
		add_filter( 'comment_text', 'hs_links_nofollow', -1 );
		add_filter( 'comment_text_rss', 'hs_links_nofollow', -1 );
	}
}

Суть в том, что плагин добавляет свои фильтры с приоритетом 99. А я сначала добавляю фильтр с приоритетом -1, чтобы он выполнился заведомо раньше. Возможно, я погорячился с приоритетом -1: возможно, стоит запускать эти фильтры после того, как сработают другие фильтры обработки контента. В общем, при возникновении проблем можно попробовать большие значения приоритета (главное — не больше 98). При первом проходе по ссылкам я превращаю ссылки с кодовым словом {follow} в начале title во внутренние, чтобы плагин их не трогал. При втором проходе фильтра (с приоритетом 131313) плагин уже поработал над ссылками, потому я возвращаю преобразованную ссылку к изначальному виду и убираю кодовое слово {follow} из title.

А если в настройках плагина не установлены галки «Маскировать ссылки в постах» или «Маскировать ссылки в комментариях», то скрипт обрабатывает другое кодовое слово в title ссылок — {nofollow}. В этом случае ссылки по умолчанию не маскируются, но если «заголовок» ссылки (так называется в русской локали WP атрибут ссылки title — я предпочитаю называть его «подсказка») начинается с кодового слова {nofollow}, такая ссылка будет замаскирована.

Заметьте, что я не добавил nofollow и dofollow фильтры на вывод comment_url и get_comment_author_...: мне не надо, если вам надо — добавьте. Только понятия не имею, как вы будете прописывать персональные подсказки к ссылкам в подписях комментаторов. ;)

Плюсы этого кода очевидны. Я буду пользоваться кодом, пока не найду время написать свой плагин для маскировки ссылок, в котором всё нужное мне будет реализовано круто, а ненужного для меня не будет. Ведь автор плагина Jehy пишет плагин для всех, в том числе и для извращенцев:

настройки

А для себя запрограммирую только тот функционал, которым реально пользуюсь.

Минусы предложенного в этой статье решения по улучшению плагина WP No External Links:

  • не знаю, будет ли работать этот код, если его поместить в отдельный плагин, чтобы он не загромождал файл functions.php. Даже не знаю, поможет ли инструкция global $wp_noexternallinks_parser. Лень проверять, ведь я буду пользоваться кодом, как он есть;
  • код не будет работать при активированной опции плагина «Маскировать ВСЕ ссылки на страницах», потому что при этом плагин использует не фильтры WP, а буферизацию вывода. Я не пользуюсь такой опцией.

На заметку:

  • предложенный код не производит запросов к БД. Возможно, запрос выполнит функция get_option( 'siteurl' ), если не получит данные из кэша — вы можете прописать конкретный адрес своего блога вместо функции, типа: parse_url( 'pavluha.net' );
  • я не буду тестировать, на сколько сотых долей секунды в среднем увеличивается время генерации страницы с этим кодом;
  • я не гарантирую, что код не перестанет работать после очередного обновления плагина. Вдруг автору приснится страшный сон, и он решит сделать приоритет своих фильтров равный 1 000 000 — конечно, код перестанет работать, пока приоритет моих фильтров не будет изменён на ещё большее значение. Как следствие, я не несу ответственности за падение вашего рейтинга в Гогетлинкс за снятие ссылок, на которое вы вовремя не отреагировали. И за прочие возможные последствия того, что ссылки с кодом {follow} вдруг стали nofollow, да ещё и через редирект;
  • не рекомендую использовать в плагине опцию «Добавлять target="blank" для всех ссылок на другие сайты». Почему то она у меня добавляет дважды target="blank" — до атрибута href и после него, что делает код не валидным. Как говорит Джованни (хозяин нашей фазенды), когда видит «цветущий» бассейн: it's not dangerous, but not beautiful.

26.11.2014 Отредактирован код: исправлено одно регулярное выражение.

Запись опубликована в рубрике Web-мастеринг с метками , , . Короткая ссылка для добавления в закладки: Улучшитель для плагина WP No External Links.

7 ответов к “Улучшитель для плагина WP No External Links”

Прячем внешние ссылки / блог Hyper SEO:

[…] О новом варианте улучшения плагина WP No External Links читайте в этой статье на блоге […]

Jehy:

Есть ещё четвёртый способ — написать мне письмо и предложить такую опцию : )

Ведь, как и написано в настройках, есть и некоторые опции для извращенцев))

А эта вполне логичная. Разве что лучше сделать follow при помощи стандартного атрибута ссылки rel="follow" — так ссылки останутся валидными даже при отключении функционала. Но надо подумать, как это изящнее реализовать.

Кстати, ещё один способ впилиться в работу плагина — сделать свой плагин, который меняет приоритеты чужого, и даже заменяет его функции. Например, я это делал тут:

wordpress.org/plugins/securimage-wp-reg/

Но это всё так, если интересно.

Рад, что плагин вам полезен. Пишите, если что : )

Сергей:

Этот плагин отказывается закрывать у меня вообще все ссылки, очень жалко даже !

Павлуха:

Да, жалко — красивый блог. Обидно будет, если уйдёт под фильтр из-за пары внешних ссылок. ;) Это я иронизирую на счёт фильтра, а что красивый — правда так думаю

Сергей:

Спасибо, Да думаю не уйдет) я этого не допущу! = )

Антон:

Здравствуйте

Плагин WP No External Links был украден и наполнен вирусами, за что был заблокирован в репозитории WordPress: wordpress.org/plugins/no-external-links/

Павлуха:

Здравствуйте, Антон. Спасибо за информацию. Действительно, оригинального плагина больше нет в репозитории WP. Насчёт новой версии, понятно, что это форк. Но, может оно и к лучшему — если автор даст вторую жизнь плагину, со временем не придётся «улучшителей писать» :) Но, если вдруг мне захочется добавить свой функционал, надеюсь, автор этого форка добавит хук-фильтр хотя бы на результат работы плагина, а лучше ещё и после проверок на необходимость подмены ссылки.

Добавить комментарий

Ваш адрес email не будет опубликован. Обязательные поля помечены *