Современная, быстрая и удобная система управления сайтом

6. Делаем плагин для подсчета RSS-подписчиков

Архив записейКомментарии: 0Просмотров: 12014

Идею сделать такой плагин мне подкинул Роберт. Сегодня я подробно расскажу и насколько просто она реализуется на MaxSite CMS.

Первым делом нам, конечно же нужно определиться с ТЗ.

Сам по себе подсчет подписчиков подразумевает ведение статистики. Серьезные сервисы, вроде фидбернера скорее всего отслеживают подписчиков с учетом множества параметров, например с учетом агрегатора, браузера, и т.д., и т.п. Для нас такой задачи пока не стоит, поэтому я решил, что мы можем ограничиться чем-то попроще: просто подсчитывать количество обращений к RSS в течение суток.

Как известно, в MaxSite CMS RSS-лента автоматически отдается если в адресе последним сегментом указан «feed». Данная проверка автоматически производится при инициализации системы, а узнать её результат можно с помощью is_feed().

Таким образом, наша задача значительно упрощается: нам достаточно просто проверить is_feed() и если она вернет true то увеличить счетчик текущего url на единицу.

Для того, чтобы перехватить входящий url, мы можем воспользоваться стандартный хуком на «init». На него мы «повесим» нашу функцию.

Теперь следующий момент: как именно хранить статистику. В MaxSite CMS есть замечательный механизм float-опции с помощью которых можно хранить любую информацию в отдельном файле. На мой взгляд можно воспользоваться обычным массивом вот с такой структурой:

 
дата1 =
    url1 = кол-во
    url2 = кол-во
    url3 = кол-во
дата2 =
    url1 = кол-во
    url2 = кол-во
    url3 = кол-во	   
...

То есть у нас получится разбивка и по адресам и по датам. Таким образом можно подсчитать количество подписчиков по дням и адресам. При этом наша статистика сохранится для анализа.

Итак с ТЗ мы определились и теперь я покажу, как все это воплощать на практике.

В MaxSite CMS существуют определенные правила для плагинов. Благодаря им, плагины получаются небольшими и строгими по своей структуре. Я бы даже сказал - однотипными. Это значительно упрощает их разработку и сопровождение.

В качестве первого шага сделаем новый каталог для нашего плагина. Все плагины находятся в maxsite/plugins. Идем в него и создаем новый каталог «feedcount».

Как и большинство программистов, я достаточно ленив, чтобы каждый раз с нуля писать код. Вместо этого я сделал несколько шаблонных решений, которые находятся в каталоге плагинов. Поскольку у нас будет плагин без админ-панели, но с виджетом (чтобы выводить статистику), то мы берем файл «template for widgets.php» и копируем в наш каталог «feedcount». Сразу же копируем файл «info.php».

Файл «template for widgets.php» переименовываем в «index.php»: основной файл плагина всегда должен быть с этим именем. В файле «info.php» заполним информацию - она используется только для отображения информации о плагине.

Вся дальнейшая наша работа будет с файлом «index.php». Открываем его Notepad2.

Следующим нашим действием будет авторасстановка имен функций, опций и т.д. Впрочем это только громко сказано, на самом деле нам нужно сделать обычную замену «%%%» на имя каталога (feedcount). Верхнюю обьяснительную строчу нужно удалить.

Дальше по тексту плагина внесем пару правок.

В функции feedcount_autoload() в mso_register_widget() изменим название нашего виджета: «Виджет подсчета подписчиков RSS».

На этом начальный этап завершен. Идем в нашу админ-панель в Плагины и активируем наш плагин.

Чтобы убедиться, что все верно, перейдем в Сайбдары и виджеты и разместим один виджет на сайдбаре. На вкладке «Настройка виджетов» у вас будет уже рабочий виджет.

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

Разберемся с нашей функцией подсчета данных.

Поскольку нам нужно анализировать входящий url, то мы будем делать это с помощью своей функции, которая будет срабатывать на хук «init».

