PageRenderTime 46ms CodeModel.GetById 17ms RepoModel.GetById 1ms app.codeStats 0ms

/api/business/survey_manager.class.php

https://github.com/patrickdemond/beartooth
PHP | 440 lines | 300 code | 51 blank | 89 comment | 84 complexity | fe490b77599b74639e52596fc204a3c6 MD5 | raw file
  1. <?php
  2. /**
  3. * survey_manager.class.php
  4. *
  5. * @author Patrick Emond <emondpd@mcmaster.ca>
  6. * @filesource
  7. */
  8. namespace beartooth\business;
  9. use cenozo\lib, cenozo\log, beartooth\util;
  10. /**
  11. * survey_manager: record
  12. */
  13. class survey_manager extends \cenozo\singleton
  14. {
  15. /**
  16. * Constructor.
  17. *
  18. * Since this class uses the singleton pattern the constructor is never called directly. Instead
  19. * use the {@link singleton} method.
  20. * @author Patrick Emond <emondpd@mcmaster.ca>
  21. * @access protected
  22. */
  23. protected function __construct() {}
  24. /**
  25. * Gets the current survey URL.
  26. *
  27. * @author Patrick Emond <emondpd@mcmaster.ca>
  28. * @return string (or false if the survey is not active)
  29. * @access public
  30. */
  31. public function get_survey_url()
  32. {
  33. $session = lib::create( 'business\session' );
  34. if( array_key_exists( 'secondary_id', $_COOKIE ) )
  35. {
  36. // get the participant being sourced
  37. $db_participant = lib::create( 'database\participant', $_COOKIE['secondary_participant_id'] );
  38. if( is_null( $db_participant ) ) return false;
  39. // determine the current sid and token
  40. $sid = $this->get_current_sid();
  41. $token = $this->get_current_token();
  42. if( false === $sid || false == $token ) return false;
  43. // determine which language to use
  44. $lang = $db_participant->language;
  45. if( !$lang ) $lang = 'en';
  46. return LIMESURVEY_URL.sprintf( '/index.php?sid=%s&lang=%s&token=%s&newtest=Y', $sid, $lang, $token );
  47. }
  48. else if( array_key_exists( 'withdrawing_participant', $_COOKIE ) )
  49. {
  50. // get the participant being withdrawn
  51. $db_participant = lib::create( 'database\participant', $_COOKIE['withdrawing_participant'] );
  52. if( is_null( $db_participant ) ) return false;
  53. // determine the current sid and token
  54. $sid = $this->get_current_sid();
  55. $token = $this->get_current_token();
  56. if( false === $sid || false == $token ) return false;
  57. // determine which language to use
  58. $lang = $db_participant->language;
  59. if( !$lang ) $lang = 'en';
  60. return LIMESURVEY_URL.sprintf( '/index.php?sid=%s&lang=%s&token=%s&newtest=Y', $sid, $lang, $token );
  61. }
  62. else
  63. {
  64. // must have an assignment
  65. $db_assignment = $session->get_current_assignment();
  66. if( is_null( $db_assignment ) ) return false;
  67. // the assignment must have an open call
  68. $modifier = lib::create( 'database\modifier' );
  69. $modifier->where( 'end_datetime', '=', NULL );
  70. $call_list = $db_assignment->get_phone_call_list( $modifier );
  71. if( 0 == count( $call_list ) ) return false;
  72. // determine the current sid and token
  73. $sid = $this->get_current_sid();
  74. $token = $this->get_current_token();
  75. if( false === $sid || false == $token ) return false;
  76. // determine which language to use
  77. $lang = $db_assignment->get_interview()->get_participant()->language;
  78. if( !$lang ) $lang = 'en';
  79. return LIMESURVEY_URL.sprintf( '/index.php?sid=%s&lang=%s&token=%s&newtest=Y', $sid, $lang, $token );
  80. }
  81. return false; // will never happen
  82. }
  83. /**
  84. * This method returns the current SID, or false if all surveys are complete.
  85. * @author Patrick Emond <emondpd@mcmaster.ca>
  86. * @return int
  87. * @access public
  88. */
  89. public function get_current_sid()
  90. {
  91. if( is_null( $this->current_sid ) ) $this->determine_current_sid_and_token();
  92. return $this->current_sid;
  93. }
  94. /**
  95. * This method returns the current token, or false if all surveys are complete.
  96. * @author Patrick Emond <emondpd@mcmaster.ca>
  97. * @return string
  98. * @access public
  99. */
  100. public function get_current_token()
  101. {
  102. if( is_null( $this->current_token ) ) $this->determine_current_sid_and_token();
  103. return $this->current_token;
  104. }
  105. /**
  106. * Determines the current SID and token.
  107. *
  108. * This method will first determine whether the participant needs to complete the withdraw
  109. * script or a questionnaire. It then determines whether the appropriate script has been
  110. * completed or not.
  111. * Note: This method will create tokens in the limesurvey database as necessary.
  112. * This is also where interviews are marked as complete once all phases are finished.
  113. *
  114. * @author Patrick Emond <emondpd@mcmaster.ca>
  115. * @access protected
  116. */
  117. protected function determine_current_sid_and_token()
  118. {
  119. $this->current_sid = false;
  120. $this->current_token = false;
  121. $tokens_class_name = lib::get_class_name( 'database\limesurvey\tokens' );
  122. $survey_class_name = lib::get_class_name( 'database\limesurvey\survey' );
  123. $session = lib::create( 'business\session' );
  124. if( array_key_exists( 'secondary_id', $_COOKIE ) )
  125. {
  126. // get the participant being sourced
  127. $db_participant = lib::create( 'database\participant', $_COOKIE['secondary_participant_id'] );
  128. if( is_null( $db_participant ) )
  129. {
  130. log::warning( 'Tried to determine survey information for an invalid participant.' );
  131. return false;
  132. }
  133. $setting_manager = lib::create( 'business\setting_manager' );
  134. $sid = $setting_manager->get_setting( 'general', 'secondary_survey' );
  135. $token = $_COOKIE['secondary_id'];
  136. $tokens_class_name::set_sid( $sid );
  137. $survey_class_name::set_sid( $sid );
  138. // reset the script and token
  139. $tokens_mod = lib::create( 'database\modifier' );
  140. $tokens_mod->where( 'token', '=', $token );
  141. foreach( $tokens_class_name::select( $tokens_mod ) as $db_tokens ) $db_tokens->delete();
  142. $scripts_mod = lib::create( 'database\modifier' );
  143. $scripts_mod->where( 'token', '=', $token );
  144. foreach( $survey_class_name::select( $scripts_mod ) as $db_survey ) $db_survey->delete();
  145. $db_tokens = lib::create( 'database\limesurvey\tokens' );
  146. $db_tokens->token = $token;
  147. $db_tokens->firstname = $db_participant->first_name;
  148. $db_tokens->lastname = $db_participant->last_name;
  149. $db_tokens->update_attributes( $db_participant );
  150. $db_tokens->save();
  151. // the secondary survey can be brought back up after it is complete, so always set these
  152. $this->current_sid = $sid;
  153. $this->current_token = $token;
  154. }
  155. else if( array_key_exists( 'withdrawing_participant', $_COOKIE ) )
  156. {
  157. // get the participant being withdrawn
  158. $db_participant = lib::create( 'database\participant', $_COOKIE['withdrawing_participant'] );
  159. if( is_null( $db_participant ) )
  160. {
  161. log::warning( 'Tried to determine survey information for an invalid participant.' );
  162. return false;
  163. }
  164. $db_qnaire = $db_participant->get_effective_qnaire();
  165. if( is_null( $db_qnaire ) )
  166. { // finished all qnaires, find the last one completed
  167. $db_assignment = $db_participant->get_last_finished_assignment();
  168. if( !is_null( $db_assignment ) )
  169. {
  170. $db_qnaire = $db_assignment->get_interview()->get_qnaire();
  171. }
  172. else
  173. { // it is possible that the interview was completed without any assignments
  174. $interview_mod = lib::create( 'database\modifier' );
  175. $interview_mod->order_desc( 'id' );
  176. $interview_list = $db_participant->get_interview_list( $interview_mod );
  177. if( 0 == count( $interview_list ) )
  178. throw lib::create( 'exception\runtime',
  179. 'Trying to withdraw participant without a questionnaire.',
  180. __METHOD__ );
  181. $db_interview = current( $interview_list );
  182. $db_qnaire = $db_interview->get_qnaire();
  183. }
  184. }
  185. $sid = $db_qnaire->withdraw_sid;
  186. $survey_class_name::set_sid( $sid );
  187. $tokens_class_name::set_sid( $sid );
  188. $token = $db_participant->uid;
  189. $tokens_mod = lib::create( 'database\modifier' );
  190. $tokens_mod->where( 'token', '=', $token );
  191. $db_tokens = current( $tokens_class_name::select( $tokens_mod ) );
  192. if( false === $db_tokens )
  193. { // token not found, create it
  194. $db_tokens = lib::create( 'database\limesurvey\tokens' );
  195. $db_tokens->token = $token;
  196. $db_tokens->firstname = $db_participant->first_name;
  197. $db_tokens->lastname = $db_participant->last_name;
  198. $db_tokens->update_attributes( $db_participant );
  199. $db_tokens->save();
  200. $this->current_sid = $sid;
  201. $this->current_token = $token;
  202. }
  203. else if( 'N' == $db_tokens->completed )
  204. {
  205. $this->current_sid = $sid;
  206. $this->current_token = $token;
  207. }
  208. else // token is complete, store the survey results
  209. {
  210. // figure out which token attributes are which
  211. $db_surveys = lib::create( 'database\limesurvey\surveys', $sid );
  212. $attributes = array();
  213. foreach( $db_surveys->get_token_attribute_names() as $key => $value )
  214. $attributes[$value] = $db_tokens->$key;
  215. // only worry about participants who have provided data
  216. if( array_key_exists( 'provided data', $attributes ) &&
  217. 'no' != $attributes['provided data'] )
  218. {
  219. if( 0 == $attributes['written consent received'] )
  220. $letter_type = 0 < $attributes['consented to provide HIN'] ? 'q' : 'r';
  221. else // written consent was received, write the letter type to the database
  222. {
  223. if( 'partial' == $attributes['provided data'] )
  224. $letter_type = 0 < $attributes['consented to provide HIN'] ? 's' : 't';
  225. else // full data received
  226. {
  227. if( 'comprehensive' == $db_participant->get_cohort()->name &&
  228. $attributes['last interview date'] == 'DATE UNKNOWN' ) // in-home only
  229. $letter_type = 0 < $attributes['consented to provide HIN'] ? 'o' : 'p';
  230. else // not in-home only
  231. {
  232. // from here we need to know whether default was applied or not
  233. $survey_mod = lib::create( 'database\modifier' );
  234. $survey_mod->where( 'token', '=', $token );
  235. $survey_list = $survey_class_name::select( $survey_mod );
  236. $db_survey = current( $survey_list );
  237. // get the code for the def and opt responses
  238. $code = 0 < $attributes['consented to provide HIN'] ? 'HIN' : 'NO_HIN';
  239. $code .= 0 < $attributes['DCS samples'] ? '_SAMP' : '_NO_SAMP';
  240. $response = array();
  241. $response['start'] = $db_survey->get_response( 'WTD_START' );
  242. $response['def'] = $db_survey->get_response( 'WTD_DEF_'.$code );
  243. $response['opt'] = $db_survey->get_response( 'WTD_OPT_'.$code );
  244. // the default option was applied if...
  245. if( 'REFUSED' == $response['start'] ||
  246. 'YES' == $response['def'] ||
  247. 'REFUSED' == $response['def'] ||
  248. 'REFUSED' == $response['opt'] )
  249. {
  250. if( 1 == $attributes['DCS samples'] )
  251. $letter_type = 0 < $attributes['consented to provide HIN'] ? 'k' : 'm';
  252. else
  253. $letter_type = 0 < $attributes['consented to provide HIN'] ? 'l' : 'n';
  254. }
  255. else
  256. {
  257. if( 'OPTION1' == $response['opt'] )
  258. {
  259. if( 1 == $attributes['DCS samples'] )
  260. $letter_type = 0 < $attributes['consented to provide HIN'] ? 'a' : 'c';
  261. else
  262. $letter_type = 0 < $attributes['consented to provide HIN'] ? 'b' : 'd';
  263. }
  264. else if( 'OPTION2' == $response['opt'] )
  265. {
  266. if( 1 == $attributes['DCS samples'] )
  267. $letter_type = 0 < $attributes['consented to provide HIN'] ? 'e' : 'g';
  268. else
  269. $letter_type = 0 < $attributes['consented to provide HIN'] ? 'f' : 'h';
  270. }
  271. else // must be OPTION3
  272. {
  273. // NOTE: to get option 3 participants must have provided HIN
  274. $letter_type = 1 == $attributes['DCS samples'] ? 'i' : 'j';
  275. }
  276. }
  277. }
  278. }
  279. }
  280. // now write the letter type for future reference
  281. $db_participant->withdraw_letter = $letter_type;
  282. $db_participant->save();
  283. }
  284. }
  285. // else do not set the current_sid or current_token members!
  286. }
  287. else
  288. {
  289. $db_assignment = $session->get_current_assignment();
  290. if( is_null( $db_assignment ) )
  291. {
  292. log::warning( 'Tried to determine survey information without an active assignment.' );
  293. return false;
  294. }
  295. // records which we will need
  296. $db_interview = $db_assignment->get_interview();
  297. $db_participant = $db_interview->get_participant();
  298. $db_consent = $db_participant->get_last_consent();
  299. if( $db_consent && false == $db_consent->accept )
  300. { // the participant has withdrawn, check to see if the withdraw script is complete
  301. $db_qnaire = $db_interview->get_qnaire();
  302. // let the tokens record class know which SID we are dealing with
  303. $tokens_class_name::set_sid( $db_qnaire->withdraw_sid );
  304. $token = $db_participant->uid;
  305. $tokens_mod = lib::create( 'database\modifier' );
  306. $tokens_mod->where( 'token', '=', $token );
  307. $db_tokens = current( $tokens_class_name::select( $tokens_mod ) );
  308. if( false === $db_tokens )
  309. { // token not found, create it
  310. $db_tokens = lib::create( 'database\limesurvey\tokens' );
  311. $db_tokens->token = $token;
  312. $db_tokens->firstname = $db_participant->first_name;
  313. $db_tokens->lastname = $db_participant->last_name;
  314. $db_tokens->update_attributes( $db_participant );
  315. $db_tokens->save();
  316. $this->current_sid = $db_qnaire->withdraw_sid;
  317. $this->current_token = $token;
  318. }
  319. else if( 'N' == $db_tokens->completed )
  320. {
  321. $this->current_sid = $db_qnaire->withdraw_sid;
  322. $this->current_token = $token;
  323. }
  324. // else do not set the current_sid or current_token members!
  325. }
  326. else
  327. { // the participant has not withdrawn, check each phase of the interview
  328. $phase_mod = lib::create( 'database\modifier' );
  329. $phase_mod->order( 'rank' );
  330. $phase_list = $db_interview->get_qnaire()->get_phase_list( $phase_mod );
  331. if( 0 == count( $phase_list ) )
  332. {
  333. log::emerg( 'Questionnaire with no phases has been assigned.' );
  334. }
  335. else
  336. {
  337. foreach( $phase_list as $db_phase )
  338. {
  339. // let the tokens record class know which SID we are dealing with
  340. $tokens_class_name::set_sid( $db_phase->sid );
  341. $token = $tokens_class_name::determine_token_string(
  342. $db_interview,
  343. $db_phase->repeated ? $db_assignment : NULL );
  344. $tokens_mod = lib::create( 'database\modifier' );
  345. $tokens_mod->where( 'token', '=', $token );
  346. $db_tokens = current( $tokens_class_name::select( $tokens_mod ) );
  347. if( false === $db_tokens )
  348. { // token not found, create it
  349. $db_tokens = lib::create( 'database\limesurvey\tokens' );
  350. $db_tokens->token = $token;
  351. $db_tokens->firstname = $db_participant->first_name;
  352. $db_tokens->lastname = $db_participant->last_name;
  353. $db_tokens->update_attributes( $db_participant );
  354. // TODO: this is temporary code to fix the TOKEN != "NO" problem in limesurvey
  355. // for survey 63834
  356. if( 63834 == $db_phase->sid && is_null( $db_tokens->attribute_9 ) )
  357. $db_tokens->attribute_9 = "UNKNOWN";
  358. $db_tokens->save();
  359. $this->current_sid = $db_phase->sid;
  360. $this->current_token = $token;
  361. break;
  362. }
  363. else if( 'N' == $db_tokens->completed )
  364. { // we have found the current phase
  365. $this->current_sid = $db_phase->sid;
  366. $this->current_token = $token;
  367. break;
  368. }
  369. // else do not set the current_sid or current_token
  370. }
  371. }
  372. // The interview is not completed here since the interview must be completed by Onyx
  373. // and Onyx must report back when it is done.
  374. }
  375. }
  376. }
  377. /**
  378. * This assignment's current sid
  379. * @var int
  380. * @access private
  381. */
  382. private $current_sid = NULL;
  383. /**
  384. * This assignment's current token
  385. * @var string
  386. * @access private
  387. */
  388. private $current_token = NULL;
  389. }