Создаем свой виджет для Twitter
Пожалуй, Twitter не нуждается в своем представлении. Для одних это способ расширить аудиторию, для других – вариант разнообразно провести свое время. Размещение фида Twitter на веб-сайте стало практически обязательным действием. Интегрировать фид на сайт можно довольно просто – с помощью стандартного виджета Twitter, однако некоторое разработчики стремятся к тому, чтобы создать свой собственный виджет, который можно будет профессионально внедрить в существующий дизайн.
Итоговый результат
Результатом приложенных нами усилий будет являться виджет для WordPress, который можно будет разместить в виджетизированном сайдбаре. Он будет выводить пользовательские данные, а также последние обновления пользовательского фида. Вы можете увидеть виджет в действии в теме Musico, а также на скриншоте, представленном ниже.
Условия использования сервиса Twitter
В случае создания произвольного виджета (как в нашем случае), вы можете самостоятельно управлять тем, какие элементы вы будете выводить и как вы будете это делать. Обязательно прочтите требования «Developer Display Requirements», чтобы узнать, что именно вам нужно вывести на экран. Некоторые из приведенных правил я нарушу в угоду простоте, что всегда можно будет поправить в дальнейшем, после полного прочтения статьи.
Обратите внимание на тот факт, что следование требованиям – это насущная необходимость. Если вы не сделаете этого, вы рискуете тем, что ваш ID может быть забанен, т.е. ваш виджет не будет выводить какие-либо твиты.
Первый шаг: создаем приложение для Twitter
Перед тем как писать какой-либо код, нам необходимо получить приложение Twitter, или, если говорить более точно, учетные данные для Twitter API. Как это сделать?
1. Заходим в раздел разработчика Twitter.
2. Переходим в My Applications, после чего щелкаем Create a new application.
3. Заполняем обязательные поля, принимаем правила, после чего щелкаем по кнопке Create your Twitter application. Вам не понадобится callback URL для приложения, потому просто оставьте соответствующее поле незаполненным.
4. Как только приложение будет создано, щелкаем по кнопке Create my access token.
5. Готово! Впоследствии вам нужны будут следующие данные:
- consumer key
- consumer secret
- access token
- access token secret
Добавляем детали к нашему приложению
Чтобы быстро добавить некоторые опции к нашей теме, мы будем использовать настройщик тем, введенный в WordPress 3.4. На данном этапе мы просто добавим необходимые базовые возможности.
Чтобы получить быстрый доступ к настройщику тем, я буду использовать следующий фрагмент кода:
add_action ('admin_menu', 'my_theme_customizer'); function my_theme_customizer() { add_theme_page( __( 'Customize Theme Options', THEMENAME ), __( 'Customize Theme', THEMENAME ), 'edit_theme_options', 'customize.php' ); }
Добавление этого кода в файл темы functions.php сгенерирует ссылку к настройщику тем в разделе «Appearance» консоли. Чтобы добавить некоторые опции, нам нужно будет создать класс. Добавим файл MyCustomizer.class.php в папку с темой, после чего вставим в него следующий код:
<?php class MyCustomizer { public static function register ( $wp_customize ) { /** Sections **/ $wp_customize->add_section( 'twitter_api' , array( 'title' => __( 'Twitter API Details', 'mytextdomain' ), 'priority' => 10, )); /** Settings **/ $wp_customize->add_setting( 'twitter_consumer_key' ); $wp_customize->add_setting( 'twitter_consumer_secret' ); $wp_customize->add_setting( 'twitter_access_token' ); $wp_customize->add_setting( 'twitter_access_token_secret' ); /** Controls **/ $wp_customize->add_control( 'twitter_consumer_key', array( 'label' => __( 'Consumer Key', 'mytextdomain' ), 'section' => 'twitter_api', 'priority' => 10, ) ); $wp_customize->add_control( 'twitter_consumer_secret', array( 'label' => __( 'Consumer Secret', 'mytextdomain' ), 'section' => 'twitter_api', 'priority' => 20, ) ); $wp_customize->add_control( 'twitter_access_token', array( 'label' => __( 'Access Token', 'mytextdomain' ), 'section' => 'twitter_api', 'priority' => 30, ) ); $wp_customize->add_control( 'twitter_access_token_secret', array( 'label' => __( 'Access Token Secret', 'mytextdomain' ), 'section' => 'twitter_api', 'priority' => 40, ) ); } } add_action( 'customize_register' , array( 'MyCustomizer' , 'register' ) ); ?>
Что мы делаем в этом коде. Все детали, которые нам нужно добавить к настройщику, инкапсулированы в класс. Класс регистрируется в самом низу блока кода с помощью хука.
Чтобы наши опции были выведены на экран, нам нужно сделать три действия с классом:
- Создать новый раздел, который будет объединять эти опции в одной логической группе. Для этого мы используем функцию add_section(); нам нужно только добавить заголовок.
- Сообщить WordPress о том, что мы добавили определенные настройки. Для этого мы используем функцию add_setting, которая также принимает параметр по умолчанию, однако в данном случае он нам не требуется.
- Наконец, мы связываем средства управления с настройками, чтобы пользователь мог управлять ими. Доступно довольно много разных средств управления; в данной статье мы воспользуемся простым текстовым полем. Используя функцию add_control(), мы определим параметры, которые будут изменяться, метку для средств управления, а также секцию под них. Тип средств управления не определен, поскольку в качестве значения по умолчанию выступает обычное поле ввода input.
Обратите внимание на настройку «приоритета» для некоторых элементов. Он определяет порядок, в котором элементы будут выводиться. Все числа кратны 10, чему есть простое объяснение – если вы вдруг впоследствии поймете, что вам нужно вставить какое-то поле между уже существующими, вам не понадобится переписывать все приоритеты; вы можете, к примеру, указать «15» для нового элемента.
Не забудьте включить этот класс в functions.php, чтобы код был выполнен.
include( 'MyCustomizer.class.php' );
Как только все это будет сделано, вы сможете заполнить детали. Получить доступ к значениям можно с помощью функции get_theme_mod( ‘option_name’ ), о которой мы еще поговорим ниже.
Интегрируем API
Теперь у нас есть простой способ получения наших API деталей, однако у нас до сих пор еще нет связи с API. Сделать это достаточно сложно; к счастью, другие люди уже сделали этот труд за нас. В указанном руководстве я буду использовать PHP-класс Codebird для взаимодействия с Twitter API.
Скачиваем codebird.php со страницы Codebird, размещаем его в папку с основной темой и настраиваем его следующим образом:
add_action( 'init', 'my_twitter_api' ); function my_twitter_api() { global $cb; $consumer_key = get_theme_mod( 'consumer_key' ); $consumer_secret = get_theme_mod( 'consumer_secret' ); $access_token = get_theme_mod( 'access_token' ); $access_secret = get_theme_mod( 'access_secret' ); include( 'codebird.php' ) Codebird::setConsumerKey( $consumer_key, $consumer_secret ); $cb = Codebird::getInstance(); $cb->setToken( $access_token, $access_secret ); }
Теперь вы сможете использовать Codebird, просто вызывая экземпляр $cb. Давайте отложим пока рассмотрение этого экземпляра; мы еще вернемся к нему.
Создаем виджет
Мне нравится представлять виджеты как отдельные файлы. Перед тем, как мы приступим к более обстоятельной работе, давайте создадим папку с виджетами и поместим в нее файл MyTwitterWidget.class.php. Включите этот файл в functions.php следующим образом:
include( 'widgets/MyTwitterWidget.class.php' );
Добавим следующий PHP-код к файлу. Это обычное начало для виджетов.
<?php class MyTwitterWidget extends WP_Widget { /** Widget setup **/ function MyTwitterWidget() { parent::WP_Widget( false, __( 'My Twitter Widget', 'mytextdomain' ), array('description' => __( 'Displays a list of tweets from a specified user name', 'mytextdomain' )), array('width' => '400px') ); } /** The back-end form **/ function form( $instance ) { } /** Saving form data **/ function update( $new_instance, $old_instance ) { } /** The front-end display **/ function widget( $args, $instance ) { } } register_widget('MyTwitterWidget'); ?>
Здесь мы видим четыре функции, каждая из которых играет определенную роль в деле создания виджета.
- Первая функция – конструктор. Здесь можно определить заголовок виджета и его описание.
- Функция form отвечает за бэк-энд формы. Если поместить сюда несколько функций, можно заметно упростить сборку формы. Об остальном позаботится WordPress.
- Функция update позволяет добавить любой код к процессу сохранения.
- Функция widget обрабатывает фронт-энд вывод виджета.
Поскольку мы создаем виджет, нам понадобятся некоторые произвольные функции. Давайте рассмотрим их.
Бэк-энд форма
Мы хотим предложить пользователям возможность изменения заголовка виджета, определения числа твитов для вывода на экран, а также задания имени пользователя в Twitter. Базовый паттерн для создания этих настроек следующий:
<p> <label for='<?php echo $this->get_field_id( 'option_name' ); ?>'> <?php _e( 'Title:', 'mytextdomain' ); ?> <input class='widefat' id='<?php echo $this->get_field_id( 'option_name' ); ?>' name='<?php echo $this->get_field_name( 'option_name' ); ?>' type='text' value='<?php echo $values['option_name']; ?>' /> </label> </p>
Массив $values – это список всех опций виджета, которые определены где-то в другом месте. Все наши опции будут следовать за паттерном. Вот функции, которые нужно изучить:
- get_field_id() – выводит ID поля для вашей опции.
- get_field_name() – выводит название поля для вашей опции.
Использование этих функций очень важно, поскольку благодаря им мы можем использовать несколько экземпляров виджета в разных сайдбарах. Полный код нашей формы выглядит следующим образом:
<?php $defaults = array( 'title' => '', 'limit' => 5, 'username' => 'bonsaished' ); $values = wp_parse_args( $instance, $defaults ); ?> <p> <label for='<?php echo $this->get_field_id( 'title' ); ?>'> <?php _e( 'Title:', 'mytextdomain' ); ?> <input class='widefat' id='<?php echo $this->get_field_id( 'title' ); ?>' name='<?php echo $this->get_field_name( 'title' ); ?>' type='text' value='<?php echo $values['title']; ?>' /> </label> </p> <p> <label for='<?php echo $this->get_field_id( 'limit' ); ?>'> <?php _e( 'Tweets to show:', 'mytextdomain' ); ?> <input class='widefat' id='<?php echo $this->get_field_id( 'limit' ); ?>' name='<?php echo $this->get_field_name( 'limit' ); ?>' type='text' value='<?php echo $values['limit']; ?>' /> </label> </p> <p> <label for='<?php echo $this->get_field_id( 'username' ); ?>'> <?php _e( 'Twitter user name:', 'mytextdomain' ); ?> <input class='widefat' id='<?php echo $this->get_field_id( 'username' ); ?>' name='<?php echo $this->get_field_name( 'username' ); ?>' type='text' value='<?php echo $values['username']; ?>' /> </label> </p>
Единственное дополнение, которое мы сделали к этому коду – это получение значений. Функция передает текущее значение в параметре $instance. Я добавил массив defaults на тот случай, если никакие значения не будут заданы. Массив defaults и массив instance были объединены в один результирующий массив $values.
Сохраняем данные формы
Я уверен, что вы будете удивлены простотой этого шага. Вот полный код для функции update().
return $new_instance;
Параметр $new_instance включает в себя все новые данные. Нам нужно лишь возвратить его. Цель функции update заключается в том, чтобы допустить некоторое управление данными, а также их валидацию.
Вывод твитов
Теперь мы перешли к самой сложной части. Получить твиты не так трудно, однако если мы будем делать это при каждой загрузке страницы, то Twitter в мгновение ока наложит на нас свои фильтры. Нам нужно отыскать способ для кэширования результатов, чтобы мы беспокоили Twitter, скажем, каждые пять минут. Я предпочитаю смотреть на эти задачи так, словно их решение уже имеется. Допустим, что у нас уже написаны все эти функции, и нам нужно создать фронт-энд.
Сначала давайте посмотрим на общий шаблон, который требуется для вывода виджетов.
echo $args['before_widget']; echo $args['before_title'] . $instance['title'] . $args['after_title']; echo $args['after_widget'];
Параметр $args хранит в себе некоторую информацию, полученную от созданного нами сайдбара. Мы просто выводим ее, чтобы убедиться в том, что этот виджет соответствует всем вашим остальным виджетам.
Теперь давайте выведем список некоторых твитов.
$tweets = $this->get_tweets( $args['widget_id'], $instance ); if( !empty( $tweets['tweets'] ) AND empty( $tweets['tweets']->errors ) ) { echo $args['before_widget']; echo $args['before_title'] . $instance['title'] . $args['after_title']; $user = current( $tweets['tweets'] ); $user = $user->user; echo ' <div class="twitter-profile"> <img src="' . $user->profile_image_url . '"> <h1><a class="heading-text-color" href="http://twitter.com/' . $user->screen_name . '">' . $user->screen_name . '</a></h1> <div class="description content">' . $user->description . '</div> </div> '; echo '<ul>'; foreach( $tweets['tweets'] as $tweet ) { if( is_object( $tweet ) ) { $tweet_text = htmlentities($tweet->text, ENT_QUOTES); $tweet_text = preg_replace( '/http://([a-z0-9_.-+&!#~/,]+)/i', 'http://$1', $tweet_text ); echo ' <li> <span class="content">' . $tweet_text . '</span> <div class="date">' . human_time_diff( strtotime( $tweet->created_at ) ) . ' ago </div> </li>'; } } echo '</ul>'; echo $args['after_widget']; }
Давайте разобьем этот код на подразделы, чтобы понять, что он делает.
Строка 1. Мы предполагаем, что у нас есть функция get_tweets(), которая возвращает список твитов в некоторой форме. Мы еще не написали ее, но предположили, что она будет находиться там, чтобы знать, что именно включать в код функции.
Строка 2. Если список твитов не пуст, и не было ошибок, мы можем отобразить виджет.
Строки 7-8. Все твиты выводятся от одного и того же пользователя, каждый твит содержит пользовательские данные. В строке 7 мы просто получаем первый твит. В строке 8 мы вносим пользовательскую информацию в переменную $user.
Строки 10-16. Мы используем данные, полученные от объекта $user, чтобы отобразить пользовательский аккаунт, включающий в себя изображение, короткое описание и имя пользователя.
Строки 18-29. Используем данные из переменной $tweets[‘tweets’] для создания списка твитов. Функция preg_replace() необходима для преобразования ссылок (которые передаются в виде простого текста) в кликабельные элементы.
Все, что нам осталось – это выяснить, как будет работать функция get_tweets(). Мы уже знаем, что она не может получать твиты напрямую из Twitter, потому нам придется воспользоваться некоторым хитростями.
Чтобы получить твиты, наша функция get_tweets() должна выполнять следующее:
1. Получить список твитов из нашей собственной базы данных.
2. Если список отсутствует или с момента его составления уже прошло более пяти минут, функция должна захватить список из Twitter.
3. Как только мы получим результаты из Twitter, мы сохраним их в свою базу данных и добавим временную метку, чтобы убедиться в том, что мы не захватим его прежде, чем пройдет пять минут.
Чтобы сохранить модульность, мы создадим три функции:
- get_tweets() – получает список твитов из нашей базы данных.
- retrieve_tweets() – получает список твитов из Twitter
- save_tweets() – сохраняет список твитов из Twitter в нашу базу данных.
Получаем твиты из Twitter
В классе MyTwitterWidget создадим функцию retrieve_tweets и заставим ее получать некоторые твиты:
function retrieve_tweets( $widget_id, $instance ) { global $cb; $timeline = $cb->statuses_userTimeline( 'screen_name=' . $instance['username']. '&count=' . $instance['limit'] . '&exclude_replies=true' ); return $timeline; }
Как вы видите, с помощью класса Codebird сделать это очень просто. Мы всего лишь использовали одну из его функций, statuses_userTimeline(), для получения нашего списка. Наши собственные функции получают ID виджета и данные instance, которые мы используем, чтобы сообщить Codebird, твиты какого пользователя мы желаем получить и в каком количестве.
Сохраняем твиты в базу данных
Чтобы сохранить твиты в базу данных, нам понадобится использовать ID виджета и фактические твиты, а также нам нужно будет сохранить время их последнего обновления.
function save_tweets( $widget_id, $instance ) { $timeline = $this->retrieve_tweets( $widget_id, $instance ); $tweets = array( 'tweets' => $timeline, 'update_time' => time() + ( 60 * 5 ) ); update_option( 'my_tweets_' . $widget_id, $tweets ); return $tweets; }
Эта функция также получает ID виджета и данные instance. Мы используем их для получения твитов с помощью функции retrieve_tweets(), созданной ранее. Мы добавим твиты в наш массив $tweets, который содержит данные, возвращенные от Twitter, а также время обновления.
Время обновления – пять минут с текущего момента. Когда мы выведем на экран наши твиты, мы будем использовать это значение для проверки, нужно ли отобразить твиты из базы данных или снова получить список твитов из Twitter (чтобы гарантировать, что мы имеем свежие твиты).
Мы используем ID виджета, чтобы сохранить список в базу данных, используя таблицу опций WordPress. Это гарантирует, что мы можем сохранить правильные детали Twitter для каждого экземпляра нашего Twitter-виджета.
Получаем твиты из базы данных
Наконец мы пришли к функции get_tweets(). Давайте посмотрим на нее. Ниже будет дано объяснение.
function get_tweets( $widget_id, $instance ) { $tweets = get_option( 'my_tweets_' . $widget_id ); if( empty( $tweets ) OR time() > $tweets['update_time'] ) { $tweets = $this->save_tweets( $widget_id, $instance ); } return $tweets; }
Сначала мы получаем твиты из базы данных, используя таблицу опций. Если таблица опций пуста или время обновления вышло за наши пределы, мы используем функцию save_tweets(). Она получит твиты из Twitter и сохранит их в базу данных (и возвратит их, чтобы мы могли сразу их использовать).
Заключение
Методика не лишена некоторой сложности, однако она обладает четкой и ясной логикой, выступающей результатом продуманного подхода, с помощью которого были реализованы виджеты в WordPress и настройщик тем.
Когда вы поймете основную идею создания виджетов, вы сможете легко добавлять на свой сайт и настраивать виджеты, которые будут радовать вас и ваших клиентов.
Источник: wp.smashingmagazine.com/2013/06/27/create-twitter-widget/