В функцию автозагрузки плагина feedcount_autoload() добавим одну строчку:

mso_hook_add( 'init', 'feedcount_init');

Естественно нам нужно сделать функцию feedcount_init():

function feedcount_init($args = array())
{
	if (!is_feed()) return $args;
 	
	... здесь будет наша функция ...
 
	return $args;
}

В данном случае мы сразу смотрим «feed»-ли адрес и если это не так, то сразу выходим (return).

Для работы с float-опциями нам потребуются две функции. С помощью первой мы получим текущие данные, второй - сохраним результат.

$stat = mso_get_float_option('feedcount', 'feedcount', array());

Получаем массив опций в $stat. Если такой опции еще нет, то будет возвращен пустой массив (третий параметр).

Для структуры нам понадобится текущая дата.

$date = date('Y-m-d');

и текущий url относительно сайта:

$url = mso_current_url();

Дальше нам нужно проверить существует ли элемент массива для этой даты и этого адреса.

	if (isset($stat[$date][$url] ))
	{
	// да, существует
	}
	else
	{
	// нет это первое обращение
	}

Дальше очень просто. Если данные есть, то увеличиваем их на 1. Если нет, то записываем 1.

	if (isset($stat[$date][$url] ))
	{
   		$stat[$date][$url]++;
	}
else
	{
   		$stat[$date][$url] = 1;
	}

В конце нам нужно сохранить обновленный массив:

mso_add_float_option('feedcount', $stat, 'feedcount');

Вот собственно и вся функция. Чтобы вы не запутались я привожу её целиком:

function feedcount_init($args = array() )
{
    if (!is_feed()) return $args;
    
    $stat = mso_get_float_option('feedcount', 'feedcount', array());
    
    $date = date('Y-m-d');
    $url = mso_current_url();
    
    if (isset($stat[$date][$url] ) )
    {
        $stat[$date][$url]++;
    }
    else
    {
        $stat[$date][$url] = 1;
    }
    
    mso_add_float_option('feedcount', $stat, 'feedcount'); 
    
    return $args;
}

У вас, естественно возникнет вопрос, а как бы это всё дело проверить. Можно конечно вручную проверить файлы опций, но есть способ получше: воспользоваться отладочной функцией pr().

Если например мы перед конечным return пропишем:

pr($stat);

и обратимся по адресу http://site/feed, то увидим отладочную информацию: содержимое переменной $stat. Я очень часто использую этой функцию при отладке и не зря она появилась в MaxSite CMS одной из первых. ;)

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

Подведем предварительный итог. Наша статистика теперь сохраняется в опциях и доступна из любой другой функции. Теперь нам нужно её вывести с помощью виджета.

При создании виджета первым делом нужно определиться с тем как и что мы хотим выводить и какие для этого потребуются настройки. Очевидно, что уже присутствующее поле «Заголовок» нам не помешает. Я думаю, что было бы неплохо предусмотреть поля для формата вывода. Это может потребоваться, если нужно обрамить вывод в какой-то HTML. В этом случае мы просто придумаем спецкод «[COUNT]», который и будет заменяться на текущее количество подписчиков. При этом есть смысл придумать и спецкод для статистики за вчерашний день. Пусть будет - [COUNTOLD].

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

Больше нам особых вариантов не нужно, поэтому остановимся только на этих двух полях.

Вначале найдем функцию вывода формы виджета feedcount_widget_form. Добавим в неё значение формата по-умолчанию (когда пользователь его не определил в настройке виджета).

if ( !isset($options['format'] ) ) 
        $options['format'] = '<strong>Сегодня:</strong> [COUNT]<br/><strong>Вчера:</strong> [COUNTOLD]';

Для этого поля сделаем textarea. В принципе можно и обычный input=text, но мы предполагаем, что будет html, а с ним удобней работать именно в texarea.

