user_import.admin.inc 36 KB

12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576777879808182838485868788899091929394959697989910010110210310410510610710810911011111211311411511611711811912012112212312412512612712812913013113213313413513613713813914014114214314414514614714814915015115215315415515615715815916016116216316416516616716816917017117217317417517617717817918018118218318418518618718818919019119219319419519619719819920020120220320420520620720820921021121221321421521621721821922022122222322422522622722822923023123223323423523623723823924024124224324424524624724824925025125225325425525625725825926026126226326426526626726826927027127227327427527627727827928028128228328428528628728828929029129229329429529629729829930030130230330430530630730830931031131231331431531631731831932032132232332432532632732832933033133233333433533633733833934034134234334434534634734834935035135235335435535635735835936036136236336436536636736836937037137237337437537637737837938038138238338438538638738838939039139239339439539639739839940040140240340440540640740840941041141241341441541641741841942042142242342442542642742842943043143243343443543643743843944044144244344444544644744844945045145245345445545645745845946046146246346446546646746846947047147247347447547647747847948048148248348448548648748848949049149249349449549649749849950050150250350450550650750850951051151251351451551651751851952052152252352452552652752852953053153253353453553653753853954054154254354454554654754854955055155255355455555655755855956056156256356456556656756856957057157257357457557657757857958058158258358458558658758858959059159259359459559659759859960060160260360460560660760860961061161261361461561661761861962062162262362462562662762862963063163263363463563663763863964064164264364464564664764864965065165265365465565665765865966066166266366466566666766866967067167267367467567667767867968068168268368468568668768868969069169269369469569669769869970070170270370470570670770870971071171271371471571671771871972072172272372472572672772872973073173273373473573673773873974074174274374474574674774874975075175275375475575675775875976076176276376476576676776876977077177277377477577677777877978078178278378478578678778878979079179279379479579679779879980080180280380480580680780880981081181281381481581681781881982082182282382482582682782882983083183283383483583683783883984084184284384484584684784884985085185285385485585685785885986086186286386486586686786886987087187287387487587687787887988088188288388488588688788888989089189289389489589689789889990090190290390490590690790890991091191291391491591691791891992092192292392492592692792892993093193293393493593693793893994094194294394494594694794894995095195295395495595695795895996096196296396496596696796896997097197297397497597697797897998098198298398498598698798898999099199299399499599699799899910001001100210031004100510061007100810091010101110121013101410151016101710181019102010211022102310241025102610271028102910301031103210331034103510361037103810391040104110421043104410451046104710481049105010511052105310541055105610571058105910601061106210631064106510661067106810691070107110721073107410751076107710781079108010811082108310841085108610871088108910901091109210931094109510961097109810991100110111021103110411051106110711081109111011111112111311141115111611171118111911201121112211231124112511261127112811291130113111321133113411351136113711381139114011411142114311441145114611471148114911501151
  1. <?php
  2. /**
  3. * @file
  4. * Provide administration configuration pages to import users.
  5. */
  6. function user_import_confirm_delete($form, &$form_state, $import_id) {
  7. $form['import_id'] = array(
  8. '#type' => 'value',
  9. '#value' => $import_id,
  10. );
  11. return confirm_form($form,
  12. t('Are you sure you want to delete the user import process?'),
  13. 'admin/people/user_import',
  14. t('Deleting a user import process will also delete the file from which user data was being read. This action cannot be undone.'),
  15. t('Delete'), t('Cancel'));
  16. }
  17. function user_import_confirm_delete_submit($form, &$form_state) {
  18. if ($form_state['values']['confirm']) {
  19. user_import_delete($form_state['values']['import_id']);
  20. }
  21. }
  22. function user_import_list($action = NULL, $import_id = NULL) {
  23. // clear incomplete imports
  24. _user_import_incomplete_deletion();
  25. if (!empty($import_id) && is_numeric($import_id)) {
  26. $pager_id = 1;
  27. $limit = 10;
  28. $rows = array();
  29. $import = _user_import_settings_select($import_id);
  30. $total = db_query('SELECT count(data) FROM {user_import_errors} WHERE import_id = :import_id', array(':import_id' => $import_id))->fetchField();
  31. // Select table
  32. $query = db_select('user_import_errors', 'imp_usr_errors');
  33. // Select fields
  34. $query->fields('imp_usr_errors', array('import_id', 'data', 'errors'));
  35. // Set conditions.
  36. $query->condition('import_id', $import['import_id']);
  37. // For pagination
  38. $query = $query->extend('TableSort')->extend('PagerDefault')->limit($limit);
  39. // Execute query
  40. $result = $query->execute();
  41. foreach ($result as $line) {
  42. $rows[] = array('import_id' => $line->import_id, 'data' => unserialize($line->data), 'errors' => unserialize($line->errors));
  43. }
  44. $output = theme('user_import_errors_display', array('import' => $import, 'file_lines' => $rows, 'total' => $total));
  45. }
  46. else {
  47. $output = theme('user_import_list');
  48. }
  49. return $output;
  50. }
  51. function user_import_preferences($import_id = NULL, $template_id = NULL) {
  52. if (empty($import_id)) {
  53. $private_path = variable_get('file_private_path', FALSE);
  54. // Private path hasn't been set, show a message instead of the form.
  55. if (!$private_path) {
  56. drupal_set_message(t('!path needs to be set before users can be imported.', array('!path' => l('Private file system path', 'admin/config/media/file-system', array('query' => array('destination' => 'admin/people/user_import/add'))))), 'warning');
  57. return ' ';
  58. }
  59. $output = drupal_get_form('user_import_add_form');
  60. }
  61. else {
  62. $output = drupal_get_form('user_import_edit', $import_id, $template_id);
  63. }
  64. return $output;
  65. }
  66. function user_import_confirm_continue($form, &$form_state, $import_id) {
  67. $form['import_id'] = array(
  68. '#type' => 'value',
  69. '#value' => $import_id,
  70. );
  71. return confirm_form($form,
  72. t('Are you sure you want to continue to import users?'),
  73. 'admin/people/user_import',
  74. t('Restart user import from where it last finished.'),
  75. t('Continue'), t('Cancel'));
  76. }
  77. function user_import_confirm_continue_submit($form, &$form_state) {
  78. if ($form_state['values']['confirm']) {
  79. user_import_continue($form_state['values']['import_id']);
  80. }
  81. }
  82. function user_import_continue($import_id = NULL) {
  83. if (!empty($import_id) && is_numeric($import_id)) {
  84. module_load_include('inc', 'user_import', 'user_import.import');
  85. $import = _user_import_settings_select($import_id);
  86. _user_import_process($import);
  87. }
  88. drupal_goto('admin/people/user_import');
  89. }
  90. function user_import_confirm_import($form, &$form_state, $import_id) {
  91. $form['import_id'] = array(
  92. '#type' => 'value',
  93. '#value' => $import_id,
  94. );
  95. return confirm_form($form,
  96. t('Are you sure you want to import users?'),
  97. 'admin/people/user_import',
  98. t('Start importing users.'),
  99. t('Import'), t('Cancel'));
  100. }
  101. function user_import_confirm_import_submit($form, &$form_state) {
  102. if ($form_state['values']['confirm']) {
  103. user_import_import($form_state['values']['import_id']);
  104. }
  105. }
  106. function user_import_import($import_id = NULL) {
  107. if (!empty($import_id) && is_numeric($import_id)) {
  108. $import = _user_import_settings_select($import_id);
  109. _user_import_initialise_import($import);
  110. }
  111. drupal_goto('admin/people/user_import');
  112. }
  113. function user_import_delete($import_id = NULL, $return_path = 'admin/people/user_import') {
  114. if (empty($import_id) || !is_numeric($import_id)) drupal_goto($return_path);
  115. $import = _user_import_settings_select($import_id);
  116. _user_import_settings_deletion($import_id);
  117. //_user_import_file_deletion($import['filepath'], $import['filename'], $import['oldfilename'], $import['ftp']);
  118. file_unmanaged_delete($import['filepath']);
  119. drupal_goto($return_path);
  120. return;
  121. }
  122. /**
  123. * Configuration form define (settings affect all user imports)
  124. */
  125. function user_import_configure_form() {
  126. $form['selectable_files'] = array(
  127. '#type' => 'fieldset',
  128. '#title' => t('Uploads Directory'),
  129. '#collapsible' => TRUE,
  130. '#collapsed' => TRUE,
  131. );
  132. if (variable_get('user_import_selectable_files', 0) == 0) {
  133. $selectable_files_description = t('This option provides a directory where files can be uploaded, and then selected when setting up an import.');
  134. }
  135. else {
  136. $selectable_files_description = t('');
  137. }
  138. $form['selectable_files']['selectable_files'] = array(
  139. '#type' => 'checkbox',
  140. '#title' => t('Enable Uploads Directory'),
  141. '#description' => $selectable_files_description,
  142. '#default_value' => variable_get('user_import_selectable_files', 0),
  143. );
  144. $form['auto_imports'] = array(
  145. '#type' => 'fieldset',
  146. '#title' => t('Automated Imports'),
  147. '#collapsible' => TRUE,
  148. '#collapsed' => TRUE,
  149. );
  150. $form['auto_imports']['auto_imports_enabled'] = array(
  151. '#type' => 'checkbox',
  152. '#title' => t('Enable Automated Imports'),
  153. '#description' => t('Each import template will have the option to create a directory which will be scanned for any files that have been uploaded to it,
  154. and when a file is found it will automatically be used to create new user accounts. Directories are scanned durring !cron runs.', array('!cron' => l(t('cron'), 'admin/config/system/cron'))),
  155. '#default_value' => variable_get('user_import_auto_imports_enabled', 0),
  156. );
  157. $form['performance'] = array(
  158. '#type' => 'fieldset',
  159. '#title' => t('Performance'),
  160. '#collapsible' => TRUE,
  161. '#collapsed' => TRUE,
  162. );
  163. $form['performance']['user_import_max'] = array(
  164. '#type' => 'textfield',
  165. '#title' => t('Maximum Users/Process'),
  166. '#default_value' => variable_get('user_import_max', 250),
  167. '#size' => 10,
  168. '#maxlength' => 10,
  169. '#description' => t('Maximum number of users to import each time the file is processed, useful for controling the rate at which emails are sent out.'),
  170. );
  171. $form['performance']['user_import_line_max'] = array(
  172. '#type' => 'textfield',
  173. '#title' => t('Maximum length of line'),
  174. '#default_value' => variable_get('user_import_line_max', 1000),
  175. '#size' => 10,
  176. '#maxlength' => 10,
  177. '#description' => t('The default is set at 1,000 characters, if a line in your csv is longer than this you should set a higher maximum here. Setting higher maximums will slow down imports.'),
  178. );
  179. if (module_exists('profile')) {
  180. $date_options = array(
  181. 'MM/DD/YYYY' => 'MM/DD/YYYY',
  182. 'DD/MM/YYYY' => 'DD/MM/YYYY',
  183. 'YYYY/MM/DD' => 'YYYY/MM/DD',
  184. 'YYYY/DD/MM' => 'YYYY/DD/MM',
  185. );
  186. $form['profile'] = array(
  187. '#type' => 'fieldset',
  188. '#title' => t('Profile Settings'),
  189. '#collapsible' => TRUE,
  190. '#collapsed' => TRUE,
  191. );
  192. $form['profile']['profile_date_format'] = array(
  193. '#type' => 'select',
  194. '#title' => t('Date field format'),
  195. '#description' => t('Select a format for importing dates into user profiles (Profile module).'),
  196. '#default_value' => variable_get('user_import_profile_date_format', 'MM/DD/YYYY'),
  197. '#options' => $date_options,
  198. );
  199. }
  200. $saved_templates = _user_import_settings_select(NULL, TRUE);
  201. if (!empty($saved_templates)) {
  202. $form['settings_templates'] = array(
  203. '#type' => 'fieldset',
  204. '#title' => t('Settings Templates'),
  205. '#collapsible' => TRUE,
  206. '#collapsed' => TRUE,
  207. );
  208. $templates_list = array('-- none --');
  209. foreach ($saved_templates AS $template) {
  210. $templates_list[$template['import_id']] = $template['name'];
  211. $templates_delete[$template['import_id']] = $template['name'];
  212. }
  213. $form['settings_templates']['user_import_settings'] = array(
  214. '#type' => 'select',
  215. '#title' => t('Default Settings'),
  216. '#description' => t('Select if you want to use a previously saved set of settings as default for all imports.'),
  217. '#default_value' => variable_get('user_import_settings', 0),
  218. '#options' => $templates_list,
  219. );
  220. $form['settings_templates']['templates'] = array(
  221. '#type' => 'checkboxes',
  222. '#title' => t('Delete Templates'),
  223. '#options' => $templates_delete,
  224. );
  225. }
  226. $form['submit'] = array(
  227. '#type' => 'submit',
  228. '#value' => t('Save'),
  229. );
  230. return $form;
  231. }
  232. function user_import_configure_form_validate($form, &$form_state) {
  233. if (is_numeric($form_state['values']['user_import_max'])) {
  234. if ($form_state['values']['user_import_max'] < 10) form_set_error('user_import_max', t("Value should be at least 10."));
  235. }
  236. else {
  237. form_set_error('user_import_max', t('Value must be a number.'));
  238. }
  239. if (is_numeric($form_state['values']['user_import_line_max'])) {
  240. if ($form_state['values']['user_import_line_max'] < 1000) form_set_error('user_import_line_max', t("Value must be higher than 1000."));
  241. if ($form_state['values']['user_import_line_max'] > 1000000) form_set_error('user_import_line_max', t("Value must be lower than 1,000,000."));
  242. }
  243. else {
  244. form_set_error('user_import_line_max', t('Value must be a number.'));
  245. }
  246. // Check private files path is set.
  247. if (!empty($form_state['values']['auto_imports_enabled'])) {
  248. $file_private_path = variable_get('file_private_path', FALSE);
  249. if (!$file_private_path) {
  250. form_set_error('auto_imports_enabled', t('The !private_file_path must be set to use this feature.', array('!private_file_path' => l(t('Private file system path'), 'admin/config/media/file-system'))));
  251. }
  252. }
  253. // Check private files path is set.
  254. if (!empty($form_state['values']['selectable_files'])) {
  255. $file_private_path = variable_get('file_private_path', FALSE);
  256. if (!$file_private_path) {
  257. form_set_error('selectable_files', t('The !private_file_path must be set to use the Uploads Directory feature.', array('!private_file_path' => l(t('Private file system path'), 'admin/config/media/file-system'))));
  258. }
  259. }
  260. return;
  261. }
  262. function user_import_configure_form_submit($form, &$form_state) {
  263. $deleted = '';
  264. settype($form_state['values']['user_import_max'], 'integer');
  265. settype($form_state['values']['user_import_line_max'], 'integer');
  266. variable_set('user_import_max', $form_state['values']['user_import_max']);
  267. variable_set('user_import_line_max', $form_state['values']['user_import_line_max']);
  268. $user_import_settings = isset($form_state['values']['user_import_settings']) ? $form_state['values']['user_import_settings'] : 0;
  269. variable_set('user_import_settings', $user_import_settings);
  270. $profile_date_format = isset($form_state['values']['profile_date_format']) ? $form_state['values']['profile_date_format'] : 0;
  271. variable_set('user_import_profile_date_format', $profile_date_format);
  272. variable_set('user_import_selectable_files', $form_state['values']['selectable_files']);
  273. variable_set('user_import_auto_imports_enabled', $form_state['values']['auto_imports_enabled']);
  274. // Create a directory for processing incoming files if auto imports are enabled.
  275. if (!empty($form_state['values']['auto_imports_enabled'])) {
  276. user_import_create_directory('processing', '');
  277. }
  278. // Create a directory for processing incoming files if auto imports are enabled.
  279. if (!empty($form_state['values']['selectable_files'])) {
  280. user_import_create_directory('selectable');
  281. }
  282. if (!empty($form_state['values']['templates'])) {
  283. foreach ($form_state['values']['templates'] as $import_id) {
  284. if (!empty($import_id)) {
  285. $template = _user_import_settings_select($import_id);
  286. if (!empty($deleted)) $deleted .= ', ';
  287. $deleted .= $template['name'];
  288. _user_import_settings_deletion($import_id);
  289. }
  290. }
  291. }
  292. if (!empty($deleted)) drupal_set_message(t('Settings templates deleted: @deleted', array('@deleted' => $deleted)));
  293. drupal_set_message(t('Configuration settings have been saved.'));
  294. $form_state['redirect'] = 'admin/people/user_import';
  295. }
  296. /**
  297. * Start new import.
  298. * Form to select file.
  299. **/
  300. function user_import_add_form($import_id = NULL) {
  301. $form = array();
  302. $ftp_files = array();
  303. if (variable_get('user_import_selectable_files', 0) == 1) {
  304. $ftp_files = _user_import_ftp_files();
  305. }
  306. user_import_add_file_form($form, $ftp_files);
  307. user_import_delimiter_form($form);
  308. $settings = _user_import_settings_select(NULL, TRUE);
  309. if ($settings) {
  310. $saved_settings = array(t('-- none --'));
  311. foreach ($settings AS $settings_set) {
  312. $saved_settings[$settings_set['import_id']] = $settings_set['name'];
  313. }
  314. $form['import_template_select'] = array(
  315. '#type' => 'select',
  316. '#title' => t('Saved Settings'),
  317. '#description' => t('Select if you want to use a previously saved set of settings.'),
  318. '#default_value' => variable_get('user_import_settings', 0),
  319. '#options' => $saved_settings,
  320. );
  321. }
  322. $form['next'] = array(
  323. '#type' => 'submit',
  324. '#value' => t('Next')
  325. );
  326. // Set form parameters so we can accept file uploads.
  327. $form['#attributes'] = array('enctype' => 'multipart/form-data');
  328. return $form;
  329. }
  330. function user_import_add_form_validate($form, &$form_state) {
  331. if (isset($form_state['values']['file_ftp']) && !empty($form_state['values']['file_ftp'])) {
  332. $file_ftp = $form_state['values']['file_ftp'];
  333. }
  334. else {
  335. $file_ftp = FALSE;
  336. }
  337. $file = _user_import_file(NULL, $file_ftp);
  338. // check file uploaded OK
  339. if (empty($file->filename)) {
  340. form_set_error('file_upload', t('A file must be uploaded or selected from FTP updates.'));
  341. }
  342. else {
  343. $form_state['values']['file_info'] = $file;
  344. }
  345. return;
  346. }
  347. function user_import_add_form_submit($form, &$form_state) {
  348. $redirect = 'admin/people/user_import/add/';
  349. if (isset($form_state['values']['file_ftp']) && !empty($form_state['values']['file_ftp'])) {
  350. $file_ftp = $form_state['values']['file_ftp'];
  351. }
  352. else {
  353. $file_ftp = FALSE;
  354. }
  355. $file = _user_import_file(NULL, $file_ftp);
  356. $file_name = user_import_move_file_for_processing($file->uri, $file->filename);
  357. $form_state['values']['ftp'] = $file_ftp;
  358. $form_state['values']['filename'] = $file_name;
  359. $form_state['values']['oldfilename'] = $file->filename;
  360. $form_state['values']['filepath'] = 'private://user_import/processing/' . $file_name;
  361. $form_state['values']['setting'] = 'file set';
  362. // create import setting
  363. $import = _user_import_settings_save($form_state['values']);
  364. $redirect .= $import['import_id'];
  365. if (!empty($form_state['values']['import_template_select'])) {
  366. $redirect .= '/' . check_plain($form_state['values']['import_template_select']);
  367. }
  368. $form_state['redirect'] = $redirect;
  369. }
  370. function user_import_delimiter_form(&$form, $value = ',') {
  371. $form['file_settings'] = array(
  372. '#type' => 'fieldset',
  373. '#title' => t('File Settings'),
  374. '#collapsible' => TRUE,
  375. '#collapsed' => TRUE,
  376. '#description' => t("File column delimiter"),
  377. );
  378. $form['file_settings']['delimiter'] = array(
  379. '#type' => 'textfield',
  380. '#title' => t('Delimiter'),
  381. '#size' => 4,
  382. '#default_value' => $value,
  383. '#required' => TRUE,
  384. '#description' => t("The column delimiter for the file. Use '/t' for Tab."),
  385. );
  386. }
  387. function user_import_edit($form, $form_state, $import_id, $template_id = NULL) {
  388. // load code for supported modules
  389. user_import_load_supported();
  390. $form = array();
  391. $import = _user_import_settings_select($import_id);
  392. $import['template_id'] = $template_id;
  393. $form['ftp'] = array(
  394. '#type' => 'value',
  395. '#value' => $import['options']['ftp'],
  396. );
  397. // add setting template values
  398. if ($import['setting'] == 'file set') {
  399. $import = _user_import_initialise_import($import);
  400. }
  401. $form['import_id'] = array(
  402. '#type' => 'value',
  403. '#value' => $import_id,
  404. );
  405. $form['setting'] = array(
  406. '#type' => 'value',
  407. '#value' => $import['setting'],
  408. );
  409. $form['return_path'] = array(
  410. '#type' => 'value',
  411. '#default_value' => 'admin/people/user_import',
  412. );
  413. $form['og_id'] = array(
  414. '#type' => 'value',
  415. '#default_value' => 0,
  416. );
  417. // don't use hook because these need to be added in this order;
  418. user_import_edit_file_fields($form, $import);
  419. user_import_form_field_match($form, $import);
  420. $collapsed = (empty($import['name'])) ? FALSE : TRUE;
  421. $additional_fieldsets = module_invoke_all('user_import_form_fieldset', $import, $collapsed);
  422. if (is_array($additional_fieldsets)) $form = $form + $additional_fieldsets;
  423. $update_user = module_invoke_all('user_import_form_update_user');
  424. if (is_array($update_user)) {
  425. $form['update_user'] = array(
  426. '#type' => 'fieldset',
  427. '#title' => t('Update Existing Users'),
  428. '#collapsible' => TRUE,
  429. '#collapsed' => TRUE,
  430. '#tree' => TRUE,
  431. );
  432. foreach ($update_user as $module => $display) {
  433. $options = array(UPDATE_NONE => t('No Update'), UPDATE_REPLACE => t('Replace Data'), UPDATE_ADD => t('Add Data'));
  434. if (isset($display['exclude_add']) && $display['exclude_add'] == TRUE) unset($options[UPDATE_ADD]);
  435. if (isset($display['exclude_replace']) && $display['exclude_replace'] == TRUE) unset($options[UPDATE_REPLACE]);
  436. $form['update_user'][$module] = array(
  437. '#type' => 'radios',
  438. '#title' => $display['title'],
  439. '#options' => $options,
  440. '#default_value' => empty($import['options']['update_user'][$module]) ? UPDATE_NONE : $import['options']['update_user'][$module],
  441. '#description' => $display['description'],
  442. );
  443. }
  444. }
  445. // don't show test option if import has started
  446. if ($import['setting'] != 'import' && $import['setting'] != 'imported') {
  447. $form['test'] = array(
  448. '#type' => 'submit',
  449. '#value' => t('Test'),
  450. '#weight' => 100,
  451. '#submit' => array('user_import_test_submit', 'user_import_edit_submit'),
  452. );
  453. }
  454. $form['import'] = array(
  455. '#type' => 'submit',
  456. '#value' => t('Import'),
  457. '#weight' => 100,
  458. '#submit' => array('user_import_import_submit', 'user_import_edit_submit'),
  459. );
  460. $form['cancel'] = array(
  461. '#type' => 'submit',
  462. '#value' => t('Cancel'),
  463. '#weight' => 100,
  464. '#validate' => array('user_import_edit_cancel_validate'),
  465. );
  466. return $form;
  467. }
  468. function user_import_edit_cancel_validate($form, &$form_state) {
  469. // if import was being added - delete file
  470. if ($form_state['values']['setting'] == 'file set') {
  471. $settings = _user_import_settings_select($form_state['values']['import_id']);
  472. _user_import_settings_deletion($form_state['values']['import_id']);
  473. // _user_import_file_deletion($settings['filepath'], $settings['filename'], $settings['oldfilename'], $settings['options']['ftp']);
  474. file_unmanaged_delete($settings['filepath']);
  475. }
  476. $form_state['redirect'] = 'admin/people/user_import';
  477. }
  478. function user_import_edit_validate($form, &$form_state) {
  479. $email = FALSE;
  480. $fields = array();
  481. foreach ($form_state['values']['field_match'] as $row => $values) {
  482. // check each field is unique
  483. if ($values['field_match'] != '0' && $values['field_match'] != '-------------' && in_array($values['field_match'], $fields)) {
  484. form_set_error('field_match', t('Database fields can only be matched to one column of the csv file.'));
  485. }
  486. $fields[$values['field_match']] = $values['field_match'];
  487. // check email address has been selected
  488. if ($values['field_match'] == 'user-email') $email = TRUE;
  489. }
  490. if (!$email) form_set_error('email', t('One column of the csv file must be set as the email address.'));
  491. if ($form_state['values']['name']) {
  492. $form_state['values']['name'] = rtrim($form_state['values']['name']);
  493. if (drupal_strlen($form_state['values']['name']) < 1 || drupal_strlen($form_state['values']['name']) > 25) {
  494. form_set_error('name', t('Name of saved settings must be 25 characters or less.'));
  495. }
  496. }
  497. // Check auto uploads directory is not already in use by another template.
  498. if (!empty($form_state['values']['auto_import_directory'])) {
  499. $auto_import_directory = 'private://user_import/uploads/' . $form_state['values']['auto_import_directory'];
  500. if (file_prepare_directory($auto_import_directory, FILE_MODIFY_PERMISSIONS) || $form_state['values']['auto_import_directory'] == 'selectable') {
  501. form_set_error('auto_import_directory', t("Directory '%directory' already exists and can not be used.", array('%directory' => $form_state['values']['auto_import_directory'])));
  502. }
  503. }
  504. return;
  505. }
  506. /**
  507. * Save a new template.
  508. */
  509. function user_import_template_new_submit($form, &$form_state) {
  510. // save settings for import
  511. _user_import_settings_save($form_state['values']);
  512. // save settings for template
  513. $import_id = $form_state['values']['import_id'];
  514. $form_state['values']['setting'] = 'template';
  515. unset($form_state['values']['import_id']);
  516. if (isset($form_state['values']['auto_import_directory']) && !empty($form_state['values']['auto_import_directory'])) {
  517. user_import_create_directory($form_state['values']['auto_import_directory']);
  518. }
  519. _user_import_initialise_import($form_state['values']);
  520. drupal_set_message(t("'%name' was saved as a settings template.", array('%name' => $form_state['values']['name'])));
  521. // reload settings page
  522. $form_state['redirect'] = 'admin/people/user_import/add/' . $import_id;
  523. return;
  524. }
  525. /**
  526. * Update an existing template.
  527. */
  528. function user_import_template_update_submit($form, &$form_state) {
  529. // save settings for import
  530. $import_id = $form_state['values']['import_id'];
  531. _user_import_settings_save($form_state['values']);
  532. // get template details
  533. $template_id = db_query_range("SELECT import_id from {user_import} where setting = 'template' AND name = :name", 0, 1, array(':name' => $form['#current_template']))->fetchField();
  534. // save settings for template
  535. $form_state['values']['setting'] = 'template';
  536. $form_state['values']['import_id'] = $template_id;
  537. $form_state['values']['name'] = $form['#current_template'];
  538. _user_import_initialise_import($form_state['values']);
  539. drupal_set_message(t("'%name' settings template was updated.", array('%name' => $form['#current_template'])));
  540. // reload settings page
  541. $form_state['redirect'] = 'admin/people/user_import/add/' . $import_id;
  542. return;
  543. }
  544. /**
  545. *
  546. */
  547. function user_import_test_submit($form, &$form_state) {
  548. $form_state['values']['setting'] = 'test';
  549. drupal_set_message(t('Tested'));
  550. }
  551. /**
  552. *
  553. */
  554. function user_import_import_submit($form, &$form_state) {
  555. $form_state['values']['setting'] = 'import';
  556. drupal_set_message(t('Imported'));
  557. }
  558. function user_import_move_file_for_processing($source, $file_name) {
  559. // Make sure processing directory exists.
  560. user_import_create_directory(NULL, 'processing');
  561. $destination = 'private://user_import/processing/' . $file_name;
  562. $uri = file_unmanaged_move($source, $destination, FILE_EXISTS_RENAME);
  563. $file_name = substr($uri, 33);
  564. return $file_name;
  565. }
  566. /**
  567. *
  568. */
  569. function user_import_edit_submit($form, &$form_state) {
  570. // Deal with import being canceled.
  571. if ($form_state['clicked_button']['#value'] == t('Cancel')) {
  572. $form_state['redirect'] = 'admin/people/user_import';
  573. return;
  574. }
  575. // Load import functions.
  576. module_load_include('inc', 'user_import', 'user_import.import');
  577. if ($form_state['values']['setting'] == 'file set') {
  578. // $file = new stdClass();
  579. // $file->uri = $form_state['values']['filepath'];
  580. // $file->filename = $form_state['values']['filename'];
  581. //$filepath = file_move($file, file_directory_path() . '/' . $form_state['values']['filename']);
  582. $filepath = user_import_move_file_for_processing($form_state['values']['filepath']);
  583. }
  584. if (!empty($form_state['values']['og_id'])) $form_state['values']['groups'][$form_state['values']['og_id']] = $form_state['values']['og_id'];
  585. $form_state['values']['ftp'] = $form_state['values']['ftp'];
  586. $form_state['values'] = _user_import_settings_save($form_state['values']);
  587. $form_state['values']['save']['update'] = NULL;
  588. $form_state['values']['import_template_id'] = NULL;
  589. $form_state['values']['save']['name'] = NULL;
  590. $form_state['redirect'] = $form_state['values']['return_path'];
  591. _user_import_process($form_state['values']);
  592. }
  593. function user_import_add_file_form(&$form, $ftp_files = NULL) {
  594. $form['browser'] = array(
  595. '#type' => 'fieldset',
  596. '#title' => t('Browser Upload'),
  597. '#collapsible' => TRUE,
  598. '#description' => t("Upload a CSV file."),
  599. );
  600. if (function_exists('file_upload_max_size')) {
  601. $file_size = t('Maximum file size: @size.', array('@size' => format_size(file_upload_max_size())));
  602. }
  603. $form['browser']['file_upload'] = array(
  604. '#type' => 'file',
  605. '#title' => t('CSV File'),
  606. '#size' => 40,
  607. '#description' => check_plain(t('Select the CSV file to be imported.') . ' ' . $file_size),
  608. );
  609. if (!empty($ftp_files)) {
  610. $form['ftp'] = array(
  611. '#type' => 'fieldset',
  612. '#title' => t('FTP Upload'),
  613. '#collapsible' => TRUE,
  614. '#collapsed' => TRUE,
  615. '#description' => t("Any files uploaded to the 'user_import' directory using FTP can be selected for import here. Useful if the import file is too large for upload via the browser."),
  616. );
  617. $form['ftp']['file_ftp'] = array(
  618. '#type' => 'radios',
  619. '#title' => t('Files'),
  620. '#default_value' => '0',
  621. '#options' => $ftp_files,
  622. );
  623. // reload the page to show any files that have been added by FTP
  624. $form['ftp']['scan'] = array(
  625. '#type' => 'submit',
  626. '#value' => t('Check for new files'),
  627. '#validate' => array(),
  628. '#submit' => array(),
  629. );
  630. }
  631. return;
  632. }
  633. function user_import_edit_file_fields(&$form, $import) {
  634. $form['filename'] = array(
  635. '#type' => 'value',
  636. '#value' => $import['filename'],
  637. );
  638. $form['oldfilename'] = array(
  639. '#type' => 'value',
  640. '#value' => $import['oldfilename'],
  641. );
  642. $form['filepath'] = array(
  643. '#type' => 'value',
  644. '#value' => $import['filepath'],
  645. );
  646. return;
  647. }
  648. // - - - - - - - - FILE HANDLING - - - - - - - -
  649. /**
  650. * open file
  651. */
  652. function _user_import_file_open($filepath, $filename) {
  653. ini_set('auto_detect_line_endings', TRUE);
  654. $handle = @fopen($filepath, "r");
  655. if (!$handle) {
  656. form_set_error('file', t("Could not find the csv file '%filename'", array('%filename' => $filename)), 'error');
  657. return t("Please add your file again.");
  658. }
  659. return $handle;
  660. }
  661. /*
  662. * File being used
  663. * $import_id - use file info stored in database
  664. * $ftp_file - chosen from FTP uploaded files
  665. * $uploaded_file - uploaded through browser
  666. */
  667. function _user_import_file($import_id = NULL, $ftp_file_selected = NULL) {
  668. static $file;
  669. if (!empty($file)) return $file;
  670. // File was uploaded through browser.
  671. if (empty($ftp_file_selected) && empty($import_id)) {
  672. // Delete record from database management so we don't have duplicates problems.
  673. db_delete('file_managed')->condition('uri', 'temporary://' . $_FILES['files']['name']['file_upload'])->execute();
  674. $file = file_save_upload('file_upload', array('file_validate_extensions' => array('csv txt')), FALSE, FILE_EXISTS_RENAME);
  675. if (!empty($file)) return $file;
  676. }
  677. // File was uploaded by FTP
  678. if (!empty($ftp_file_selected)) {
  679. $ftp_files = file_scan_directory('private://user_import/uploads/selectable', '/.*$/', array('key' => 'filename'));
  680. $file = $ftp_files[$ftp_file_selected];
  681. $file->filepath = $file->uri;
  682. return $file;
  683. }
  684. // Use file info stored in database
  685. if (!empty($import_id)) {
  686. $import = _user_import_settings_select($import_id);
  687. $file->uri = $import['filepath'];
  688. $file->filepath = $import['filepath'];
  689. $file->oldfilename = $import['oldfilename'];
  690. $file->filename = $import['filename'];
  691. return $file;
  692. }
  693. return;
  694. }
  695. // get info on files uploaded via FTP
  696. function _user_import_ftp_files() {
  697. //$directory = opendir(drupal_get_path('module', 'user_import'));
  698. $files = file_scan_directory('private://user_import/uploads/selectable', '/.*$/');
  699. $filenames[] = t('none');
  700. foreach ($files as $file) {
  701. $filenames[$file->filename] = $file->filename;
  702. }
  703. return $filenames;
  704. }
  705. // delete incomplete import settings, where only the file has been uploaded
  706. function _user_import_incomplete_deletion() {
  707. $result = db_query("SELECT * FROM {user_import} WHERE setting = 'file set'");
  708. foreach ($result as $import) {
  709. $options = unserialize($import->options);
  710. //_user_import_file_deletion($import->filepath, $import->filename, $import->oldfilename, $options['ftp'], FALSE);
  711. file_unmanaged_delete($import->filepath);
  712. _user_import_settings_deletion($import->import_id);
  713. }
  714. return;
  715. }
  716. /**
  717. * Create a directory in the private files directory.
  718. *
  719. **/
  720. function user_import_create_directory($directory_name, $path_prefix = 'uploads/') {
  721. if (!file_stream_wrapper_valid_scheme('private')) {
  722. drupal_set_message(t('Directory %path could not be created as the Private files path has not been set.', array('%path' => $directory_name)), 'warning');
  723. }
  724. $path = 'private://user_import/' . $path_prefix . $directory_name;
  725. $directory_created = file_prepare_directory($path, FILE_CREATE_DIRECTORY);
  726. if ($directory_created) {
  727. file_create_htaccess($path);
  728. }
  729. }
  730. // - - - - - - - - MISC - - - - - - - -
  731. function user_import_form_field_match(&$form, $import) {
  732. $delimiter = isset($import['options']['delimiter']) && !empty($import['options']['delimiter']) ? $import['options']['delimiter'] : ',';
  733. $collapsed = (empty($import['name'])) ? FALSE : TRUE;
  734. $handle = _user_import_file_open($form['filepath']['#value'], $form['filename']['#value']);
  735. $data_row = _user_import_file_row($form['filename']['#value'], $handle, $delimiter);
  736. $fieldmatch_description_parts = array(
  737. '<strong>' . t('Drupal fields') . ':</strong> ' . t("Match columns in CSV file to drupal user fields, leave as '----' to ignore the column."),
  738. '<strong>' . t('Username') . ':</strong> ' . t("If username is selected for multiple fields, the username will be built in the order selected. Otherwise, the username will be randomly generated."),
  739. '<strong>' . t('Abbreviate') . ':</strong> ' . t("Use the first letter of a field in uppercase for the Username, e.g. 'john' -> 'J'."),
  740. );
  741. $fieldmatch_description = theme('item_list', array('items' => $fieldmatch_description_parts));
  742. $form['field_match'] = array(
  743. '#type' => 'fieldset',
  744. '#title' => t('Field Match'),
  745. '#description' => $fieldmatch_description,
  746. '#weight' => -90,
  747. '#collapsible' => TRUE,
  748. '#collapsed' => $collapsed,
  749. '#tree' => TRUE,
  750. );
  751. // add default and email address options
  752. $user_fields[0] = '-------------';
  753. $additional_user_fields = module_invoke_all('user_import_form_field_match');
  754. foreach ($additional_user_fields as $type => $type_options) {
  755. if (is_array($type_options)) {
  756. foreach ($type_options as $field_id => $label) {
  757. $user_fields["$type-$field_id"] = $label;
  758. }
  759. }
  760. }
  761. asort($user_fields);
  762. $row = 0;
  763. $sort = array(t('--'), 1, 2, 3, 4);
  764. if (empty($data_row)) return;
  765. foreach ($data_row as $data_cell) {
  766. $form['field_match'][$row] = array(
  767. '#tree' => TRUE,
  768. );
  769. $form['field_match'][$row]['csv'] = array(
  770. '#markup' => check_plain(drupal_substr($data_cell, 0, 40)),
  771. );
  772. $form['field_match'][$row]['field_match'] = array(
  773. '#type' => 'select',
  774. '#default_value' => isset($import['field_match'][$row]['field_match']) ? $import['field_match'][$row]['field_match'] : $user_fields[0],
  775. '#options' => $user_fields,
  776. );
  777. $form['field_match'][$row]['username'] = array(
  778. '#type' => 'select',
  779. '#default_value' => isset($import['field_match'][$row]['username']) ? $import['field_match'][$row]['username'] : $sort[0],
  780. '#options' => $sort,
  781. );
  782. $form['field_match'][$row]['abbreviate'] = array(
  783. '#type' => 'checkbox',
  784. '#default_value' => isset($import['field_match'][$row]['abbreviate']) ? $import['field_match'][$row]['abbreviate'] : NULL,
  785. );
  786. $row++;
  787. }
  788. return;
  789. }
  790. // get first row of file
  791. function _user_import_file_row($filename, $handle, $delimiter = ',') {
  792. // Handle folks who may list 'tab' as 't' or 'tab'
  793. if (strtolower($delimiter) == 't' || strtolower($delimiter) == 'tab' || $delimiter == '\t' || $delimiter == '/t') {
  794. $delimiter = '\t';
  795. }
  796. $data_row = @fgetcsv($handle, 1000000, $delimiter);
  797. if (!$data_row) {
  798. form_set_error('file', t("Could not get data, the file '%filename' is either empty or has incompatible line endings.", array('%filename' => $filename)), 'error');
  799. }
  800. return $data_row;
  801. }
  802. // move from one stage to the next
  803. // set up all necessary variables
  804. function _user_import_initialise_import($import) {
  805. //_user_import_process won't work w/o this include
  806. module_load_include('inc', 'user_import', 'user_import.import');
  807. switch ($import['setting']) {
  808. case 'imported':
  809. drupal_set_message(t('File has already been imported'), 'error');
  810. break;
  811. // add setting template values to new import settings
  812. case 'file set':
  813. if (empty($import['template_id'])) return $import;
  814. $template = _user_import_settings_select($import['template_id']);
  815. $template['import_id'] = $import['import_id'];
  816. $template['filename'] = $import['filename'];
  817. $template['oldfilename'] = $import['oldfilename'];
  818. $template['filepath'] = $import['filepath'];
  819. $template['started'] = 0;
  820. $template['setting'] = 'file set';
  821. return $template;
  822. case 'test':
  823. case 'tested':
  824. $import['setting'] = 'import';
  825. $import['started'] = 0;
  826. $import['pointer'] = 0;
  827. $import['processed'] = 0;
  828. $import['valid'] = 0;
  829. _user_import_errors_display_delete($import['import_id']);
  830. _user_import_settings_save($import);
  831. _user_import_process($import);
  832. break;
  833. case 'template':
  834. unset($import['filename']);
  835. unset($import['oldfilename']);
  836. unset($import['filepath']);
  837. $import['started'] = 0;
  838. $import['pointer'] = 0;
  839. $import['processed'] = 0;
  840. $import['valid'] = 0;
  841. _user_import_settings_save($import);
  842. break;
  843. default:
  844. _user_import_process($import);
  845. drupal_set_message(t('Imported'));
  846. break;
  847. }
  848. return;
  849. }
  850. /**
  851. * Delete errors from database for a specified import.
  852. * @param $import_id
  853. */
  854. function _user_import_errors_display_delete($import_id) {
  855. db_query('DELETE FROM {user_import_errors} WHERE import_id = :import_id', array(':import_id' => $import_id));
  856. return;
  857. }
  858. function _user_import_profile($key = 'fid', $return_value = NULL) {
  859. if (!module_exists('profile')) return;
  860. static $fields_static;
  861. $fields = array();
  862. // avoid making more than one database call for profile info
  863. if (empty($fields_static)) {
  864. $results = db_query("SELECT * FROM {profile_field}");
  865. foreach ($results as $row) {
  866. // don't include private fields
  867. if (user_access('administer users') || $row->visibility != PROFILE_PRIVATE) {
  868. $fields_static[] = $row;
  869. }
  870. }
  871. }
  872. if (empty($fields_static)) return array();
  873. // return all profile fields info, or just specific type
  874. if (empty($return_value)) {
  875. foreach ($fields_static as $field) {
  876. $fields[$field->{$key}] = $field;
  877. }
  878. }
  879. else {
  880. foreach ($fields_static as $field) {
  881. $fields[$field->{$key}] = $field->{$return_value};
  882. }
  883. }
  884. asort($fields);
  885. return $fields;
  886. }