В этой статье расскажу о программном использовании cron в Drupal 7. Cron позволяет выполнять запланированные действия через определенный промежуток времени. Тем самым снижается разовая нагрузка сайт. В качестве приведу пример модуля, который позволяет изменять слова в тексте на их синонимы. Для этого модуль с помощью cron, будет обращаться к сайту seogenerator.ru. Данный способ активно применяется в SEO для уникализации текста. Лично я не являюсь сторонником данного метода. Считаю что, материал не должен быть сворован и оптимизирован под SEO. Такие сайты никогда не будут пользоваться популярностью.
Создадим директорию seogenerator для будущего модуля. Добавим информацию о модуле в файл seogenerator.info.
name = SeoGenerator
description = SeoGenerator
core = 7.x
configure = admin/config/content/seogenerator
Добавим функцию, которая будет отвечать за создание таблицы в базе данных. В этой таблице будем хранить информацию об узлах, которые прошли обработку с помощью нашего модуля.
/**
* hook_schema().
*/
function seogenerator_schema() {
$schema['seogenerator'] = array(
'description' => 'SeoGenerator',
'fields' => array(
'nid' => array(
'type' => 'int',
'unsigned' => TRUE,
'not null' => TRUE,
'default' => 0,
'description' => "{node}.nid.",
),
),
'primary key' => array('nid'),
);
return $schema;
}
Добавим функцию для удаления модуля из Drupal.
/**
* hook_uninstall().
*/
function seogenerator_uninstall() {
db_delete('variable')
->condition('name', 'seogenerator_%', 'LIKE')
->execute();
cache_clear_all('variables', 'cache_bootstrap');
}
Добавим страницу для настройки нашего модуля.
/**
* hook_menu().
*/
function seogenerator_menu() {
$items['admin/config/content/seogenerator'] = array(
'title' => 'SeoGenerator',
'description' => 'Настройки SeoGenerator',
'page callback' => 'drupal_get_form',
'page arguments' => array('seogenerator_settings'),
'access arguments' => array('administer seogenerator'),
);
return $items;
}
function seogenerator_settings() {
...
}
Добавим поле типа переключатель, которое позволит включить / выключить модуль.
$form['seogenerator_enable'] = array(
'#type' => 'checkbox',
'#title' => t('Включить SeoGenerator'),
'#default_value' => variable_get('seogenerator_enable', 0),
);
Добавим группу независимых переключателей для выбора типа материала, для которого будем применять наш модуль. Функция node_type_get_names позволяет поличить список всех типов материала.
$form['seogenerator_node_types'] = array(
'#type' => 'checkboxes',
'#title' => t('Типы материалов'),
'#options' => node_type_get_names(),
'#default_value' => variable_get('seogenerator_node_types', array()),
);
Функционал сайта позволяет использовать несколько баз синонимов для генерации текста. Позволим пользователям выбирать из какой базы генерировать текст. Добавим список зависимых переключателей для выбора.
$form['seogenerator_base'] = array(
'#type' => 'radios',
'#title' => t('База синонимов'),
'#default_value' => variable_get('seogenerator_base', 0),
'#options' => array(0 => 'Big one', 1 => 'Small one', 2 => 'Small two'),
'#description' => t('Используемая база синонимов для генерации текста.'),
);
Также функционал сайта позволяет выбрать метод подстановки символов. Обеспечим для пользоватлей возможность выбора. Добавим список зависимых переключателей для выбора.
$form['seogenerator_type'] = array(
'#type' => 'radios',
'#title' => t('Метод подстановки'),
'#default_value' => variable_get('seogenerator_type', 0),
'#options' => array(0 => 'Первый', 1 => 'Случайный'),
'#description' => t('Метод подстановки синонимов (первый или случайный).'),
);
Добавим стандартные кнопки и обработчик результатов заполнения формы.
return system_settings_form($form);
Определим права доступа к странице настройки модуля.
/**
* hook_permission().
*/
function seogenerator_permission() {
return array(
'administer seogenerator' => array(
'title' => t('Администратирование SeoGenerator'),
'description' => t('Изменение настроек модуля SeoGenerator.'),
),
);
}
Для определения новой задачи cron существует хук hook_cron_queue_info. В параметре worker callback указываем какая функция будет вызываться при выполнении cron. Параметр time определяет время выполнения функции.
/**
* hook_cron_queue_info()
*/
function seogenerator_cron_queue_info() {
$queues['seogenerator'] = array(
'worker callback' => '_seogenerator_update',
'time' => 5,
);
return $queues;
}
Функция выполняет запросы на сайт и заменяет заголовок узла и его содержимое на сгенерированный текст. Сайт позволяет за один раз генерировать только 6 тысяч символов. Поэтому разбираем текст на части.
В завершении добавляет запись в базу данных об уникализации нашего материала.
function _seogenerator_update($node) {
watchdog('seogenerator', $node->nid, array(), WATCHDOG_INFO);
$node = node_load($node->nid);
$node->title = _seogenerator_query($node->title);
$body = $node->body['und'][0]['value'];
$elements = str_split($body, 6000);
$node->body['und'][0]['value'] = '';
foreach ($elements as $element) {
$body = _seogenerator_query($element);
$node->body['und'][0]['value'] .= $body;
}
node_save($node);
db_insert('seogenerator')
->fields(array('nid' => $node->nid))
->execute();
}
Функция для выполнения запроса с помощью cURL на сайт seogenerator.ru. Отправляем параметры для генератора текста и получаем ответ.
function _seogenerator_query($text) {
$params = array();
$params['text'] = $text;
$params['base'] = variable_get('seogenerator_base', 0);
$params['type'] = variable_get('seogenerator_type', 0);
$params['format'] = 'text';
$curl = curl_init();
curl_setopt($curl, CURLOPT_URL, 'http://seogenerator.ru/api/synonym/');
curl_setopt($curl, CURLOPT_POST, 1);
curl_setopt($curl, CURLOPT_POSTFIELDS, $params);
curl_setopt($curl, CURLOPT_HEADER,0);
curl_setopt($curl, CURLOPT_SSL_VERIFYPEER, FALSE);
curl_setopt($curl, CURLOPT_RETURNTRANSFER, 1);
$result = curl_exec($curl);
curl_close($curl);
return $result == 'Exceeded the limit queries from this IP address'? $text : $result;
}
Для перехвата cron используем хук hook_cron.
/**
* hook_cron()
*/
function seogenerator_cron() {
if (variable_get('seogenerator_enable', 0)) {
...
}
}
Выполняем запрос в базу данных и получаем список id узлов, которые отсутствуют в нашем списке обработанных узлов. Для этого формируем запрос в базу данных.
$nodes = db_select('node', 'n');
$nodes->leftJoin('seogenerator', 's', 'n.nid = s.nid');
$nodes = $nodes
->fields('n', array('nid'))
->range(0, 5)
->condition('n.type', _seogenerator_get_selected_node_types())
->isNull('s.nid')
->execute()
->fetchAll();
Добавляем элементы для выполнения нашей задачи, с помощью cron. Для этого в Drupal 7 предназначен объект DrupalQueue. Метод get устанавливает задачу. Как добавить новую задачу было рассказано выше. Используя метод createItem мы можем добавить новый элемент к нашей задачи. Параметры этого метода передаются функции, которая была установлена для задачи cron.
$queue = DrupalQueue::get('seogenerator');
foreach($nodes as $node) {
$queue->createItem($node);
}