Причины создания
Недавно попросили сделать геотаргетинг по городам для сайта на wordpress. Пересмотрев существующие геотаргетинг-плагины (в том числе платные), не нашёл не одного работающего с городами (только страны). Поэтому решил сделать свой, используя какую-нибудь существующую базу для определения местоположения по IP-адресу. Сначала начал с разработки функции в шаблоне, но потом решил создать плагин и выложить на github, так как думаю, что он может пригодиться кому-нибудь ещё.
Выбор базы
Первым делом нужно было выбрать базу. И это, наверное, одна из самых сложных проблем. В процессе разработки пробовал много вариантов, даже делал CURL-запросы на сайты, определяющие местоположение по ip, и парсил их. Но все они были не точны, к примеру, один Московский IP определяло как Москву, другой — просто Россия. Также нужно было, чтобы плагин работал не только с Россией, но и с Беларусью и Украиной. Перепробовав кучу множество баз, я остановился на Sypex Geo. У них есть условно-платная и бесплатная версии баз. Условно-платная использует REST API и возвращает данные в виде xml, json и jsonp. Бесплатную можно скачать в виде файла, также можно скачать класс для работы с ней. Условно-платная версия более точная, но бесплатно предоставляет только 10 000 запросов. Бесплатная версия тоже достаточно точна и обновляется на сайте.
Функционал
Как я уже писал, начинал я делать не с плагина, а с функции в шаблоне. Сначала думал только об условно-платной версии базы, но количество бесплатных запросов закончилось за день-два. Поэтому перешёл на бесплатную, используя готовый класс для работы с файлом базы.
При разработке плагина я решил сделать выбор между локальной базой и REST API. В будущем планирую сделать кнопку автоматического обновления базы.
Также из базы можно вернуть русские и английские имена городов (стран, регионов). В связи с этим сделал выбор языка.
Ещё столкнулся с тем, что нужно включить список несколько городов или наоборот исключить какой-то.
Настройка плагина в админке
Реализация
Так как с WordPress я работаю редко (как и со всеми CMS) и написанием плагинов для него никогда не занимался, начал читать, как их писать и смотреть, как устроены существующие. Идею реализации взял с существующих гео-плагинов. Ещё долго думал писать функционально или объектно-ориентированно. Решил функционально, так как плагин не большой.
Вкратце опишу его работу.
При активации плагина инициируем две опции: тип бд и язык на котором будем вводить названия.
register_activation_hook(__FILE__, 'wp_sypexgeo_activation'); function wp_sypexgeo_activation() { update_option('sgeo_language', 'en'); update_option('sgeo_dbase', 'loc'); }
Далее
add_filter('the_content', 'geotargeting_filter'); add_filter('the_content_rss', 'geotargeting_filter'); add_filter('the_excerpt', 'geotargeting_filter'); add_filter('the_excerpt_rss', 'geotargeting_filter');
вызывают функцию
function geotargeting_filter($s) { //parse Country preg_match_all("#\[" . GEOTARGETING_COUNTY . "\s*(in|out)=([^\]]+)\](.*?)\[/" . GEOTARGETING_COUNTY . "\]#isu", $s, $country); //parse Country preg_match_all("#\[" . GEOTARGETING_REGION . "\s*(in|out)=([^\]]+)\](.*?)\[/" . GEOTARGETING_REGION . "\]#isu", $s, $region); //parse Country preg_match_all("#\[" . GEOTARGETING_CITY . "\s*(in|out)=([^\]]+)\](.*?)\[/" . GEOTARGETING_CITY . "\]#isu", $s, $city); if (empty($country) && empty($region) && empty($city)) { return $s; } $base_type = get_option('sgeo_dbase'); if ($base_type == 'loc') { $ipdata = getLocInfo(); } elseif ($base_type == 'rm') { $ipdata = getRemInfo(); } if (!empty($country)) { foreach ($country[0] as $i => $raw) { $type = strtolower($country[1][$i]); $countries = strtolower(trim(str_replace(array("\"", "'", "\n", "\r", "\t", " "), "", $country[2][$i]))); $content = $country[3][$i]; $countries = explode(",", $countries); $replacement = ""; if ((($type == "in") && in_array($ipdata['country'], $countries)) || (($type == "out") && !in_array($ipdata['country'], $countries))) { $replacement = $content; } $s = str_replace($raw, $replacement, $s); } } if (!empty($region)) { foreach ($region[0] as $i => $raw) { $type = strtolower($region[1][$i]); $regions = strtolower(trim(str_replace(array("\"", "'", "\n", "\r", "\t"), "", $region[2][$i]))); $content = $region[3][$i]; $regions = explode(",", $regions); $replacement = ""; if ((($type == "in") && in_array($ipdata['region'], $regions)) || (($type == "out") && !in_array($ipdata['region'], $regions))) { $replacement = $content; } $s = str_replace($raw, $replacement, $s); } } if (!empty($city)) { foreach ($city[0] as $i => $raw) { $type = strtolower($city[1][$i]); $cities = strtolower(trim(str_replace(array("\"", "'", "\n", "\r", "\t", " "), "", $city[2][$i]))); $content = $city[3][$i]; $cities = explode(",", $cities); $replacement = ""; if ((($type == "in") && in_array($ipdata['city'], $cities)) || (($type == "out") && !in_array($ipdata['city'], $cities))) { $replacement = $content; } $s = str_replace($raw, $replacement, $s); } } return $s; }
В которую приходит текущий контент. В зависимости от типа базы вызывается функция для получения данных. Затем идёт поиск специальных тегов в шаблоне и сверка их с данными о местоположении. Если данные совпадают то конструкция заменяется на содержимое из тегов, если нет — она удаляется.
Использование
Для указания списка стран:
[GeoCountry in=Belarus,Russia]Привет Belarus,Russia![/GeoCountry]
Для указания списка регионов:
[GeoRegion in=Moscow]Привет Moscow Region![/GeoRegion]
Для указания списка городов:
[GeoCity in=Минск,Брест]Привет Минск,Брест![/GeoCity]
Если вы хотите выбрать страны (регионы, города) за исключением указанных, используйте «out»:
[GeoRegion out=Minsk,Brest]Привет всем, кроме Minsk,Brest![/GeoRegion]
Пример использования в шаблоне:
Добро пожаловать в WordPress. Это ваша первая запись. Отредактируйте или удалите её, затем пишите! Наши контакты: [GeoCity in=Minsk]+375295552255[/GeoCity][GeoCity out=Minsk]+375475552255[/GeoCity]
Заключение
Надеюсь мой плагин кому-нибудь пригодится. Если есть вопросы или предложение — пишите. Также, если кто-то считает что нужно использовать другую базу (геосервис или ещё что-нибудь) предлагайте, я добавлю или можете добавить сами.
Ссылка на плагин: wp-sypexgeo
ссылка на оригинал статьи http://habrahabr.ru/post/258705/
Добавить комментарий