taxonomy_csv.export.admin.inc 16 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458
  1. <?php
  2. /**
  3. * @file
  4. * Create taxonomy csv export form and validate user input.
  5. */
  6. /**
  7. * Invoke associated files.
  8. */
  9. $module_dir = drupal_get_path('module', 'taxonomy_csv');
  10. require_once($module_dir . '/taxonomy_csv.api.inc');
  11. /**
  12. * Generates the taxonomy CSV export form.
  13. *
  14. * Form contain three fieldsets:
  15. * - 1. Which vocabulary to export ?
  16. * - 2. How to export (format of csv file) ?
  17. * - 1. Csv delimiter
  18. * - 2. Csv enclosure
  19. * - 3. Csv end of line
  20. * - 3. Order and specific options
  21. *
  22. * @ingroup forms
  23. * @see taxonomy_csv_export_form_validate()
  24. * @see taxonomy_csv_export_form_submit()
  25. * @see taxonomy_csv_export_form_default_values_validate()
  26. * @see taxonomy_csv_export_form_default_values_submit()
  27. */
  28. function taxonomy_csv_export_form($form, &$form_state) {
  29. // Remember previous values to use in particular when reloading form.
  30. // If not reloading form, use saved values if exist, else recommended ones.
  31. $list_recommended_values = _taxonomy_csv_values('export_default_ui');
  32. $list_previous_values = array();
  33. foreach ($list_recommended_values as $key => $value) {
  34. $list_previous_values[$key] = isset($form_state['values'][$key]) ?
  35. $form_state['values'][$key] :
  36. variable_get("taxonomy_csv_{$key}", $value);
  37. }
  38. $list_export_format = _taxonomy_csv_values('export_format');
  39. $list_export_delimiter = array(
  40. 'comma' => t('« , » (Comma)'),
  41. 'semicolon' => t('« ; » (Semicolon)'),
  42. 'tabulation' => t('« » (Tabulation)'),
  43. 'pipe' => t('« | » (Pipe)'),
  44. 'space' => t('« » (Space)'),
  45. 'currency_sign' => t('« ¤ » (Currency sign)'),
  46. 'custom_delimiter' => t('Custom delimiter'),
  47. );
  48. $list_export_enclosure = array(
  49. 'none' => t('None'),
  50. 'quotation' => t('« " » (Quotation mark)'),
  51. 'quote' => t("« ' » (Quote)"),
  52. 'custom_enclosure' => t('Custom enclosure'),
  53. );
  54. $list_export_line_ending = array(
  55. 'Unix' => t('Unix / Linux'),
  56. 'Mac' => t('Apple Mac'),
  57. 'MS-DOS' => t('Microsoft DOS'),
  58. );
  59. $list_export_order = array(
  60. 'name' => t('Alphabetic order'),
  61. 'weight' => t('Weight'),
  62. 'tid' => t('Internal order (tid)'),
  63. );
  64. // Build form.
  65. $form = array();
  66. $list_vocabularies = taxonomy_vocabulary_get_names();
  67. if (count($list_vocabularies) == 0) {
  68. $form['info'] = array(
  69. '#type' => 'item',
  70. '#markup' => t("As there isn't any vocabulary, nothing can be exported..."),
  71. );
  72. return $form;
  73. }
  74. // Else there are vocabularies.
  75. $form['tab'] = array(
  76. '#type' => 'vertical_tabs',
  77. '#default_tab' => 'content',
  78. );
  79. $form['tab']['content'] = array(
  80. '#type' => 'fieldset',
  81. '#title' => t('1. What do you want to export?'),
  82. '#collapsible' => TRUE,
  83. '#collapsed' => FALSE,
  84. );
  85. $form['tab']['content']['export_format'] = array(
  86. '#type' => 'radios',
  87. '#title' => 'CSV format',
  88. '#options' => $list_export_format,
  89. '#default_value' => $list_previous_values['export_format'],
  90. );
  91. $form['tab']['content']['info'] = array(
  92. '#type' => 'item',
  93. '#description' => t('See <a href="!more_help_link">advanced help</a> for informations about formats.', array('!more_help_link' => url('admin/help/taxonomy_csv'))) . '<br />'
  94. . t('In all cases, you will be notified if a duplicate is found.'),
  95. );
  96. $form['tab']['content']['export_vocabulary_id'] = array(
  97. '#type' => 'select',
  98. '#title' => t('Vocabularies to export'),
  99. '#options' => array(
  100. 0 => t('All vocabularies'),
  101. ),
  102. '#multiple' => TRUE,
  103. '#default_value' => $list_previous_values['export_vocabulary_id'],
  104. '#description' => t('The vocabularies you want to export.'),
  105. '#size' => min(12, count($list_vocabularies)) + 1,
  106. );
  107. foreach ($list_vocabularies as $vocabulary) {
  108. $form['tab']['content']['export_vocabulary_id']['#options'][$vocabulary->vid] = $vocabulary->name;
  109. }
  110. $form['tab']['csv_format'] = array(
  111. '#type' => 'fieldset',
  112. '#title' => t('2. How do you want to format your CSV file?'),
  113. '#collapsible' => TRUE,
  114. '#collapsed' => FALSE,
  115. );
  116. $form['tab']['csv_format']['export_delimiter'] = array(
  117. '#type' => 'select',
  118. '#title' => t('CSV value delimiter'),
  119. '#options' => $list_export_delimiter,
  120. '#default_value' => $list_previous_values['export_delimiter'],
  121. '#description' => t('Choose the delimiter to use in the CSV file.'),
  122. );
  123. $form['tab']['csv_format']['export_delimiter_custom'] = array(
  124. '#type' => 'textfield',
  125. '#title' => 'Custom delimiter',
  126. '#default_value' => $list_previous_values['export_delimiter_custom'],
  127. '#size' => 2,
  128. '#maxlength' => 1,
  129. '#description' => t('Specify your custom delimiter.'),
  130. '#states' => array(
  131. 'visible' => array(
  132. ':input[name=export_delimiter]' => array('value' => 'custom_delimiter'),
  133. ),
  134. ),
  135. );
  136. $form['tab']['csv_format']['export_enclosure'] = array(
  137. '#type' => 'select',
  138. '#title' => t('CSV value enclosure'),
  139. '#options' => $list_export_enclosure,
  140. '#default_value' => $list_previous_values['export_enclosure'],
  141. '#description' => t('Choose the enclosure used in the CSV file you want to export. Warning: enclosure should not be used in term definitions, specially in descriptions. Furthermore, an enclosure is needed if a field contains a line ending character. Export process will stop in case of problem.'),
  142. );
  143. $form['tab']['csv_format']['export_enclosure_custom'] = array(
  144. '#type' => 'textfield',
  145. '#title' => 'Custom enclosure',
  146. '#default_value' => $list_previous_values['export_enclosure_custom'],
  147. '#size' => 2,
  148. '#maxlength' => 1,
  149. '#description' => t('Specify your custom enclosure.'),
  150. '#states' => array(
  151. 'visible' => array(
  152. ':input[name=export_enclosure]' => array('value' => 'custom_enclosure'),
  153. ),
  154. ),
  155. );
  156. $form['tab']['csv_format']['export_line_ending'] = array(
  157. '#type' => 'select',
  158. '#title' => t('Line ending'),
  159. '#options' => $list_export_line_ending,
  160. '#default_value' => $list_previous_values['export_line_ending'],
  161. '#description' => t('Choose the end of line to use.'),
  162. );
  163. $form['tab']['advanced_options'] = array(
  164. '#type' => 'fieldset',
  165. '#title' => t('3. Advanced and specific options'),
  166. '#collapsible' => TRUE,
  167. '#collapsed' => FALSE,
  168. );
  169. $form['tab']['advanced_options']['export_order'] = array(
  170. '#type' => 'select',
  171. '#title' => t('Terms order'),
  172. '#options' => $list_export_order,
  173. '#default_value' => $list_previous_values['export_order'],
  174. '#description' => t('Choose order of exported terms.'),
  175. '#states' => array(
  176. 'invisible' => array(
  177. ':input[name=export_format]' => array('value' => TAXONOMY_CSV_FORMAT_TREE),
  178. ),
  179. ),
  180. );
  181. $form['tab']['advanced_options']['info'] = array(
  182. '#type' => 'item',
  183. '#description' => t('Specific options are shown only if suitable.'),
  184. );
  185. $form['tab']['advanced_options']['result_duplicates'] = array(
  186. '#type' => 'checkbox',
  187. '#title' => t('Show duplicate terms after export'),
  188. '#default_value' => $list_previous_values['result_duplicates'],
  189. '#description' => '',
  190. );
  191. $form['export_submit'] = array(
  192. '#type' => 'submit',
  193. '#value' => t('Export'),
  194. );
  195. $form['export_default_values'] = array(
  196. '#type' => 'submit',
  197. '#value' => t('Reset to defaults'),
  198. '#validate' => array('taxonomy_csv_export_form_default_values_validate'),
  199. '#submit' => array('taxonomy_csv_export_form_default_values_submit'),
  200. );
  201. return $form;
  202. }
  203. /**
  204. * Handles CSV export form validation.
  205. *
  206. * @see taxonomy_csv_export_form()
  207. */
  208. function taxonomy_csv_export_form_validate($form, &$form_state) {
  209. // Invoke taxonomy_csv api (defines and functions).
  210. $module_dir = drupal_get_path('module', 'taxonomy_csv');
  211. require_once($module_dir . '/export/taxonomy_csv.export.api.inc');
  212. $options = &$form_state['values'];
  213. // 1. Presave a file in order to check it.
  214. // Define vocabulary id (use simple api name of it).
  215. $options['vocabulary_id'] = $options['export_vocabulary_id'];
  216. $messages = _taxonomy_csv_export_output_presave($options);
  217. // 2, Simplify values to be compatible with api checks.
  218. // Define true delimiter.
  219. $delimiter = array(
  220. 'comma' => ',',
  221. 'semicolon' => ';',
  222. 'tabulation' => "\t",
  223. 'pipe' => '|',
  224. 'space' => ' ',
  225. 'currency_sign' => '¤',
  226. 'custom_delimiter' => $options['export_delimiter_custom'],
  227. );
  228. $options['delimiter'] = $delimiter[$options['export_delimiter']];
  229. // Define true enclosure.
  230. $enclosure = array(
  231. 'none' => '',
  232. 'quotation' => '"',
  233. 'quote' => "'",
  234. 'custom_enclosure' => $options['export_enclosure_custom'],
  235. );
  236. $options['enclosure'] = $enclosure[$options['export_enclosure']];
  237. // Define true line ending and order.
  238. $options['line_ending'] = $options['export_line_ending'];
  239. $options['order'] = $options['export_order'];
  240. // 3, Make api checks and eventually update options by reference.
  241. $messages = array_merge($messages, _taxonomy_csv_export_check_options($options));
  242. // Use form set error for api errors.
  243. foreach (array(
  244. 'vocabulary_id' => 'export_vocabulary_id',
  245. 'delimiter' => 'export_delimiter',
  246. 'enclosure' => 'export_enclosure',
  247. 'line_ending' => 'export_line_ending',
  248. 'order' => 'export_order',
  249. ) as $key => $value) {
  250. if (isset($message[$key])) {
  251. $message[$value] = $message[$key];
  252. unset($message[$key]);
  253. }
  254. }
  255. // 4. Make non api checks.
  256. if (($options['export_delimiter'] == 'custom_delimiter')
  257. && (empty($options['export_delimiter_custom']))) {
  258. $messages['export_delimiter_custom'] = t('You choose to use a custom delimiter, but your delimiter is empty.');
  259. }
  260. if (($options['export_enclosure'] == 'custom_enclosure')
  261. && (empty($options['export_enclosure_custom']))) {
  262. $messages['export_enclosure_custom'] = t('You choose to use a custom enclosure, but your enclosure is empty.');
  263. }
  264. if (($options['export_delimiter'] == 'custom_delimiter')
  265. && (drupal_strlen($options['export_delimiter_custom']) > 1)) {
  266. $messages['export_delimiter_custom'] = t('Delimiter should have only one character.');
  267. }
  268. if (($options['export_enclosure'] == 'custom_enclosure')
  269. && (drupal_strlen($options['export_enclosure_custom']) > 1)) {
  270. $messages['export_enclosure_custom'] = t('Enclosure should have only zero or one character.');
  271. }
  272. // 5. Finish validatation of form.
  273. foreach ($messages as $item => $message) {
  274. form_set_error(check_plain($item), filter_xss($message));
  275. }
  276. }
  277. /**
  278. * Validate options of exported vocabulary.
  279. *
  280. * @param $options
  281. * An associative array of options.
  282. *
  283. * @return
  284. * Array of messages errors if any.
  285. * By reference options are cleaned and completed.
  286. */
  287. function _taxonomy_csv_export_check_options(&$options) {
  288. $messages = array();
  289. if ($options['export_format'] == TAXONOMY_CSV_FORMAT_TRANSLATE && !module_exists('i18n_taxonomy')) {
  290. $messages['export_format'] = t('You cannot use Translations if i18n_taxonomy is not enabled.');
  291. }
  292. $list_vocabularies = taxonomy_get_vocabularies();
  293. if (!$list_vocabularies) {
  294. $messages['vocabulary_id'] = t('No vocabulary to export.');
  295. }
  296. elseif ($options['vocabulary_id']) {
  297. // Replace machine name with vocabulary id.
  298. if (!(is_numeric($options['vocabulary_id']) || is_array($options['vocabulary_id']))) {
  299. $vocabulary = taxonomy_vocabulary_machine_name_load($options['vocabulary_id']);
  300. $options['vocabulary_id'] = array($vocabulary->vid);
  301. }
  302. // Replace vocabulary_id by an array if only one item is selected.
  303. elseif (!is_array($options['vocabulary_id'])) {
  304. $options['vocabulary_id'] = array($options['vocabulary_id']);
  305. }
  306. if ((count($options['vocabulary_id']) > 1) && in_array(0, $options['vocabulary_id'])) {
  307. $messages['vocabulary_id'] = t('You choose to export all vocabularies, but you select some individual vocabularies too.');
  308. }
  309. foreach ($options['vocabulary_id'] as $item) {
  310. if (($item != 0) && !isset($list_vocabularies[$item])) {
  311. $messages['vocabulary_id'] = t("You choose to export a vocabulary, but it doesn't exist.");
  312. }
  313. }
  314. }
  315. // Delimiter and enclosure greater than one character are forbidden.
  316. if (drupal_strlen($options['delimiter']) != 1) {
  317. $messages['delimiter'] = t('Delimiter should be a one character string.');
  318. }
  319. if (drupal_strlen($options['enclosure']) > 1) {
  320. $messages['enclosure'] = t('Enclosure lenght cannot be greater than one character.');
  321. }
  322. if ($options['delimiter'] == $options['enclosure']) {
  323. $messages['delimiter'] = t('Delimiter and enclosure cannot be same character.');
  324. }
  325. if (!in_array($options['line_ending'], array(
  326. 'Unix',
  327. 'Mac',
  328. 'MS-DOS',
  329. ))) {
  330. $messages['line_ending'] = t('Line ending should be "Unix", "Mac" or "MS-DOS".');
  331. }
  332. if (!in_array($options['order'], array(
  333. 'name',
  334. 'tid',
  335. 'weight',
  336. ))) {
  337. $messages['order'] = t('Order should be "name", "tid" or "weight".');
  338. }
  339. // Calculates number of terms to be exported.
  340. $options['total_terms'] = taxonomy_csv_vocabulary_count_terms($options['vocabulary_id']);
  341. if (!$options['total_terms']) {
  342. $messages['vocabulary_id'] = t('Vocabulary has no term to export. Export finished.');
  343. }
  344. return $messages;
  345. }
  346. /**
  347. * Handles CSV export form submission and launch batch set.
  348. *
  349. * @see taxonomy_csv_export_form()
  350. */
  351. function taxonomy_csv_export_form_submit($form, &$form_state) {
  352. // Remember last preferences and prepare only options to be sent to api.
  353. foreach (array(
  354. 'export_format',
  355. 'export_vocabulary_id',
  356. 'export_delimiter',
  357. 'export_delimiter_custom',
  358. 'export_enclosure',
  359. 'export_enclosure_custom',
  360. 'export_line_ending',
  361. 'export_order',
  362. 'result_duplicates',
  363. ) as $option) {
  364. variable_set('taxonomy_csv_' . $option, $form_state['values'][$option]);
  365. $options[$option] = $form_state['values'][$option];
  366. }
  367. // Finish to prepare $options. Unset useless options for api.
  368. unset($options['export_vocabulary_id']);
  369. unset($options['export_delimiter']);
  370. unset($options['export_delimiter_custom']);
  371. unset($options['export_enclosure']);
  372. unset($options['export_enclosure_custom']);
  373. unset($options['export_line_ending']);
  374. unset($options['export_order']);
  375. $options['delimiter'] = $form_state['values']['delimiter'];
  376. $options['enclosure'] = $form_state['values']['enclosure'];
  377. $options['line_ending'] = $form_state['values']['line_ending'];
  378. $options['order'] = $form_state['values']['order'];
  379. $options['file'] = $form_state['values']['file'];
  380. $options['vocabulary_id'] = $form_state['values']['vocabulary_id'];
  381. $options['check_options'] = FALSE; // Already done.
  382. $options['result_display'] = TRUE;
  383. // Prepares process batch (will be automatically processed when returns).
  384. taxonomy_csv_vocabulary_export($options);
  385. }
  386. /**
  387. * Restore recommended default values in the export form. Empty validate hook.
  388. */
  389. function taxonomy_csv_export_form_default_values_validate($form, &$form_state) {
  390. }
  391. /**
  392. * Restore recommended default values in the export form.
  393. */
  394. function taxonomy_csv_export_form_default_values_submit($form, &$form_state) {
  395. foreach (_taxonomy_csv_values('export_default_ui') as $option => $value) {
  396. variable_set("taxonomy_csv_$option", $value);
  397. }
  398. unset($form_state['values']);
  399. unset($form_state['storage']);
  400. drupal_set_message(t('Export options have been reset to default.'));
  401. }