Для генерации textarea мы воспользуемся CodeIgniter-хелпером «Form». Под полем сразу же выведем подсказку. Вот результирующий код:

	    $form .= '<p><div class="t150">Формат:</div> '. form_textarea( array( 'name'=>$widget . 'format', 'value'=>$options['format'] ) ) ;
    $form .= '<p><div class="t150">&nbsp</div>[COUNT] - подписчиков сегодня, [COUNTOLD] - подписчиков вчера</p>';

Теперь, если вы зайдете в Настройку виджетов, то сразу же увидите готовый виджет.

Для того, чтобы форма сохранилась в опции виджета нужно указать имена полей в функции feedcount_widget_update():

$newoptions['format'] = mso_widget_get_post($widget . 'format');

Теперь наш виджет вполне способен сохранять введенные данные.

Последнее наше действие - это вывод самого виджета на сайте. За него отвечает функция feedcount_widget_custom().

Сейчас в этой функции находится код для работы с кэшем. Но нам он в данном случае не нужен, потому что float-опции сами работают как кэш. Поэтому особого смысла кэшировать еще и их просто нет. Сократим функцию до вот такого:

function feedcount_widget_custom($options = array(), $num = 1)
{
    if ( !isset($options['header'] ) ) $options['header'] = '';
    if ( !isset($options['format'] ) ) 
        $options['format'] = '<strong>Сегодня:</strong> [COUNT]<br/><strong>Вчера:</strong> [COUNTOLD]';
    
    $out = $options['format'];
 
    ... тут будут наши действия ...
 
    if ($out and $options['header'] ) $out = $options['header'] . $out;
    return $out;    
}

Я сразу добавил строчки для формата и для вывода заголовка. Даже если вы сейчас обновите сайт, то сразу увидите рабочий виджет.

Нам остался последний штрих - получение данных из float-опций их подсчет и вывод.

Получение данных мы уже рассмотрели:

$stat = mso_get_float_option('feedcount', 'feedcount', array());

Текущая дата:

$date = date('Y-m-d');

Чтобы получить ключ для вчерашней даты воспользуемся маленькой хитростью. В функции date() укажем стандартную time() за вычетом количества секунд в сутках.

$date_old = date('Y-m-d', time() - 86400);

Для подсчета количества подписчиков мы можем либо просуммировать все числа по всем адресам за сутки, но мне кажется, что более правильным будет подсчет именно главной страницы, то есть url = feed

Сделать же выбор вариантов я предлагаю вам в качестве домашнего задания. :)

Итак подсчет осуществляется с помощью несложного кода:

if (isset($stat[$date]['feed'] ) ) $count = $stat[$date]['feed'];
  	else $count = 0;
		
if (isset($stat[$date_old]['feed'] ) ) $count_old = $stat[$date_old]['feed'];
  	else $count_old = 0;

Последним действием нам нужно заменить в строчке формата наши спецкоды:

$out = str_replace('[COUNT]', $count, $out);
$out = str_replace('[COUNTOLD]', $count_old, $out);

Вот на этом всё. :)

Привожу полный код функции feedcount_widget_custom():

function feedcount_widget_custom($options = array(), $num = 1)
{
    if ( !isset($options['header'] ) ) $options['header'] = '';
    if ( !isset($options['format'] ) ) 
        $options['format'] = '<strong>Сегодня:</strong> [COUNT]<br/><strong>Вчера:</strong> [COUNTOLD]';
    
    $out = $options['format'];
    
    $stat = mso_get_float_option('feedcount', 'feedcount', array());
    $date = date('Y-m-d');
    $date_old = date('Y-m-d', time() - 86400);
    
    if (isset($stat[$date]['feed'] ) ) $count = $stat[$date]['feed'];
        else $count = 0;
        
    if (isset($stat[$date_old]['feed'] ) ) $count_old = $stat[$date_old]['feed'];
        else $count_old = 0;
        
    $out = str_replace('[COUNT]', $count, $out);
    $out = str_replace('[COUNTOLD]', $count_old, $out);
    
    if ($out and $options['header'] ) $out = $options['header'] . $out;
    return $out;    
}

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