#!/usr/bin/php * @version 1.0 * @since 02 Nov 2013 21:39:53 */ /******************************************************************** * CONFIG ********************************************************************/ define('_CLI', true); require realpath(dirname(__FILE__) . '/../app/_config.inc.php'); require_once 'models/Survey.inc.php'; require_once 'models/Participant.inc.php'; $app->setParam(array( 'log_screen_priority' => LOG_DEBUG, 'log_file_priority' => LOG_NOTICE, 'error_reporting' => E_ALL, )); /******************************************************************** * MAIN ********************************************************************/ // Process command line options. $options = getopt('dhr'); // Help! if (!$options || isset($options['h'])) { usage(); $app->stop(); die; } // Get survey to run: only one survey, with a begin_datetime that has passed, which isn't closed yet. if (!$s = Survey::getCurrent()) { // No survey to run. $app->logMsg(sprintf('No survey available to run now.', null), LOG_INFO, __FILE__, __LINE__); $app->stop(); die; } $app->logMsg(sprintf('The current survey_id is %s', $s['survey_id']), LOG_DEBUG, __FILE__, __LINE__); // Get participants for this survey. For now, all participants will be in every survey. $qid = $db->query(" SELECT participant_tbl.* FROM participant_tbl -- WHERE participant_id NOT BETWEEN '2' AND '91' # Exclude test-numbers. /// # We're not using the following three lines. #LEFT JOIN participant_survey_tbl ON (participant_tbl.participant_id = participant_survey_tbl.participant_id) #WHERE participant_survey_tbl.survey_id = '" . $db->escapeString($s['survey_id']) . "' #ORDER BY participant_tbl.participant_id ASC "); $participants = array(); while ($row = mysql_fetch_assoc($qid)) { $participants[] = $row; } if (empty($participants)) { // No participants in this survey. $app->logMsg(sprintf('No participants found for survey_id %s', $s['survey_id']), LOG_INFO, __FILE__, __LINE__); $app->stop(); die; } $app->logMsg(sprintf('Found %s participants for survey_id %s', sizeof($participants), $s['survey_id']), LOG_DEBUG, __FILE__, __LINE__); // Ok, let's get this survey underway. if ('underway' != $s['status']) { $app->logMsg(sprintf('Setting survey_id %s status to "underway"', $s['survey_id']), LOG_DEBUG, __FILE__, __LINE__); $db->query("UPDATE survey_tbl SET status = 'underway' WHERE survey_id = '" . $db->escapeString($s['survey_id']) . "'"); } // Loop through participants. $count = 0; foreach ($participants as $i => $p) { // Check participant survey status. if (!$p_s_status = Participant::getSurveyStatus($p['participant_id'], $s['survey_id'])) { // User has not yet joined this survey; add them now. Survey::addParticipant($p['participant_id'], $s['survey_id']); } else { switch ($p_s_status['status']) { case 'pending' : $app->logMsg(sprintf('Participant_id %s is pending in survey_id %s', $p['participant_id'], $s['survey_id']), LOG_DEBUG, __FILE__, __LINE__); break; case 'underway' : $app->logMsg(sprintf('Participant_id %s is underway in survey_id %s', $p['participant_id'], $s['survey_id']), LOG_DEBUG, __FILE__, __LINE__); break; case 'completed' : // User has finished this survey; skip them. $app->logMsg(sprintf('Participant_id %s is completed in survey_id %s', $p['participant_id'], $s['survey_id']), LOG_DEBUG, __FILE__, __LINE__); continue 2; } } // Discover the next question to ask for this user. if (!$q = Participant::getCurrentQuestion($p['participant_id'])) { // Couldn't find a question for this participant, probably because he reached the end of the survey; skip him. $app->logMsg(sprintf("Couldn't find a question for participant_id %s", $p['participant_id']), LOG_DEBUG, __FILE__, __LINE__); continue; } if (Participant::wasSentQuestion($p['participant_id'], $q['question_id'])) { // This participant has already been sent the current question. // We must wait for him to reply to it before we send another. $app->logMsg(sprintf('Waiting for reply from participant_id %s to question_id %s', $p['participant_id'], $q['question_id']), LOG_DEBUG, __FILE__, __LINE__); continue; } // Get the details of the question we're gonna send. $q = Question::get(array('question_id' => $q['question_id'])); if (!isset($options['d'])) { // Send the question text to this participant. SMS::send($p['phone'], $q['question_text']); // Mark this question as having been sent to this participant. $db->query(" UPDATE participant_survey_tbl SET status = 'underway', current_question_id = '" . $db->escapeString($q['question_id']) . "' WHERE participant_id = '" . $db->escapeString($p['participant_id']) . "' AND survey_id = '" . $db->escapeString($s['survey_id']) . "' "); $db->query(" INSERT INTO participant_question_tbl ( participant_id, question_id, sent_datetime ) VALUES ( '" . $db->escapeString($p['participant_id']) . "', '" . $db->escapeString($q['question_id']) . "', NOW() ) "); $app->logMsg(sprintf('Set current_question_id to %s for participant_id %s', $q['question_id'], $p['participant_id']), LOG_DEBUG, __FILE__, __LINE__); // If this is a statement rather than a question, we are not expecting a response; let's emulate a response so the next question is sent automatically. if ($q['auto_continue'] == 'true') { // Discover the next question to ask for this user. if (!$next_q = Question::getNextInSurvey($q['question_id'], $s['survey_id'])) { // No more questions; implicit end of survey. Survey::endParticipant($p['participant_id'], $s['survey_id']); continue; } // Set current_question_id to the next question. $db->query(" UPDATE participant_survey_tbl SET current_question_id = '" . $db->escapeString($next_q['question_id']) . "' WHERE participant_id = '" . $db->escapeString($p['participant_id']) . "' AND survey_id = '" . $db->escapeString($s['survey_id']) . "' "); $app->logMsg(sprintf('Set current_question_id to %s for participant_id %s (auto-continue)', $next_question_id, $p['participant_id']), LOG_INFO, __FILE__, __LINE__); } } $app->logMsg(sprintf('Sent SMS to participant_id %s (%s): %s', $p['participant_id'], $p['phone'], $q['question_text']), LOG_INFO, __FILE__, __LINE__); $count++; } // Done! $app->logMsg(sprintf('Sent %s SMSs', $count), LOG_INFO, __FILE__, __LINE__); /******************************************************************** * FUNCTIONS ********************************************************************/ function usage() { ?> This script should be run every 10 minutes via cron. It checks if there are any surveys to send, calculates which questions to send to which users. Usage: [OPTIONS] OPTIONS -d Debug mode; don't really send anything -h Display this help message. -r Really send the queued questions! stop();