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

/application/controllers/admin/participantsaction.php

https://bitbucket.org/sammousa/valuematchbv-ls2
PHP | 1770 lines | 1332 code | 162 blank | 276 comment | 190 complexity | 5285531018425b7becb137d642f3558a MD5 | raw file
Possible License(s): GPL-2.0, LGPL-2.1, BSD-3-Clause, GPL-3.0, LGPL-3.0
  1. <?php if ( ! defined('BASEPATH')) exit('No direct script access allowed');
  2. /*
  3. * LimeSurvey
  4. * Copyright (C) 2007-2011 The LimeSurvey Project Team / Carsten Schmitz
  5. * All rights reserved.
  6. * License: GNU/GPL License v2 or later, see LICENSE.php
  7. * LimeSurvey is free software. This version may have been modified pursuant
  8. * to the GNU General Public License, and as distributed it includes or
  9. * is derivative of works licensed under the GNU General Public License or
  10. * other free or open source software licenses.
  11. * See COPYRIGHT.php for copyright notices and details.
  12. *
  13. * $Id$
  14. */
  15. function subval_sort($a, $subkey, $order)
  16. {
  17. $b = array();
  18. $c = array();
  19. foreach ($a as $k => $v)
  20. {
  21. $b[$k] = strtolower($v[$subkey]);
  22. }
  23. if ($order == "asc")
  24. {
  25. asort($b, SORT_REGULAR);
  26. }
  27. else
  28. {
  29. arsort($b, SORT_REGULAR);
  30. }
  31. foreach ($b as $key => $val)
  32. {
  33. $c[] = $a[$key];
  34. }
  35. return $c;
  36. }
  37. /*
  38. * This is the main controller for Participants Panel
  39. */
  40. class participantsaction extends Survey_Common_Action
  41. {
  42. public function runWithParams($params)
  43. {
  44. if (!hasGlobalPermission('USER_RIGHT_PARTICIPANT_PANEL'))
  45. {
  46. die('No permission');
  47. }
  48. parent::runWithParams($params);
  49. }
  50. /**
  51. * Loads jqGrid for the view
  52. * @param string $sScript Subaction
  53. */
  54. private function _loadjqGrid($sScript = '', $aData = array())
  55. {
  56. $this->getController()->_js_admin_includes(Yii::app()->getConfig('generalscripts') . 'jquery/jqGrid/js/i18n/grid.locale-en.js');
  57. $this->getController()->_js_admin_includes(Yii::app()->getConfig('generalscripts') . 'jquery/jqGrid/js/jquery.jqGrid.min.js');
  58. $this->getController()->_js_admin_includes(Yii::app()->getConfig('generalscripts') . 'jquery/jqGrid/plugins/jquery.searchFilter.js');
  59. $this->getController()->_js_admin_includes(Yii::app()->getConfig('generalscripts') . 'jquery/jqGrid/src/grid.celledit.js');
  60. $this->getController()->_css_admin_includes(Yii::app()->getConfig('generalscripts') . 'jquery/jqGrid/css/ui.jqgrid.css');
  61. $this->getController()->_css_admin_includes(Yii::app()->getConfig('generalscripts') . 'jquery/jqGrid/css/jquery.ui.datepicker.css');
  62. if (!empty($sScript))
  63. {
  64. $this->getController()->_js_admin_includes(Yii::app()->getConfig('adminscripts') . $sScript . '.js');
  65. $this->_renderWrappedTemplate('participants', array('participantsPanel', $sScript), $aData);
  66. }
  67. }
  68. /**
  69. * Renders template(s) wrapped in header and footer
  70. *
  71. * @param string $sAction Current action, the folder to fetch views from
  72. * @param string|array $aViewUrls View url(s)
  73. * @param array $aData Data to be passed on. Optional.
  74. */
  75. protected function _renderWrappedTemplate($sAction = 'participants', $aViewUrls = array(), $aData = array())
  76. {
  77. $aData['display']['menu_bars'] = false;
  78. foreach((array) $aViewUrls as $sViewUrl)
  79. {
  80. $a_ViewUrls[] = $sViewUrl . '_view';
  81. }
  82. parent::_renderWrappedTemplate($sAction, $a_ViewUrls, $aData);
  83. }
  84. /**
  85. * Export to csv using optional search/filter
  86. *
  87. * @param type $search
  88. */
  89. private function csvExport($search = null) {
  90. Yii::app()->loadHelper('export');
  91. $attid = ParticipantAttributeNames::model()->getVisibleAttributes();
  92. //If super admin all the participants will be visible
  93. if (Yii::app()->session['USER_RIGHT_SUPERADMIN'])
  94. {
  95. $iUserID = null;
  96. } else {
  97. $iUserID = Yii::app()->session['loginID'];
  98. }
  99. $query = Participants::model()->getParticipants(0, 0, $attid, null, $search, $iUserID);
  100. if (!$query)
  101. return false;
  102. // Field names in the first row
  103. $fields = array('participant_id', 'firstname', 'lastname', 'email', 'language', 'blacklisted', 'owner_uid');
  104. $outputarray = array(); // The array to be passed to the export helper to be written to a csv file
  105. $outputarray[0] = $fields; //fields written to output array
  106. // If attribute fields are selected, add them to the output
  107. $queryId = Yii::app()->request->getQuery('id');
  108. if (!is_null($queryId) && $queryId != "null") {
  109. $iAttributeId = explode(",", $queryId);
  110. foreach ($iAttributeId as $key => $value)
  111. {
  112. $fields[] = 'a'.$value;
  113. $attributename = ParticipantAttributeNames::model()->getAttributeNames($value);
  114. $outputarray[0][] = $attributename[0]['attribute_name'];
  115. }
  116. }
  117. $fieldKeys = array_flip($fields);
  118. foreach ($query as $field => $aData)
  119. {
  120. $outputarray[] = array_intersect_key($aData, $fieldKeys);
  121. }
  122. CPDBExport($outputarray, "central_" . time());
  123. }
  124. /**
  125. * Returns a string with the number of participants available for export or 0
  126. *
  127. * @param type $search
  128. * @return string|0
  129. */
  130. protected function csvExportCount($search = null)
  131. {
  132. $clang = $this->getController()->lang;
  133. $attid = ParticipantAttributeNames::model()->getVisibleAttributes();
  134. //If super admin all the participants will be visible
  135. if (Yii::app()->session['USER_RIGHT_SUPERADMIN'])
  136. {
  137. $iUserID = null;
  138. } else {
  139. $iUserID = Yii::app()->session['loginID'];
  140. }
  141. $count = Participants::model()->getParticipantsCount($attid, $search, $iUserID);
  142. if ($count > 0) {
  143. return sprintf($clang->gT("Export %s participant(s) to CSV"), $count);
  144. } else {
  145. return $count;
  146. }
  147. }
  148. /**
  149. * Loads the view 'participantsPanel'
  150. */
  151. function index()
  152. {
  153. $iUserID = Yii::app()->session['loginID'];
  154. // if superadmin all the records in the cpdb will be displayed
  155. if (Yii::app()->session['USER_RIGHT_SUPERADMIN'])
  156. {
  157. $iTotalRecords = Participants::model()->count();
  158. }
  159. // if not only the participants on which he has right on (shared and owned)
  160. else
  161. {
  162. $iTotalRecords = Participants::model()->getParticipantsOwnerCount($iUserID);
  163. }
  164. // gets the count of participants, their attributes and other such details
  165. $aData = array(
  166. 'totalrecords' => $iTotalRecords,
  167. 'owned' => Participants::model()->count('owner_uid = ' . $iUserID),
  168. 'shared' => Participants::model()->getParticipantsSharedCount($iUserID),
  169. 'attributecount' => ParticipantAttributeNames::model()->count(),
  170. 'blacklisted' => Participants::model()->count('owner_uid = ' . $iUserID . ' AND blacklisted = \'Y\'')
  171. );
  172. // loads the participant panel and summary view
  173. $this->_renderWrappedTemplate('participants', array('participantsPanel', 'summary'), $aData);
  174. }
  175. /**
  176. * Loads the view 'importCSV'
  177. */
  178. function importCSV()
  179. {
  180. $this->_renderWrappedTemplate('participants', array('participantsPanel', 'importCSV'));
  181. }
  182. /**
  183. * Loads the view 'displayParticipants' which contains the main grid
  184. */
  185. function displayParticipants()
  186. {
  187. $lang = Yii::app()->session['adminlang'];
  188. // loads the survey names to be shown in add to survey
  189. // if user is superadmin, all survey names
  190. $urlSearch=Yii::app()->request->getQuery('searchurl');
  191. $urlSearch=!empty($urlSearch) ? "getParticipantsResults_json/search/$urlSearch" : "getParticipants_json";
  192. //Get list of surveys.
  193. //Should be all surveys owned by user (or all surveys for super admin)
  194. $surveys = Survey::model();
  195. //!!! Is this even possible to execute?
  196. if (empty(Yii::app()->session['USER_RIGHT_SUPERADMIN']))
  197. $surveys->permission(Yii::app()->user->getId());
  198. $aSurveyNames = $surveys->model()->with(array('languagesettings'=>array('condition'=>'surveyls_language=language'), 'owner'))->findAll();
  199. /* Build a list of surveys that have tokens tables */
  200. $tSurveyNames=array();
  201. foreach($aSurveyNames as $row)
  202. {
  203. $row = array_merge($row->attributes, $row->languagesettings[0]->attributes);
  204. $bTokenExists = tableExists('{{tokens_' . $row['sid'] . '}}');
  205. if ($bTokenExists) //If tokens table exists
  206. {
  207. $tSurveyNames[]=$row;
  208. }
  209. }
  210. // data to be passed to view
  211. $aData = array(
  212. 'names' => User::model()->findAll(),
  213. 'attributes' => ParticipantAttributeNames::model()->getVisibleAttributes(),
  214. 'allattributes' => ParticipantAttributeNames::model()->getAllAttributes(),
  215. 'attributeValues' => ParticipantAttributeNames::model()->getAllAttributesValues(),
  216. 'surveynames' => $aSurveyNames,
  217. 'tokensurveynames' => $tSurveyNames,
  218. 'urlsearch' => $urlSearch
  219. );
  220. $this->getController()->_js_admin_includes(Yii::app()->getConfig('generalscripts') . 'jquery/jqGrid/js/i18n/grid.locale-en.js');
  221. $this->getController()->_js_admin_includes(Yii::app()->getConfig('generalscripts') . 'jquery/jqGrid/js/jquery.jqGrid.min.js');
  222. $this->getController()->_css_admin_includes(Yii::app()->getConfig('publicstyleurl') . 'jquery.multiselect.css');
  223. $this->getController()->_css_admin_includes(Yii::app()->getConfig('publicstyleurl') . 'jquery.multiselect.filter.css');
  224. $this->getController()->_css_admin_includes(Yii::app()->getConfig('adminstyleurl') . 'displayParticipants.css');
  225. $this->getController()->_css_admin_includes(Yii::app()->getConfig('generalscripts') . 'jquery/jqGrid/css/ui.jqgrid.css');
  226. $this->getController()->_css_admin_includes(Yii::app()->getConfig('generalscripts') . 'jquery/jqGrid/css/jquery.ui.datepicker.css');
  227. // loads the participant panel view and display participant view
  228. $this->_renderWrappedTemplate('participants', array('participantsPanel', 'displayParticipants'), $aData);
  229. }
  230. /**
  231. * Loads the view 'blacklistControl'
  232. */
  233. function blacklistControl()
  234. {
  235. $aData = array(
  236. 'blacklistallsurveys' => Yii::app()->getConfig('blacklistallsurveys'),
  237. 'blacklistnewsurveys' => Yii::app()->getConfig('blacklistnewsurveys'),
  238. 'blockaddingtosurveys' => Yii::app()->getConfig('blockaddingtosurveys'),
  239. 'hideblacklisted' => Yii::app()->getConfig('hideblacklisted'),
  240. 'deleteblacklisted' => Yii::app()->getConfig('deleteblacklisted'),
  241. 'allowunblacklist' => Yii::app()->getConfig('allowunblacklist')
  242. );
  243. $this->_renderWrappedTemplate('participants', array('participantsPanel', 'blacklist'), $aData);
  244. }
  245. /**
  246. * Loads the view 'userControl'
  247. */
  248. function userControl()
  249. {
  250. $aData = array(
  251. 'userideditable' => Yii::app()->getConfig('userideditable')
  252. );
  253. $this->_renderWrappedTemplate('participants', array('participantsPanel', 'userControl'), $aData);
  254. }
  255. /**
  256. * Loads the view 'sharePanel'
  257. */
  258. function sharePanel()
  259. {
  260. $this->_loadjqGrid('sharePanel');
  261. }
  262. /**
  263. * Sends the shared participant info to the share panel using JSON encoding
  264. * Called after the share panel grid is loaded
  265. * Returns the json depending on the user logged in by checking it from the session
  266. * @return JSON encoded string containg sharing information
  267. */
  268. function getShareInfo_json()
  269. {
  270. $aData = new stdClass();
  271. $aData->page = 1;
  272. // If super administrator all the share info in the links table will be shown
  273. if (Yii::app()->session['USER_RIGHT_SUPERADMIN'])
  274. {
  275. $records = Participants::model()->getParticipantSharedAll();
  276. $aData->records = count($records);
  277. $aData->total = ceil($aData->records / 10);
  278. $i = 0;
  279. foreach ($records as $row)
  280. {
  281. $oShared = User::model()->getName($row['share_uid']); //for conversion of uid to human readable names
  282. $owner = User::model()->getName($row['owner_uid']);
  283. $aData->rows[$i]['id'] = $row['participant_id']."--".$row['share_uid']; //This is the unique combination per record
  284. $aData->rows[$i]['cell'] = array($row['firstname'], $row['lastname'], $row['email'], $oShared[0]['full_name'], $row['share_uid'], $owner[0]['full_name'], $row['date_added'], $row['can_edit']);
  285. $i++;
  286. }
  287. echo ls_json_encode($aData);
  288. }
  289. // otherwise only the shared participants by that user
  290. else
  291. {
  292. $records = Participants::model()->getParticipantShared(Yii::app()->session['loginID']);
  293. $aData->records = count($records);
  294. $aData->total = ceil($aData->records / 10);
  295. $i = 0;
  296. foreach ($records as $row)
  297. {
  298. $sharename = User::model()->getName($row['share_uid']); //for conversion of uid to human readable names
  299. $aData->rows[$i]['id'] = $row['participant_id'];
  300. $aData['rows'][$i]['cell'] = array($row['firstname'], $row['lastname'], $row['email'], $sharename['full_name'], $row['share_uid'], $row['date_added'], $row['can_edit']);
  301. $i++;
  302. }
  303. echo ls_json_encode($aData);
  304. }
  305. }
  306. /**
  307. * Takes the edit call from the share panel, which either edits or deletes the share information
  308. * Basically takes the call on can_edit
  309. */
  310. function editShareInfo()
  311. {
  312. $operation = Yii::app()->request->getPost('oper');
  313. $shareIds = Yii::app()->request->getPost('id');
  314. if ($operation == 'del') // If operation is delete , it will delete, otherwise edit it
  315. {
  316. ParticipantShares::model()->deleteRow($shareIds);
  317. }
  318. else
  319. {
  320. $aData = array(
  321. 'participant_id' => Yii::app()->request->getPost('participant_id'),
  322. 'can_edit' => Yii::app()->request->getPost('can_edit'),
  323. 'share_uid' => Yii::app()->request->getPost('shared_uid')
  324. );
  325. ParticipantShares::model()->updateShare($aData);
  326. }
  327. }
  328. /**
  329. * Loads the view 'attributeControl'
  330. */
  331. function attributeControl()
  332. {
  333. $this->_loadjqGrid('attributeControl');
  334. }
  335. /**
  336. * Sends the attributes info using JSON encoding
  337. * Called after the Attribute management grid is loaded
  338. * @return JSON encoded string containg sharing information
  339. */
  340. function getAttributeInfo_json()
  341. {
  342. $clang = Yii::app()->lang;
  343. $page = Yii::app()->request->getPost('page');
  344. $limit = Yii::app()->request->getPost('rows');
  345. $limit = isset($limit) ? $limit : 50; //Stop division by zero errors
  346. $records = ParticipantAttributeNames::model()->with('participant_attribute_names_lang')->findAll();
  347. $attribute_types = array(
  348. 'DD' => $clang->gT("Drop-down list"),
  349. 'DP' => $clang->gT("Date"),
  350. 'TB' => $clang->gT("Text box")
  351. );
  352. $aData = new stdClass();
  353. $aData->page = $page;
  354. $aData->records = count($records);
  355. $aData->total = ceil(ParticipantAttributeNames::model()->getAttributes(true) / $limit);
  356. $i = 0;
  357. foreach($records as $row) { //Iterate through each attribute
  358. $thisname="";
  359. foreach($row->participant_attribute_names_lang as $names) { //Iterate through each language version of this attribute
  360. if($thisname=="") {$thisname=$names->attribute_name;} //Choose the first item by default
  361. if($names->lang == Yii::app()->session['adminlang']) {$thisname=$names->attribute_name;} //Override the default with the admin language version if found
  362. }
  363. $aData->rows[$i]['id'] = $row->attribute_id;
  364. $aData->rows[$i]['cell'] = array('', $thisname, $attribute_types[$row->attribute_type], $row->visible);
  365. $i++;
  366. }
  367. echo ls_json_encode($aData);
  368. }
  369. /**
  370. * Takes the edit call from the share panel, which either edits or deletes the share information
  371. * Basically takes the call on can_edit
  372. */
  373. function editAttributeInfo()
  374. {
  375. $clang = Yii::app()->lang;
  376. $operation = Yii::app()->request->getPost('oper');
  377. if ($operation == 'del' && Yii::app()->request->getPost('id'))
  378. {
  379. $aAttributeIds = (array) explode(',', Yii::app()->request->getPost('id'));
  380. $aAttributeIds = array_map('trim', $aAttributeIds);
  381. $aAttributeIds = array_map('intval', $aAttributeIds);
  382. foreach ($aAttributeIds as $iAttributeId)
  383. {
  384. ParticipantAttributeNames::model()->delAttribute($iAttributeId);
  385. }
  386. }
  387. elseif ($operation == 'add' && Yii::app()->request->getPost('attribute_name'))
  388. {
  389. $aData = array(
  390. 'attribute_name' => Yii::app()->request->getPost('attribute_name'),
  391. 'attribute_type' => Yii::app()->request->getPost('attribute_type'),
  392. 'visible' => Yii::app()->request->getPost('visible') == 'TRUE' ? 'TRUE' : 'FALSE'
  393. );
  394. echo ParticipantAttributeNames::model()->storeAttribute($aData);
  395. }
  396. elseif ($operation == 'edit' && Yii::app()->request->getPost('id'))
  397. {
  398. $aData = array(
  399. 'attribute_id' => Yii::app()->request->getPost('id'),
  400. 'attribute_name' => Yii::app()->request->getPost('attribute_name'),
  401. 'attribute_type' => Yii::app()->request->getPost('attribute_type'),
  402. 'visible' => Yii::app()->request->getPost('visible') == 'TRUE' ? 'TRUE' : 'FALSE'
  403. );
  404. ParticipantAttributeNames::model()->saveAttribute($aData);
  405. $clang->eT("Attribute display setting updated");
  406. }
  407. }
  408. /**
  409. * Takes the delete call from the display participants and take appropriate action depending on the condition
  410. */
  411. function delParticipant()
  412. {
  413. $selectoption = Yii::app()->request->getPost('selectedoption');
  414. $iParticipantId = Yii::app()->request->getPost('participant_id');
  415. //echo $selectoption." -- ".$iParticipantId."<br />"; die();
  416. // Deletes from participants only
  417. if ($selectoption == 'po')
  418. {
  419. Participants::model()->deleteParticipants($iParticipantId);
  420. }
  421. // Deletes from central and token table
  422. elseif ($selectoption == 'ptt')
  423. {
  424. Participants::model()->deleteParticipantToken($iParticipantId);
  425. }
  426. // Deletes from central , token and assosiated responses as well
  427. elseif ($selectoption == 'ptta')
  428. {
  429. Participants::model()->deleteParticipantTokenAnswer($iParticipantId);
  430. }
  431. }
  432. /**
  433. * Resposible for editing data on the jqGrid
  434. */
  435. function editParticipant()
  436. {
  437. $operation = Yii::app()->request->getPost('oper');
  438. //In case the uid is not editable, then user id is not posted and hence the current user is added in the uid
  439. if (Yii::app()->request->getPost('owner_uid') == '')
  440. {
  441. $oid = Yii::app()->session['loginID'];
  442. }
  443. //otherwise the one which is posted is added
  444. else
  445. {
  446. $oid = Yii::app()->request->getPost('owner_uid');
  447. }
  448. if (Yii::app()->request->getPost('language') == '')
  449. {
  450. $lang = Yii::app()->session['adminlang'];
  451. }
  452. else
  453. {
  454. $lang = Yii::app()->request->getPost('language');
  455. }
  456. // if edit it will update the row
  457. if ($operation == 'edit')
  458. {
  459. $aData = array(
  460. 'participant_id' => Yii::app()->request->getPost('id'),
  461. 'firstname' => Yii::app()->request->getPost('firstname'),
  462. 'lastname' => Yii::app()->request->getPost('lastname'),
  463. 'email' => Yii::app()->request->getPost('email'),
  464. 'language' => Yii::app()->request->getPost('language'),
  465. 'blacklisted' => Yii::app()->request->getPost('blacklisted'),
  466. 'owner_uid' => $oid
  467. );
  468. Participants::model()->updateRow($aData);
  469. }
  470. // if add it will insert a new row
  471. elseif ($operation == 'add')
  472. {
  473. $uuid = $this->gen_uuid();
  474. $aData = array(
  475. 'participant_id' => $uuid,
  476. 'firstname' => Yii::app()->request->getPost('firstname'),
  477. 'lastname' => Yii::app()->request->getPost('lastname'),
  478. 'email' => Yii::app()->request->getPost('email'),
  479. 'language' => Yii::app()->request->getPost('language'),
  480. 'blacklisted' => Yii::app()->request->getPost('blacklisted'),
  481. 'owner_uid' => $oid
  482. );
  483. Participants::model()->insertParticipant($aData);
  484. }
  485. }
  486. /**
  487. * Stores the user control setting to the database
  488. */
  489. function storeUserControlValues()
  490. {
  491. if ($find = Settings_global::model()->findByPk('userideditable'))
  492. {
  493. Settings_global::model()->updateByPk('userideditable', array('stg_value'=>Yii::app()->request->getPost('userideditable')));
  494. }
  495. else
  496. {
  497. $stg = new Settings_global;
  498. $stg ->stg_name='userideditable';
  499. $stg ->stg_value=Yii::app()->request->getPost('userideditable');
  500. $stg->save();
  501. }
  502. Yii::app()->getController()->redirect(Yii::app()->getController()->createUrl('admin/participants/sa/userControl'));
  503. }
  504. /**
  505. * Stores the blacklist setting to the database
  506. */
  507. function storeBlacklistValues()
  508. {
  509. $values = Array('blacklistallsurveys', 'blacklistnewsurveys', 'blockaddingtosurveys', 'hideblacklisted', 'deleteblacklisted', 'allowunblacklist', 'userideditable');
  510. foreach ($values as $value)
  511. {
  512. if ($find = Settings_global::model()->findByPk($value))
  513. {
  514. Settings_global::model()->updateByPk($value, array('stg_value'=>Yii::app()->request->getPost($value)));
  515. }
  516. else
  517. {
  518. $stg = new Settings_global;
  519. $stg ->stg_name=$value;
  520. $stg ->stg_value=Yii::app()->request->getPost($value);
  521. $stg->save();
  522. }
  523. }
  524. Yii::app()->getController()->redirect(Yii::app()->getController()->createUrl('admin/participants/sa/blacklistControl'));
  525. }
  526. /**
  527. * Receives an ajax call containing the participant id in the fourth segment of the url
  528. * Supplies list of survey links - surveys of which this participant is on the tokens table
  529. * URL: [localurl]/limesurvey/admin/participants/getSurveyInfo_json/pid/[participant_id]
  530. * RETURNS: json data containing linked survey information (Survey name, survey id, token_id and date_added)
  531. */
  532. function getSurveyInfo_json()
  533. {
  534. $participantid = Yii::app()->request->getQuery('pid');
  535. $records = Survey_links::model()->findAllByAttributes((array('participant_id' => $participantid)));
  536. $aData = new stdClass();
  537. $aData->page = 1;
  538. $aData->records = count($records);
  539. $aData->total = ceil($aData->records / 10);
  540. $i = 0;
  541. foreach ($records as $row)
  542. {
  543. $oSurvey=Survey::model()->with(array('languagesettings'=>array('condition'=>'surveyls_language=language')))->findByAttributes(array('sid' => $row['survey_id']));
  544. foreach($oSurvey->languagesettings as $oLanguageSetting)
  545. {
  546. $surveyname= $oLanguageSetting->surveyls_title;
  547. }
  548. $surveylink = "";
  549. /* Check permissions of each survey before creating a link*/
  550. if (!hasSurveyPermission($row['survey_id'], 'tokens', 'read'))
  551. {
  552. $surveylink = $row['survey_id'];
  553. } else
  554. {
  555. $surveylink = '<a href=' . Yii::app()->getController()->createUrl("/admin/tokens/sa/browse/surveyid/{$row['survey_id']}") . '>' . $row['survey_id'].'</a>';
  556. }
  557. $aData->rows[$i]['cell'] = array($surveyname, $surveylink, $row['token_id'], $row['date_created'], $row['date_invited'], $row['date_completed']);
  558. $i++;
  559. }
  560. echo ls_json_encode($aData);
  561. }
  562. /**
  563. * Returns the count of the participants in the CSV and show it in the title of the modal box
  564. * This is to give the user the hint to see the number of participants he is exporting
  565. */
  566. function exporttocsvcount()
  567. {
  568. $searchconditionurl = Yii::app()->request->getPost('searchcondition');
  569. $searchcondition = basename($searchconditionurl);
  570. if ($searchcondition != 'getParticipants_json') // if there is a search condition then only the participants that match the search criteria are counted
  571. {
  572. $condition = explode("||", $searchcondition);
  573. $search = Participants::model()->getParticipantsSearchMultipleCondition($condition);
  574. } else {
  575. $search = null;
  576. }
  577. echo $this->csvExportCount($search);
  578. }
  579. /**
  580. * Outputs the count of participants when using the export all button on the top
  581. */
  582. function exporttocsvcountAll()
  583. {
  584. echo $this->csvExportCount();
  585. }
  586. /**
  587. * Responsible to export all the participants in the central table
  588. */
  589. function exporttocsvAll()
  590. {
  591. $this->csvExport(); // no search
  592. }
  593. /**
  594. * Similar to export to all message where it counts the number to participants to be copied
  595. * and echo them to be displayed in modal box header
  596. */
  597. function getaddtosurveymsg()
  598. {
  599. $searchcondition = basename(Yii::app()->request->getPost('searchcondition'));
  600. // If there is a search condition in the url of the jqGrid
  601. if ($searchcondition != 'getParticipants_json')
  602. {
  603. $participantid = "";
  604. $condition = explode("||", $searchcondition);
  605. $query = Participants::model()->getParticipantsSearchMultiple($condition, 0, 0);
  606. printf( $this->getController()->lang->gT("%s participant(s) are to be copied "), count($query));
  607. }
  608. // if there is no search condition the participants will be counted on the basis of who is logged in
  609. else
  610. {
  611. if (Yii::app()->session['USER_RIGHT_SUPERADMIN']) //If super admin all the participants will be visible
  612. {
  613. $count = Participants::model()->getParticipantsCountWithoutLimit();
  614. }
  615. else
  616. {
  617. $query = Participants::model()->getParticipantsOwner(Yii::app()->session['loginID']);
  618. $count = count($query);
  619. }
  620. printf($this->getController()->lang->gT("%s participant(s) are to be copied "), $count);
  621. }
  622. }
  623. /**
  624. * Gets the ids of participants to be copied to the individual survey
  625. */
  626. function getSearchIDs()
  627. {
  628. $searchcondition = basename(Yii::app()->request->getPost('searchcondition')); // get the search condition from the URL
  629. /* a search contains posted data inside $_POST['searchcondition'].
  630. * Each seperate query is made up of 3 fields, seperated by double-pipes ("|")
  631. * EG: fname||eq||jason||lname||ct||c
  632. *
  633. */
  634. if ($searchcondition != 'getParticipants_json') // if there is a search condition present
  635. {
  636. $participantid = "";
  637. $condition = explode("||", $searchcondition); // explode the condition to the array
  638. $query = Participants::model()->getParticipantsSearchMultiple($condition, 0, 0);
  639. foreach ($query as $key => $value)
  640. {
  641. if (Yii::app()->session['USER_RIGHT_SUPERADMIN'])
  642. {
  643. $participantid .= "," . $value['participant_id']; // combine the participant id's in an string
  644. } else
  645. {
  646. if(Participants::model()->is_owner($value['participant_id']))
  647. {
  648. $participantid .= "," . $value['participant_id']; // combine the participant id's in an string
  649. }
  650. }
  651. }
  652. echo $participantid; //echo the participant id's
  653. }
  654. else// if no search condition
  655. {
  656. $participantid = ""; // initiallise the participant id to blank
  657. if (Yii::app()->session['USER_RIGHT_SUPERADMIN']) //If super admin all the participants will be visible
  658. {
  659. $query = Participants::model()->getParticipantsWithoutLimit(); // get all the participant id if it is a super admin
  660. }
  661. else // get participants on which the user has right on
  662. {
  663. $query = Participants::model()->getParticipantsOwner(Yii::app()->session['loginID']);
  664. }
  665. foreach ($query as $key => $value)
  666. {
  667. $participantid = $participantid . "," . $value['participant_id']; // combine the participant id's in an string
  668. }
  669. echo $participantid; //echo the participant id's
  670. }
  671. }
  672. /**
  673. * Responsible for reading the CSV file line by line, check for duplicate participants
  674. * invalid participants and invalid attributes and copy them to the central table
  675. * Also responsible for creation of new attribute and mapping of old attribute to attribute in csv
  676. */
  677. function exporttocsv()
  678. {
  679. $searchconditionurl = Yii::app()->request->getPost('searchcondition');
  680. $searchcondition = basename($searchconditionurl);
  681. if ($searchcondition != 'getParticipants_json') // if there is a search condition then only the participants that match the search criteria are counted
  682. {
  683. $condition = explode("||", $searchcondition);
  684. $search = Participants::model()->getParticipantsSearchMultipleCondition($condition);
  685. } else {
  686. $search = null;
  687. }
  688. $this->csvExport($search);
  689. }
  690. /**
  691. * Equal to getParticipants_json() but now with a search
  692. */
  693. function getParticipantsResults_json()
  694. {
  695. $searchcondition = Yii::app()->request->getpost('searchcondition');
  696. $finalcondition = array();
  697. $condition = explode("||", $searchcondition);
  698. $search = Participants::model()->getParticipantsSearchMultipleCondition($condition);
  699. return $this->getParticipants_json($search);
  700. }
  701. /*
  702. * Sends the data in JSON format extracted from the database to be displayed using the jqGrid
  703. */
  704. function getParticipants_json($search = null)
  705. {
  706. $page = Yii::app()->request->getPost('page');
  707. $limit = Yii::app()->request->getPost('rows');
  708. $limit = isset($limit) ? $limit : 50; //Stop division by zero errors
  709. $attid = ParticipantAttributeNames::model()->getVisibleAttributes();
  710. $participantfields = array('participant_id', 'can_edit', 'firstname', 'lastname', 'email', 'blacklisted', 'survey', 'language', 'owner_uid');
  711. foreach ($attid as $key => $value)
  712. {
  713. array_push($participantfields, $value['attribute_id']);
  714. }
  715. $sidx = Yii::app()->request->getPost('sidx');
  716. $sidx = !empty($sidx) ? $sidx : "lastname";
  717. $sord = Yii::app()->request->getPost('sord');
  718. $sord = !empty($sord) ? $sord : "asc";
  719. $order = $sidx. " ". $sord;
  720. $aData = new stdClass;
  721. //If super admin all the participants will be visible
  722. if (Yii::app()->session['USER_RIGHT_SUPERADMIN'])
  723. {
  724. $iUserID = null;
  725. } else {
  726. $iUserID = Yii::app()->session['loginID'];
  727. }
  728. $aData->records = Participants::model()->getParticipantsCount($attid, $search, $iUserID);
  729. $aData->total = ceil($aData->records / $limit);
  730. if ($page>$aData->total) {
  731. $page = $aData->total;
  732. }
  733. $aData->page = $page;
  734. $records = Participants::model()->getParticipants($page, $limit,$attid, $order, $search, $iUserID);
  735. $aRowToAdd=array();
  736. foreach ($records as $key => $row)
  737. {
  738. if (array_key_exists('can_edit', $row)) {
  739. $sCanEdit = $row['can_edit'];
  740. if (is_null($sCanEdit)) {
  741. $sCanEdit = 'true';
  742. }
  743. } else {
  744. // Super admin
  745. $sCanEdit = "true";
  746. }
  747. if (trim($row['ownername'])=='') {
  748. $row['ownername']=$row['username'];
  749. }
  750. $aRowToAdd['cell'] = array($row['participant_id'], $sCanEdit, $row['firstname'], $row['lastname'], $row['email'], $row['blacklisted'], $row['survey'], $row['language'], $row['ownername']);
  751. $aRowToAdd['id'] = $row['participant_id'];
  752. unset($row['participant_id'], $row['firstname'], $row['lastname'], $row['email'], $row['blacklisted'], $row['language'],$row['ownername'],$row['owner_uid'], $row['can_edit'], $row['survey'], $row['username']);
  753. foreach($row as $key=>$attvalue)
  754. {
  755. $aRowToAdd['cell'][] = $attvalue;
  756. }
  757. $aData->rows[] = $aRowToAdd;
  758. }
  759. echo ls_json_encode($aData);
  760. }
  761. /*
  762. * Fetches the attributes of a participant to be displayed in the attribute subgrid
  763. */
  764. function getAttribute_json()
  765. {
  766. $iParticipantId = Yii::app()->request->getQuery('pid');
  767. $records = ParticipantAttributeNames::model()->getParticipantVisibleAttribute($iParticipantId);
  768. //$getallattributes = ParticipantAttributeNames::model()->with('participant_attribute_names_lang')->findAll();
  769. $records = subval_sort($records, "attribute_name", "asc");
  770. $i = 0;
  771. $doneattributes = array(); //If the user has any actual attribute values, they'll be stored here
  772. /* Iterate through each attribute owned by this user */
  773. foreach ($records as $row)
  774. {
  775. $outputs[$i] = array("", $row['participant_id']."_".$row['attribute_id'], $row['attribute_type'], $row['attribute_id'], $row['attribute_name'], $row['value']);
  776. /* Collect allowed values for a DropDown attribute */
  777. if ($row['attribute_type'] == "DD")
  778. {
  779. $attvalues = ParticipantAttributeNames::model()->getAttributesValues($row['attribute_id']);
  780. if (!empty($attvalues))
  781. {
  782. $attval = "";
  783. foreach ($attvalues as $val)
  784. {
  785. $attval .= $val['value'] . ":" . $val['value'];
  786. $attval .= ";";
  787. }
  788. $attval = substr($attval, 0, -1);
  789. array_push($outputs[$i], $attval);
  790. }
  791. else
  792. {
  793. array_push($outputs[$i], "");
  794. }
  795. }
  796. else
  797. {
  798. array_push($outputs[$i], "");
  799. }
  800. array_push($doneattributes, $row['attribute_id']);
  801. $i++;
  802. }
  803. /* Build a list of attribute names for which this user has NO values stored, keep it in $attributenotdone */
  804. $attributenotdone=array();
  805. /* The user has NO values stored against any attribute */
  806. if (count($doneattributes) == 0)
  807. {
  808. $attributenotdone = ParticipantAttributeNames::model()->getAttributes();
  809. }
  810. /* The user has SOME values stored against attributes */
  811. else
  812. {
  813. $attributenotdone = ParticipantAttributeNames::model()->getnotaddedAttributes($doneattributes);
  814. }
  815. /* Go through the empty attributes and build an entry in the output for them */
  816. foreach ($attributenotdone as $row)
  817. {
  818. $outputs[$i] = array("", $iParticipantId."_".$row['attribute_id'], $row['attribute_type'], $row['attribute_id'], $row['attribute_name'], "");
  819. if ($row['attribute_type'] == "DD")
  820. {
  821. $attvalues = ParticipantAttributeNames::model()->getAttributesValues($row['attribute_id']);
  822. if (!empty($attvalues))
  823. {
  824. $attval = "";
  825. foreach ($attvalues as $val)
  826. {
  827. $attval .= $val['value'] . ":" . $val['value'];
  828. $attval .= ";";
  829. }
  830. $attval = substr($attval, 0, -1);
  831. array_push($outputs[$i], $attval);
  832. }
  833. else
  834. {
  835. array_push($outputs[$i], "");
  836. }
  837. }
  838. else
  839. {
  840. array_push($outputs[$i], "");
  841. }
  842. $i++;
  843. }
  844. $outputs=subval_sort($outputs, 3, "asc");
  845. $aData = new stdClass();
  846. $aData->page = 1;
  847. $aData->rows[0]['id'] = $iParticipantId;
  848. $aData->rows[0]['cell'] = array();
  849. $aData->records = count($outputs);
  850. $aData->total = ceil($aData->records / 10);
  851. foreach($outputs as $key=>$output) {
  852. $aData->rows[$key]['id']=$output[1];
  853. $aData->rows[$key]['cell']=$output;
  854. }
  855. /* TODO: It'd be nice to do a natural sort on the attribute list at some point.
  856. Currently they're returned in order of attributes WITH values, then WITHOUT values
  857. */
  858. echo ls_json_encode($aData);
  859. }
  860. /*
  861. * Gets the data from the form for add participants and pass it to the participants model
  862. */
  863. function storeParticipants()
  864. {
  865. $aData = array('participant_id' => uniqid(),
  866. 'firstname' => Yii::app()->request->getPost('firstname'),
  867. 'lastname' => Yii::app()->request->getPost('lastname'),
  868. 'email' => Yii::app()->request->getPost('email'),
  869. 'language' => Yii::app()->request->getPost('language'),
  870. 'blacklisted' => Yii::app()->request->getPost('blacklisted'),
  871. 'owner_uid' => Yii::app()->request->getPost('owner_uid'));
  872. Participants::model()->insertParticipant($aData);
  873. }
  874. /*
  875. * Responsible for showing the additional attribute for central database
  876. */
  877. function viewAttribute()
  878. {
  879. $iAttributeId = Yii::app()->request->getQuery('aid');
  880. $aData = array(
  881. 'attributes' => ParticipantAttributeNames::model()->getAttribute($iAttributeId),
  882. 'attributenames' => ParticipantAttributeNames::model()->getAttributeNames($iAttributeId),
  883. 'attributevalues' => ParticipantAttributeNames::model()->getAttributesValues($iAttributeId)
  884. );
  885. $this->getController()->_css_admin_includes(Yii::app()->getConfig('adminstyleurl') . 'participants.css');
  886. $this->getController()->_css_admin_includes(Yii::app()->getConfig('adminstyleurl') . 'viewAttribute.css');
  887. $this->_renderWrappedTemplate('participants', array('participantsPanel', 'viewAttribute'), $aData);
  888. }
  889. /*
  890. * Responsible for saving the additional attribute. It iterates through all the new attributes added dynamically
  891. * and iterates through them
  892. */
  893. function saveAttribute()
  894. {
  895. $iAttributeId = Yii::app()->request->getQuery('aid');
  896. $aData = array(
  897. 'attribute_id' => $iAttributeId,
  898. 'attribute_type' => Yii::app()->request->getPost('attribute_type'),
  899. 'visible' => Yii::app()->request->getPost('visible')
  900. );
  901. ParticipantAttributeNames::model()->saveAttribute($aData);
  902. foreach ($_POST as $key => $value)
  903. {
  904. // check for language code in the post variables this is a hack as the only way to check for language data
  905. if (strlen($key) == 2)
  906. {
  907. $langdata = array(
  908. 'attribute_id' => $iAttributeId,
  909. 'attribute_name' => $value,
  910. 'lang' => $key
  911. );
  912. ParticipantAttributeNames::model()->saveAttributeLanguages($langdata);
  913. }
  914. }
  915. if (Yii::app()->request->getPost('langdata'))
  916. {
  917. $langdata = array(
  918. 'attribute_id' => $iAttributeId,
  919. 'attribute_name' => Yii::app()->request->getPost('attname'),
  920. 'lang' => Yii::app()->request->getPost('langdata')
  921. );
  922. ParticipantAttributeNames::model()->saveAttributeLanguages($langdata);
  923. }
  924. /* Create new attribute value */
  925. if (Yii::app()->request->getPost('attribute_value_name_1') || Yii::app()->request->getPost('attribute_value_name_1') == "0")
  926. {
  927. $i = 1;
  928. $attvaluename = 'attribute_value_name_' . $i;
  929. while (array_key_exists($attvaluename, $_POST) && $_POST[$attvaluename] != "")
  930. {
  931. if ($_POST[$attvaluename] != "")
  932. {
  933. $aDatavalues[$i] = array(
  934. 'attribute_id' => $iAttributeId,
  935. 'value' => Yii::app()->request->getPost($attvaluename)
  936. );
  937. }
  938. $attvaluename = 'attribute_value_name_' . ++$i;
  939. };
  940. ParticipantAttributeNames::model()->storeAttributeValues($aDatavalues);
  941. }
  942. /* Save updated attribute values */
  943. if (Yii::app()->request->getPost('editbox') || Yii::app()->request->getPost('editbox')=="0")
  944. {
  945. $editattvalue = array(
  946. 'attribute_id' => $iAttributeId,
  947. 'value_id' => Yii::app()->request->getPost('value_id'),
  948. 'value' => Yii::app()->request->getPost('editbox')
  949. );
  950. ParticipantAttributeNames::model()->saveAttributeValue($editattvalue);
  951. }
  952. Yii::app()->getController()->redirect(Yii::app()->getController()->createUrl('admin/participants/sa/attributeControl'));
  953. }
  954. /*
  955. * Responsible for deleting the additional attribute values in case of drop down.
  956. */
  957. function delAttributeValues()
  958. {
  959. $iAttributeId = Yii::app()->request->getQuery('aid');
  960. $iValueId = Yii::app()->request->getQuery('vid');
  961. ParticipantAttributeNames::model()->delAttributeValues($iAttributeId, $iValueId);
  962. Yii::app()->getController()->redirect(Yii::app()->getController()->createUrl('/admin/participants/sa/viewAttribute/aid/' . $iAttributeId));
  963. }
  964. /*
  965. * Responsible for editing the additional attributes values
  966. */
  967. function editAttributevalue()
  968. {
  969. if (Yii::app()->request->getPost('oper') == "edit" && (Yii::app()->request->getPost('attvalue') || Yii::app()->request->getPost('attvalue')=="0"))
  970. {
  971. $pid = explode('_',Yii::app()->request->getPost('participant_id'));
  972. $iAttributeId = Yii::app()->request->getPost('attid');
  973. $aData = array('participant_id' => $pid[0], 'attribute_id' => $iAttributeId, 'value' => Yii::app()->request->getPost('attvalue'));
  974. ParticipantAttributeNames::model()->editParticipantAttributeValue($aData);
  975. }
  976. }
  977. function attributeMapCSV()
  978. {
  979. $clang = $this->getController()->lang;
  980. $sRandomFileName=randomChars(20);
  981. $sFilePath = Yii::app()->getConfig('tempdir') . DIRECTORY_SEPARATOR . $sRandomFileName;
  982. $aPathinfo = pathinfo($_FILES['the_file']['name']);
  983. $sExtension = $pathinfo['extension'];
  984. if (strtolower($sExtension)=='csv')
  985. {
  986. $bMoveFileResult = @move_uploaded_file($_FILES['the_file']['tmp_name'], $sFilePath);
  987. $errorinupload = '';
  988. $filterblankemails = Yii::app()->request->getPost('filterbea');
  989. }
  990. else
  991. {
  992. $templateData['error_msg'] = sprintf($clang->gT("This is not a .csv file."), Yii::app()->getConfig('tempdir'));
  993. $errorinupload = array('error' => $this->upload->display_errors());
  994. Yii::app()->session['summary'] = array('errorinupload' => $errorinupload);
  995. $this->_renderWrappedTemplate('participants', array('participantsPanel', 'uploadSummary'));
  996. }
  997. if (!$bMoveFileResult)
  998. {
  999. $templateData['error_msg'] = sprintf($clang->gT("An error occurred uploading your file. This may be caused by incorrect permissions in your %s folder."), Yii::app()->getConfig('tempdir'));
  1000. $errorinupload = array('error' => $this->upload->display_errors());
  1001. Yii::app()->session['summary'] = array('errorinupload' => $errorinupload);
  1002. $this->_renderWrappedTemplate('participants', array('participantsPanel', 'uploadSummary'));
  1003. }
  1004. else
  1005. {
  1006. $aData = array('upload_data' => $_FILES['the_file']);
  1007. $sFileName = $_FILES['the_file']['name'];
  1008. $regularfields = array('firstname', 'participant_id', 'lastname', 'email', 'language', 'blacklisted', 'owner_uid');
  1009. $csvread = fopen($sFilePath, 'r');
  1010. $seperator = Yii::app()->request->getPost('seperatorused');
  1011. $firstline = fgetcsv($csvread, 1000, ',');
  1012. $selectedcsvfields = array();
  1013. foreach ($firstline as $key => $value)
  1014. {
  1015. $testvalue = preg_replace('/[^(\x20-\x7F)]*/','', $value); //Remove invalid characters from string
  1016. if (!in_array(strtolower($testvalue), $regularfields))
  1017. {
  1018. array_push($selectedcsvfields, $value);
  1019. }
  1020. $fieldlist[]=$value;
  1021. }
  1022. $linecount = count(file($sFilePath));
  1023. $attributes = ParticipantAttributeNames::model()->model()->getAttributes();
  1024. $aData = array(
  1025. 'attributes' => $attributes,
  1026. 'firstline' => $selectedcsvfields,
  1027. 'fullfilepath' => $sRandomFileName,
  1028. 'linecount' => $linecount - 1,
  1029. 'filterbea' => $filterblankemails,
  1030. 'participant_id_exists' => in_array('participant_id', $fieldlist)
  1031. );
  1032. $this->_renderWrappedTemplate('participants', 'attributeMapCSV', $aData);
  1033. }
  1034. }
  1035. /*
  1036. * Uploads the file to the server and process it for valid enteries and import them into database
  1037. */
  1038. function uploadCSV()
  1039. {
  1040. unset(Yii::app()->session['summary']);
  1041. $characterset = Yii::app()->request->getPost('characterset');
  1042. $seperator = Yii::app()->request->getPost('seperatorused');
  1043. $newarray = Yii::app()->request->getPost('newarray');
  1044. $mappedarray = Yii::app()->request->getPost('mappedarray');
  1045. $filterblankemails = Yii::app()->request->getPost('filterbea');
  1046. $overwrite = Yii::app()->request->getPost('overwrite');
  1047. $sFilePath = Yii::app()->getConfig('tempdir') . '/' . basename(Yii::app()->request->getPost('fullfilepath'));
  1048. $errorinupload = "";
  1049. $recordcount = 0;
  1050. $mandatory = 0;
  1051. $mincriteria = 0;
  1052. $imported = 0;
  1053. $dupcount = 0;
  1054. $overwritten = 0;
  1055. $dupreason="nameemail"; //Default duplicate comparison method
  1056. $duplicatelist = array();
  1057. $invalidemaillist = array();
  1058. $invalidformatlist = array();
  1059. $invalidattribute = array();
  1060. $invalidparticipantid = array();
  1061. /* Adjust system settings to read file with MAC line endings */
  1062. @ini_set('auto_detect_line_endings', true);
  1063. /* Open the uploaded file into an array */
  1064. $tokenlistarray = file($sFilePath);
  1065. // open it and trim the endings
  1066. $separator = Yii::app()->request->getPost('seperatorused');
  1067. $uploadcharset = Yii::app()->request->getPost('characterset');
  1068. /* The $newarray contains a list of fields that will be used
  1069. to create new attributes */
  1070. if (!empty($newarray))
  1071. {
  1072. /* Create a new entry in the lime_participant_attribute_names table,
  1073. and it's associated lime_participant_attribute_names_lang table
  1074. for each NEW attribute being created in this import process */
  1075. foreach ($newarray as $key => $value)
  1076. {
  1077. $aData = array('attribute_type' => 'TB', 'attribute_name' => $value, 'visible' => 'FALSE');
  1078. $insertid = ParticipantAttributeNames::model()->storeAttributeCSV($aData);
  1079. /* Keep a record of the attribute_id for this new attribute
  1080. in the $mappedarray string. For example, if the new attribute
  1081. has attribute_id of 35 and is called "gender",
  1082. $mappedarray['35']='gender' */
  1083. $mappedarray[$insertid] = $value;
  1084. }
  1085. }
  1086. if (!isset($uploadcharset))
  1087. {
  1088. $uploadcharset = 'auto';
  1089. }
  1090. foreach ($tokenlistarray as $buffer) //Iterate through the CSV file line by line
  1091. {
  1092. $buffer = @mb_convert_encoding($buffer, "UTF-8", $uploadcharset);
  1093. $firstname = "";
  1094. $lastname = "";
  1095. $email = "";
  1096. $language = "";
  1097. if ($recordcount == 0) {
  1098. //The first time we iterate through the file we look at the very
  1099. //first line, which contains field names, not values to import
  1100. // Pick apart the first line
  1101. $buffer = removeBOM($buffer);
  1102. $attrid = ParticipantAttributeNames::model()->getAttributeID();
  1103. $allowedfieldnames = array('participant_id', 'firstname', 'lastname', 'email', 'language', 'blacklisted');
  1104. if (!empty($mappedarray))
  1105. {
  1106. foreach ($mappedarray as $key => $value)
  1107. {
  1108. array_push($allowedfieldnames, strtolower($value));
  1109. }
  1110. }
  1111. //For Attributes
  1112. switch ($separator)
  1113. {
  1114. case 'comma':
  1115. $separator = ',';
  1116. break;
  1117. case 'semicolon':
  1118. $separator = ';';
  1119. break;
  1120. default:
  1121. $comma = substr_count($buffer, ',');
  1122. $semicolon = substr_count($buffer, ';');
  1123. if ($semicolon > $comma)
  1124. $separator = ';'; else
  1125. $separator = ',';
  1126. }
  1127. $firstline = convertCSVRowToArray($buffer, $separator, '"');
  1128. $firstline = array_map('trim', $firstline);
  1129. $ignoredcolumns = array();
  1130. //now check the first line for invalid fields
  1131. foreach ($firstline as $index => $fieldname)
  1132. {
  1133. $firstline[$index] = preg_replace("/(.*) <[^,]*>$/", "$1", $fieldname);
  1134. $fieldname = $firstline[$index];
  1135. if (!in_array(strtolower($fieldname), $allowedfieldnames) && !in_array($fieldname,$mappedarray))
  1136. {
  1137. $ignoredcolumns[] = $fieldname;
  1138. } else {
  1139. $firstline[$index] = strtolower($fieldname);
  1140. }
  1141. }
  1142. if ((!in_array('firstname', $firstline) && !in_array('lastname', $firstline) && !in_array('email', $firstline)) && !in_array('participant_id', $firstline))
  1143. {
  1144. $recordcount = count($tokenlistarray);
  1145. break;
  1146. }
  1147. } else {
  1148. // After looking at the first line, we now import the actual values
  1149. $line = convertCSVRowToArray($buffer, $separator, '"');
  1150. if (count($firstline) != count($line))
  1151. {
  1152. $invalidformatlist[] = $recordcount;
  1153. continue;
  1154. }
  1155. $writearray = array_combine($firstline, $line);
  1156. //kick out ignored columns
  1157. foreach ($ignoredcolumns as $column)
  1158. {
  1159. unset($writearray[$column]);
  1160. }
  1161. $invalidemail = false;
  1162. $dupfound = false;
  1163. $thisduplicate = 0;
  1164. $filterduplicatefields = array('firstname', 'lastname', 'email');
  1165. //Check for duplicate participants
  1166. $aData = array(
  1167. 'firstname' => $writearray['firstname'],
  1168. 'lastname' => $writearray['lastname'],
  1169. 'email' => $writearray['email'],
  1170. 'owner_uid' => Yii::app()->session['loginID']
  1171. );
  1172. //HACK - converting into SQL instead of doing an array search
  1173. if(in_array('participant_id', $firstline)) {
  1174. $dupreason="participant_id";
  1175. $aData = "participant_id = ".Yii::app()->db->quoteValue($writearray['participant_id']);
  1176. } else {
  1177. $dupreason="nameemail";
  1178. $aData = "firstname = ".Yii::app()->db->quoteValue($writearray['firstname'])." AND lastname = ".Yii::app()->db->quoteValue($writearray['lastname'])." AND email = ".Yii::app()->db->quoteValue($writearray['email'])." AND owner_uid = '".Yii::app()->session['loginID']."'";
  1179. }
  1180. //End of HACK
  1181. $aData = Participants::model()->checkforDuplicate($aData, "participant_id");
  1182. if ($aData !== false) {
  1183. $thisduplicate = 1;
  1184. $dupcount++;
  1185. if($overwrite=="true")
  1186. {
  1187. //Although this person already exists, we want to update the mapped attribute values
  1188. if (!empty($mappedarray)) {
  1189. //The mapped array contains the attributes we are
  1190. //saving in this import
  1191. foreach ($mappedarray as $attid => $attname) {
  1192. if (!empty($attname)) {
  1193. $bData = array('participant_id' => $aData,
  1194. 'attribute_id' => $attid,
  1195. 'value' => $writearray[$attname]);
  1196. Participant_attribute::model()->updateParticipantAttributeValue($bData);
  1197. } else {
  1198. //If the value is empty, don't write the value
  1199. }
  1200. }
  1201. $overwritten++;
  1202. }
  1203. }
  1204. }
  1205. if ($thisduplicate == 1) {
  1206. $dupfound = true;
  1207. $duplicatelist[] = $writearray['firstname'] . " " . $writearray['lastname'] . " (" . $writearray['email'] . ")";
  1208. }
  1209. //Checking the email address is in a valid format
  1210. $invalidemail = false;
  1211. $writearray['email'] = trim($writearray['email']);
  1212. if ($writearray['email'] != '') {
  1213. $aEmailAddresses = explode(';', $writearray['email']);
  1214. foreach ($aEmailAddresses as $sEmailaddress) {
  1215. if (!validateEmailAddress($sEmailaddress)) {
  1216. $invalidemail = true;
  1217. $invalidemaillist[] = $line[0] . " " . $line[1] . " (" . $line[2] . ")";
  1218. }
  1219. }
  1220. }
  1221. if (!$dupfound && !$invalidemail) {
  1222. //If it isn't a duplicate value or an invalid email, process the entry as a new participant
  1223. //First, process the known fields
  1224. if (!isset($writearray['participant_id']) || $writearray['participant_id'] == "") {
  1225. $uuid = $this->gen_uuid(); //Generate a UUID for the new participant
  1226. $writearray['participant_id'] = $uuid;
  1227. }
  1228. if (isset($writearray['emailstatus']) && trim($writearray['emailstatus'] == '')) {
  1229. unset($writearray['emailstatus']);
  1230. }
  1231. if (!isset($writearray['language']) || $writearray['language'] == "") {
  1232. $writearray['language'] = "en";
  1233. }
  1234. if (!isset($writearray['blacklisted']) || $writearray['blacklisted'] == "") {
  1235. $writearray['blacklisted'] = "N";
  1236. }
  1237. $writearray['owner_uid'] = Yii::app()->session['loginID'];
  1238. if (isset($writearray['validfrom']) && trim($writearray['validfrom'] == '')) {
  1239. unset($writearray['validfrom']);
  1240. }
  1241. if (isset($writearray['validuntil']) && trim($writearray['validuntil'] == '')) {
  1242. unset($writearray['validuntil']);
  1243. }
  1244. $dontimport=false;
  1245. if (($filterblankemails == "accept" && $writearray['email'] == "") || $writearray['firstname'] == "" || $writearray['lastname'] == "") {
  1246. //The mandatory fields of email, firstname and lastname
  1247. //must be filled, but one or more are empty
  1248. $mandatory++;
  1249. $dontimport=true;
  1250. } else {
  1251. foreach ($writearray as $key => $value) {
  1252. if (!empty($mappedarray)) {
  1253. //The mapped array contains the attributes we are
  1254. //saving in this import
  1255. if (in_array($key, $allowedfieldnames)) {
  1256. foreach ($mappedarray as $attid => $attname) {
  1257. if (strtolower($attname) == $key) {
  1258. if (!empty($value)) {
  1259. $aData = array('participant_id' => $writearray['participant_id'],
  1260. 'attribute_id' => $attid,
  1261. 'value' => $value);
  1262. ParticipantAttributeNames::model()->saveParticipantAttributeValue($aData);
  1263. } else {
  1264. //If the value is empty, don't write the value
  1265. }
  1266. }
  1267. }
  1268. }
  1269. }
  1270. }
  1271. }
  1272. //If any of the mandatory fields are blank, then don't import this user
  1273. if(!$dontimport)
  1274. {
  1275. Participants::model()->insertParticipantCSV($writearray);
  1276. $imported++;
  1277. }
  1278. }
  1279. $mincriteria++;
  1280. }
  1281. $recordcount++;
  1282. }
  1283. unlink($sFilePath);
  1284. $clang = $this->getController()->lang;
  1285. $aData = array();
  1286. $aData['clang'] = $clang;
  1287. $aData['recordcount'] = $recordcount - 1;
  1288. $aData['duplicatelist'] = $duplicatelist;
  1289. $aData['mincriteria'] = $mincriteria;
  1290. $aData['imported'] = $imported;
  1291. $aData['errorinupload'] = $errorinupload;
  1292. $aData['invalidemaillist'] = $invalidemaillist;
  1293. $aData['mandatory'] = $mandatory;
  1294. $aData['invalidattribute'] = $invalidattribute;
  1295. $aData['mandatory'] = $mandatory;
  1296. $aData['invalidparticipantid'] = $invalidparticipantid;
  1297. $aData['overwritten'] = $overwritten;
  1298. $aData['dupreason'] = $dupreason;
  1299. $this->getController()->render('/admin/participants/uploadSummary_view', $aData);
  1300. }
  1301. function summaryview()
  1302. {
  1303. $this->_renderWrappedTemplate('participants', array('participantsPanel', 'uploadSummary'));
  1304. }
  1305. /*
  1306. * Responsible for setting the session variables for attribute map page redirect
  1307. */
  1308. function setSession()
  1309. {
  1310. unset(Yii::app()->session['participantid']);
  1311. Yii::app()->session['participantid'] = Yii::app()->request->getPost('participantid');
  1312. }
  1313. /*
  1314. * Generation of unique id
  1315. */
  1316. function gen_uuid()
  1317. {
  1318. return sprintf(
  1319. '%04x%04x-%04x-%04x-%04x-%04x%04x%04x',
  1320. mt_rand(0, 0xffff),
  1321. mt_rand(0, 0xffff),
  1322. mt_rand(0, 0xffff),
  1323. mt_rand(0, 0x0fff) | 0x4000,
  1324. mt_rand(0, 0x3fff) | 0x8000,
  1325. mt_rand(0, 0xffff),
  1326. mt_rand(0, 0xffff),
  1327. mt_rand(0, 0xffff)
  1328. );
  1329. }
  1330. /*
  1331. * Stores the shared participant information in participant_shares
  1332. */
  1333. function shareParticipants()
  1334. {
  1335. $clang = $this->getController()->lang;
  1336. $iParticipantId = Yii::app()->request->getPost('participantid');
  1337. $iShareUserId = Yii::app()->request->getPost('shareuser');
  1338. $bCanEdit = Yii::app()->request->getPost('can_edit');
  1339. $i = 0;
  1340. foreach ($iParticipantId as $iId)
  1341. {
  1342. $time = time();
  1343. $aData = array('participant_id' => $iId,
  1344. 'share_uid' => $iShareUserId,
  1345. 'date_added' => date('Y-m-d H:i:s', $time),
  1346. 'can_edit' => $bCanEdit);
  1347. ParticipantShares::model()->storeParticipantShare($aData);
  1348. $i++;
  1349. }
  1350. printf($clang->gT("%s participants have been shared"), $i);
  1351. }
  1352. /*
  1353. * Responsible for copying the participant from tokens to the central Database
  1354. *
  1355. * TODO: Most of the work for this function is in the participants model file
  1356. * but it doesn't belong there.
  1357. */
  1358. function addToCentral()
  1359. {
  1360. $newarr = Yii::app()->request->getPost('newarr');
  1361. $mapped = Yii::app()->request->getPost('mapped');
  1362. $overwriteauto = Yii::app()->request->getPost('overwriteauto');
  1363. $overwriteman = Yii::app()->request->getPost('overwriteman');
  1364. $createautomap = Yii::app()->request->getPost('createautomap');
  1365. $response = Participants::model()->copyToCentral(Yii::app()->request->getPost('surveyid'), $newarr, $mapped, $overwriteauto, $overwriteman, $createautomap);
  1366. $clang = $this->getController()->lang;
  1367. printf($clang->gT("%s participants have been copied to the central participants table"), $response['success']);
  1368. if($response['duplicate'] > 0) {
  1369. echo "\r\n";
  1370. printf($clang->gT("%s entries were not copied because they already existed"), $response['duplicate']);
  1371. }
  1372. if($response['overwriteman']=="true" || $response['overwriteauto']) {
  1373. echo "\r\n";
  1374. $clang->eT("Attribute values for existing participants have been updated from the token records");
  1375. }
  1376. }
  1377. /*
  1378. * Responsible for adding the participant to the specified survey
  1379. */
  1380. function addToToken()
  1381. {
  1382. $response = Participants::model()->copytoSurvey(Yii::app()->request
  1383. ->getPost('participantid'),
  1384. Yii::app()->request
  1385. ->getPost('surveyid'), Yii::app()
  1386. ->request->getPost('attributeid')
  1387. );
  1388. $clang = $this->getController()->lang;
  1389. printf($clang->gT("%s participants have been copied to the survey token table"), $response['success']);
  1390. if($response['duplicate']>0) {
  1391. echo "\r\n";
  1392. printf($clang->gT("%s entries were not copied because they already existed"), $response['duplicate']);
  1393. }
  1394. if($response['overwrite']=="true") {
  1395. echo "\r\n";
  1396. $clang->eT("Attribute values for existing participants have been updated from the participants records");
  1397. }
  1398. }
  1399. /*
  1400. * Responsible for adding the participant to the specified survey with attribute mapping
  1401. */
  1402. function addToTokenattmap()
  1403. {
  1404. $iParticipantId = Yii::app()->request->getPost('participant_id');
  1405. $iSurveyId = Yii::app()->request->getPost('surveyid');
  1406. $mapped = Yii::app()->request->getPost('mapped');
  1407. $newcreate = Yii::app()->request->getPost('newarr');
  1408. $overwriteauto = Yii::app()->request->getPost('overwrite');
  1409. $overwriteman = Yii::app()->request->getPost('overwriteman');
  1410. $overwritest = Yii::app()->request->getPost('overwritest');
  1411. $createautomap = Yii::app()->request->getPost('createautomap');
  1412. $clang = $this->getController()->lang;
  1413. if (empty($newcreate[0])) { $newcreate = array(); }
  1414. $response = Participants::model()->copytosurveyatt($iSurveyId, $mapped, $newcreate, $iParticipantId, $overwriteauto, $overwriteman, $overwritest, $createautomap);
  1415. printf($clang->gT("%s participants have been copied to the survey token table"), $response['success']);
  1416. if($response['duplicate']>0) {
  1417. echo "\r\n";
  1418. printf($clang->gT("%s entries were not copied because they already existed"), $response['duplicate']);
  1419. }
  1420. if($response['overwriteauto']=="true" || $response['overwriteman']=="true") {
  1421. echo "\r\n";
  1422. $clang->eT("Attribute values for existing participants have been updated from the participants records");
  1423. }
  1424. }
  1425. /*
  1426. * Responsible for attribute mapping while copying participants from cpdb to token's table
  1427. */
  1428. function attributeMap()
  1429. {
  1430. Yii::app()->loadHelper('common');
  1431. $this->getController()->_js_admin_includes(Yii::app()->getConfig('adminscripts') . "attributeMap.js");
  1432. $this->getController()->_css_admin_includes(Yii::app()->getConfig('adminstyleurl') ."attributeMap.css");
  1433. $iSurveyId = Yii::app()->request->getPost('survey_id');
  1434. $redirect = Yii::app()->request->getPost('redirect');
  1435. $count = Yii::app()->request->getPost('count');
  1436. $iParticipantId = Yii::app()->request->getPost('participant_id');
  1437. $attributes = ParticipantAttributeNames::model()->getAttributes();
  1438. $tokenattributefieldnames = getTokenFieldsAndNames($iSurveyId, TRUE);
  1439. /* $arr = Yii::app()->db
  1440. ->createCommand()
  1441. ->select('*')
  1442. ->from("{{tokens_$iSurveyId}}")
  1443. ->queryRow();
  1444. if (is_array($arr))
  1445. {
  1446. $tokenfieldnames = array_keys($arr);
  1447. $tokenattributefieldnames = array_filter($tokenfieldnames, 'filterForAttributes');
  1448. }
  1449. else
  1450. {
  1451. $tokenattributefieldnames = array();
  1452. } */
  1453. $selectedattribute = array(); //List of existing attribute fields that are not mapped
  1454. $selectedcentralattribute = array(); //List of attributes that haven't already been mapped
  1455. $alreadymappedattid = array(); //List of fields already mapped to this tokens table
  1456. $alreadymappedattname = array();
  1457. $i = 0;
  1458. $j = 0;
  1459. foreach ($tokenattributefieldnames as $key => $value)
  1460. {
  1461. if (is_numeric($key[10])) //Assumes that if the 11th character is a number, it must be a token-table created attribute
  1462. {
  1463. $selectedattribute[$key] = $value['description'];
  1464. $i++;
  1465. }
  1466. else
  1467. {
  1468. array_push($alreadymappedattid, substr($key, 15));
  1469. }
  1470. }
  1471. foreach ($attributes as $row)
  1472. {
  1473. if (!in_array($row['attribute_id'], $alreadymappedattid))
  1474. {
  1475. $selectedcentralattribute[$row['attribute_id']] = $row['attribute_name'];
  1476. }
  1477. else
  1478. {
  1479. array_push($alreadymappedattname, $row['attribute_name']);
  1480. }
  1481. }
  1482. $aData = array(
  1483. 'selectedcentralattribute' => $selectedcentralattribute,
  1484. 'selectedtokenattribute' => $selectedattribute,
  1485. 'alreadymappedattributename' => $alreadymappedattname,
  1486. 'survey_id' => $iSurveyId,
  1487. 'redirect' => $redirect,
  1488. 'participant_id' => $iParticipantId,
  1489. 'count' => $count
  1490. );
  1491. $this->_renderWrappedTemplate('participants', 'attributeMap', $aData);
  1492. }
  1493. /*
  1494. * This function is responsible for attribute mapping while copying participants from cpdb to token's table
  1495. */
  1496. function attributeMapToken()
  1497. {
  1498. Yii::app()->loadHelper('common');
  1499. $this->getController()->_js_admin_includes(Yii::app()->getConfig('adminscripts') . "attributeMapToken.js");
  1500. $this->getController()->_css_admin_includes(Yii::app()->getConfig('adminstyleurl') ."attributeMapToken.css");
  1501. $iSurveyId = Yii::app()->request->getQuery('sid');
  1502. $attributes = ParticipantAttributeNames::model()->getAttributes();
  1503. $tokenattributefieldnames = getTokenFieldsAndNames($iSurveyId, TRUE);
  1504. $selectedattribute = array();
  1505. $selectedcentralattribute = array();
  1506. $alreadymappedattid = array();
  1507. $alreadymappedattdisplay = array();
  1508. $alreadymappedattnames = array();
  1509. $i = 0;
  1510. $j = 0;
  1511. foreach ($tokenattributefieldnames as $key => $value)
  1512. {
  1513. if (is_numeric($key[10]))
  1514. {
  1515. $selectedattribute[$value['description']] = $key;
  1516. }
  1517. else
  1518. {
  1519. $attributeid=substr($key,15);
  1520. $continue=false;
  1521. foreach($attributes as $attribute) {
  1522. if($attribute['attribute_id']==$attributeid) {
  1523. $continue=true;
  1524. }
  1525. }
  1526. if($continue) {
  1527. array_push($alreadymappedattid, $attributeid);
  1528. array_push($alreadymappedattdisplay, $key);
  1529. $alreadymappedattnames[$key]=$value['description'];
  1530. } else {
  1531. $selectedattribute[$value['description']]=$key;
  1532. }
  1533. }
  1534. }
  1535. foreach ($attributes as $row)
  1536. {
  1537. if (!in_array($row['attribute_id'], $alreadymappedattid))
  1538. {
  1539. $selectedcentralattribute[$row['attribute_id']] = $row['attribute_name'];
  1540. }
  1541. }
  1542. $aData = array(
  1543. 'attribute' => $selectedcentralattribute,
  1544. 'tokenattribute' => $selectedattribute,
  1545. 'alreadymappedattributename' => $alreadymappedattdisplay,
  1546. 'alreadymappedattdescription' => $alreadymappedattnames
  1547. );
  1548. $this->_renderWrappedTemplate('participants', 'attributeMapToken', $aData);
  1549. }
  1550. /**
  1551. * This function deletes the uploaded csv file if the import is cancelled
  1552. *
  1553. */
  1554. function mapCSVcancelled()
  1555. {
  1556. unlink(Yii::app()->getConfig('tempdir') . '/' . basename(Yii::app()->request->getPost('fullfilepath')));
  1557. }
  1558. function blacklistParticipant()
  1559. {
  1560. $this->load->model('participants_model');
  1561. $iParticipantId = $this->uri->segment(4);
  1562. $iSurveyId = $this->uri->segment(5);
  1563. $clang = $this->limesurvey_lang;
  1564. if (!is_numeric($iSurveyId))
  1565. {
  1566. $blacklist = $this->uri->segment(5);
  1567. if ($blacklist == 'Y' || $blacklist == 'N')
  1568. {
  1569. $aData = array('blacklisted' => $blacklist, 'participant_id' => $iParticipantId);
  1570. $aData = $this->participants_model->blacklistparticipantglobal($aData);
  1571. $aData['global'] = 1;
  1572. $aData['clang'] = $clang;
  1573. $aData['blacklist'] = $blacklist;
  1574. $this->load->view('admin/participants/blacklist_view', $aData);
  1575. }
  1576. else
  1577. {
  1578. $aData['is_participant'] = 0;
  1579. $aData['is_updated'] = 0;
  1580. $aData['clang'] = $clang;
  1581. $this->load->view('admin/participants/blacklist_view', $aData);
  1582. }
  1583. }
  1584. else
  1585. {
  1586. $blacklist = $this->uri->segment(6);
  1587. if ($blacklist == 'Y' || $blacklist == 'N')
  1588. {
  1589. $aData = array('blacklisted' => $blacklist);
  1590. $aData = $this->participants_model->blacklistparticipantlocal($aData, $iSurveyId, $iParticipantId);
  1591. $aData['global'] = 1;
  1592. $aData['clang'] = $clang;
  1593. $aData['local'] = 1;
  1594. $aData['blacklist'] = $blacklist;
  1595. $this->load->view('admin/participants/blacklist_view', $aData);
  1596. }
  1597. else
  1598. {
  1599. $aData['is_participant'] = 0;
  1600. $aData['is_updated'] = 0;
  1601. $aData['clang'] = $clang;
  1602. $this->load->view('admin/participants/blacklist_view', $aData);
  1603. }
  1604. }
  1605. }
  1606. }
  1607. ?>