WordPress cron + Crontrol + Events Calendar plugin
Займемся созданием планировщика для WordPress, который будет отправлять почту и смс о предстоящих событиях. Используем api wp-cron.php в связке с плагином Crontrol. Скрипт будет брать события, созданные в категории Events Calendar WD (плагин). Далее проверит события за текущий день, завтрашний, а также на всю неделю вперед.
Событие регистрируется как wp_schedule_event(). Оно проверяется на хите, т.е. надо будет запускать его серверным кроном, обращаясь к wp-cron.php( оставим на финал статьи). В параметрахwp_schedule_event() передается точка отсчета крона, частота, хук. Перед запуском события надо проверить не выполнялось ли оно ранее
!wp_next_scheduled(‘name’)
К хукам добавим функции
add_action(‘hook_name’ , ‘func_name’);
Крон запустит хук, хук — функцию, функции проверят события в календаре. Если найдутся совпадения — отправиться уведомление на почту и по смс.
Поместим скрипт планировщика в отд. файл. cron_tasks.php
// functions.php
require_once( get_template_directory() . '/inc/cron_tasks.php' );
Зарегистрируем 3 события.
$date1 = new DateTime("now");
if( !wp_next_scheduled('weekly_hook') ){
// события календаря от понедельника на неделю
$monday = new DateTime("monday this week");
$week_date = $monday->setTime("10","00","00");
wp_schedule_event( $week_date->getTimestamp() , 'weekly', 'weekly_hook');
}
if( !wp_next_scheduled('daily_hook') ) {
// ежедневная проверка
$day_date = $date1->setTime("10","00","00");
wp_schedule_event( $day_date->getTimestamp() , 'daily', 'daily_hook');
}
if( !wp_next_scheduled('daily_tomorrow_hook') ) {
// проверка событий на завтра
$day_date = $date1->setTime("18","00","00");
wp_schedule_event( $day_date->getTimestamp() , 'daily', 'daily_tomorrow_hook');
}
Назначим функции для хуков
add_action('weekly_hook' , 'weekly_func');
add_action('daily_hook' , 'daily_func');
add_action('daily_tomorrow_hook' , 'daily_tomorrow_func');
Ниже сами функции
/**
* еженедельно
*/
function weekly_func(){
$monday = new DateTime("monday this week");
$week_date = $monday->setTime("10","00","00");
check_posts($week_date->format("Y-m-d H:i:s"), "week");
}
/**
* ежедневно
*/
function daily_func(){
$date_today = new DateTime("now");
$date_today->setTime("9","00","00");
check_posts($date_today->format("Y-m-d"), "day");
}
/**
* на завтра
*/
function daily_tomorrow_func(){
$date_today = new DateTime("now");
$date_today->add(new DateInterval('P1D'));
$date_today->setTime("21","00","00");
check_posts($date_today->format("Y-m-d"), "tomorrow");
}
Они вызывают калбек check_posts(), к-й проверяет наличие запланированных событий. check_posts()в параметрах принимает точку отсчета и период.
Получим события календаря для проверки их актуальности.
// посты типа ecwd_event
$args = array(
'posts_per_page' => -1,
'orderby' => 'date',
'order' => 'DESC',
'include' => array(),
'exclude' => array(),
'post_type' => 'ecwd_event',
'suppress_filters' => true,
);
$posts = get_posts( $args );
Пробегаясь по массиву постов типа ecwd_event, проверяем даты этих постов from и to методами check_week_interval() и check_day_interval(). В параметрах check_xxx_interval() — дата когда крон выполнился (сегодня) и интервал поста-события. Событие календаря может длиться несколько дней.
Забегая вперед, если условие сработало — формируется тело письма и отправляется смс-почта.
/**
* @param $cron_date
* @param $period
*/
// проверка актуальных постов
function check_posts($cron_date, $period){
global $posts, $body_week, $body_day, $body_day_tomorrow, $body_week_text , $body_day_text;
foreach($posts as $post){
$post_meta = get_post_meta($post->ID, '', true);
// посты типа ecwd_event
$from_date = $post_meta["ecwd_event_date_from"][0];
$to_date = $post_meta["ecwd_event_date_to"][0];
// еженедельная проверка
if($period == "week"){
if(check_week_interval($cron_date, $from_date)){
$from_date = new DateTime($from_date);
$body_week .= "".$post->post_title." ".
"начало в ".$from_date->format("d.m").";
";
$body_week_text = true;
}
}// ежедневная проверка
else if($period == "day"){
if(check_day_interval($cron_date, $from_date, $to_date)){
$from_date = new DateTime($from_date);
$body_day .= "".$post->post_title." ".
"начало в ".$from_date->format("H:i").";
";
$body_day_text = true;
}
}// проверка завтрашнего дня
else if($period == "tomorrow"){
if(check_day_interval($cron_date, $from_date, $to_date)){
$from_date = new DateTime($from_date);
$body_day_tomorrow .= "".$post->post_title." ".
"начало в ".$from_date->format("H:i").";
";
$body_day_tomorrow_text = true;
}
}
}
if($body_week_text == true && $period == "week"){
send_email_sms($body_week);
}
if($body_day_text == true && $period == "day"){
send_email_sms($body_day);
}
if($body_day_tomorrow_text == true && $period == "tomorrow"){
send_email_sms($body_day_tomorrow);
}
}
Рассмотрим проверку интервалов постов.
/**
* @param $cron_date
* @param $from_date
* @return bool
*/
function check_week_interval($cron_date, $from_date){
return strtotime($from_date) >= strtotime($cron_date) && strtotime($from_date) <= strtotime($cron_date) + WEEK_IN_SECONDS + 60*60*6 ;
}
WEEK_IN_SECONDS — это константа WP. Еженедельная проверка осуществляется в рамках недели, т.е. дата начала события ($from_date) должна быть в интервале недели от ПН. Ежеденная проверка же — в рамках события-поста.
/**
* @param $cron_date
* @param $from_date
* @param $to_date
* @return bool
*/
function check_day_interval($cron_date, $from_date, $to_date){
// интервал преобразуется в ранжированный массив
$dates_range = dateRange($from_date, $to_date);
return in_array($cron_date, $dates_range);
}
Ранжирование временного периода поста
/**
* @param $first
* @param $last
* @param string $step
* @param string $format
* @return array
*/
function dateRange($first, $last, $step = '+1 day', $format = 'Y-m-d' ) {
$dates = array();
$current = strtotime($first);
$last = strtotime($last);
while( $current <= $last ) {
$dates[] = date($format, $current);
$current = strtotime($step, $current);
}
return $dates;
}
Если сегодняшний день в пределах рамок события календаря — значит событие надо добавить в рассылку. check_day_interval() вернет true.
Итак, проверки интервалов завершились, сформировались тела сообщений. Начало сообщений общее, поэтому заранее выносим его.
$body_week = "<p>Здравствуйте! На следующей неделе запланировано: </p>";
$body_day = "<p>Здравствуйте! Сегодня запланировано: </p>";
$body_day_tomorrow = "<p>Здравствуйте! На завтра запланировано: </p>";
$body_week_text = $body_day_text = $body_day_tomorrow_text = false;
Сработал колбек send_email_sms(). Здесь для каждого польз-ля проверяется его подписка на смс и почту.
$subject = 'mess';
$headers = array();
$headers[] = 'Content-Type: text/html; charset=UTF-8';
// $headers = 'From: aaa@aaa.ru';
$users = get_users( array() );
/**
* @param $text
*/
function send_email_sms($text){
global $users, $subject, $headers;
foreach($users as $user) {
$user_id = $user->data->ID;
// проверка подписок
$subscribe_sms = get_user_option('subscribe_sms', $user_id);
$subscribe_email = get_user_option('subscribe_email', $user_id);
$phone = get_user_option('phone', $user_id);
$to_recepient = $user->data->user_email;
if($subscribe_email == true) {
wp_mail($to_recepient, $subject, $text, $headers);
}
if($subscribe_sms == true){
if(!empty($phone)) {
send_sms($text, $phone);
}
}
}
}
Отправка смс отдельно
/**
* @param $text
* @param $phone_number
* @return mixed
*/
function send_sms($text, $phone_number){
$login = 'mp123456';
$password = '123456';
$sender = 'aaa';
$text = strip_tags($text);
$text = urlencode($text);
$url = "http://api.lalala-sms.ru/messages/v2/send/?phone=%2B7$phone_number&text=$text&login=$login&password=$password&sender=$sender";
$ch = curl_init($url);
curl_setopt($ch, CURLOPT_RETURNTRANSFER, true);
$res = curl_exec($ch);
curl_close($ch);
return $res;
}
По умолчанию апи wp-cron не имеет еженедельной частоты выполнения wp_schedule_event(timestamp, ‘weekly’, ‘hook’). Надо добавить weekly
add_filter( 'cron_schedules', 'true_moi_interval');
function true_moi_interval( $raspisanie ) {
$raspisanie['weekly'] = array(
'interval' => WEEK_IN_SECONDS,
'display' => 'Еженедельно'
);
return $raspisanie;
}
Плагин crontrol покажет нам его во вкладке Настройки — Cron Schedules.
В инструментах плагин добавил вкладку Cron Events, где как раз появились наши события daily_tomorrow_hook, daily_hook, weekly_hook. Можно попробовать их запустить — Run Now.
Событие запускается на хите, но нам надо мануально. Напишем серверный крон, к-й вызовет wp-cron.php. На разных серверах и хостингах команда разная. Можно curl, wget. Пишу нечто стандартное.
*/30 * * * * wget http://example.com/wp-cron.php > /dev/null 2>&1
Leave a comment