/[drupal]/contributions/modules/taxonomy_csv/taxonomy_csv.module
ViewVC logotype

Contents of /contributions/modules/taxonomy_csv/taxonomy_csv.module

Parent Directory Parent Directory | Revision Log Revision Log | View Revision Graph Revision Graph


Revision 2.12 - (show annotations) (download) (as text)
Tue Oct 20 20:21:44 2009 UTC (5 weeks, 1 day ago) by danielkm
Branch: MAIN
CVS Tags: HEAD
Changes since 2.11: +537 -169 lines
File MIME type: text/x-php
By Daniel Berthereau: Added export of terms and vocabularies.
1 <?php
2 // $Id: taxonomy_csv.module,v 2.11 2009/10/05 09:43:12 danielkm Exp $
3
4 /**
5 * taxonomy_csv module for Drupal
6 *
7 * Copyright (c) 2007-2008 Dennis Stevense, see LICENSE.txt for more information
8 * Copyright (c) 2009 Daniel Berthereau <daniel.drupal@berthereau.net>
9 *
10 * This program is free software; you can redistribute it and/or modify it under
11 * the terms of the GNU General Public License as published by the Free Software
12 * Foundation; either version 2 of the License, or (at your option) any later
13 * version.
14 *
15 * This program is distributed in the hope that it will be useful, but WITHOUT
16 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
17 * FOR A PARTICULAR PURPOSE. See the GNU General Public License for more
18 * details.
19 *
20 * You should have received a copy of the GNU General Public License along with
21 * this program; if not, write to the Free Software Foundation, Inc.,
22 * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
23 */
24
25 /**
26 * @file
27 * Quick export and import of taxonomies, structure or lists of terms to or from
28 * a csv local or distant file or a text area.
29 *
30 * Automatically exports or imports a list of terms, structure, children,
31 * related, synonyms, descriptions and/or weights from or into a vocabulary with
32 * a simple csv file.
33 *
34 * taxonomy_csv.module contains functions to manage import/export form pages.
35 * taxonomy_csv.api.inc is an api which can be use alone. It contains generic
36 * functions to import and export vocabularies or lines.
37 */
38
39 /**
40 * Implements hook_help().
41 */
42 function taxonomy_csv_help($path, $arg) {
43 global $language;
44
45 switch ($path) {
46 case 'admin/content/taxonomy/csv_import':
47 $output = '<p>'. t('Use this form to import a taxonomy, a structure or a list of terms into a vocabulary from a simple <a href="!link" title="Wikipedia definition">CSV</a> file, a url or a copy-and-paste text.', array('!link' => url('http://en.wikipedia.org/wiki/Comma-separated_values'))) .'</p>';
48 $output .= '<p>'. t('For performance reasons, it is recommended to disable some other taxonomy related modules before import of big taxonomies and to reactivate them after process.') .'</p>';
49 $output .= '<p>'. t('<strong>Warning:</strong> If you want to update an existing vocabulary, make sure you have a backup before you proceed so you can roll back, if necessary.') . theme('more_help_link', url('admin/help/taxonomy_csv')) .'</p>';
50 return $output;
51
52 case 'admin/content/taxonomy/csv_export':
53 $output = '<p>'. t('Use this form to export a taxonomy, a structure or a list of terms to a simple <a href="!link" title="Wikipedia definition">CSV</a> file.', array('!link' => url('http://en.wikipedia.org/wiki/Comma-separated_values'))) . theme('more_help_link', url('admin/help/taxonomy_csv')) .'</p>';
54 return $output;
55
56 case 'admin/help#taxonomy_csv':
57 $output = file_get_contents(drupal_get_path('module', 'taxonomy_csv') . ((is_file(drupal_get_path('module', 'taxonomy_csv') ."/translations/taxonomy_csv.help.{$language->prefix}.html")) ? "/translations/taxonomy_csv.help.{$language->prefix}.html" : '/taxonomy_csv.help.html'));
58 return $output;
59 }
60 }
61
62 /**
63 * Implements hook_perm().
64 */
65 function taxonomy_csv_perm() {
66 return array(
67 'administer taxonomy by csv',
68 'export taxonomy by csv',
69 );
70 }
71
72 /**
73 * Implements hook_menu().
74 *
75 * @note See hook_menu for a description of return values.
76 */
77 function taxonomy_csv_menu() {
78 $items = array();
79
80 $items['admin/content/taxonomy/csv_import'] = array(
81 'title' => 'CSV import',
82 'page callback' => 'taxonomy_csv_form_import_prepare',
83 'access arguments' => array('administer taxonomy by csv'),
84 'weight' => 12,
85 'type' => MENU_LOCAL_TASK,
86 );
87
88 $items['admin/content/taxonomy/csv_export'] = array(
89 'title' => 'CSV export',
90 'page callback' => 'taxonomy_csv_form_export_prepare',
91 'access arguments' => array('export taxonomy by csv'),
92 'weight' => 13,
93 'type' => MENU_LOCAL_TASK,
94 );
95
96 return $items;
97 }
98
99 /**
100 * Menu callback of the main import form.
101 */
102 function taxonomy_csv_form_import_prepare() {
103 // Invoke taxonomy_csv api (defines and functions).
104 $taxonomy_csv_path = drupal_get_path('module', 'taxonomy_csv');
105 require_once("$taxonomy_csv_path/taxonomy_csv.api.inc");
106
107 // Javascript and css allow to show only available options depending user's choice.
108 drupal_add_js("$taxonomy_csv_path/taxonomy_csv.js");
109 drupal_add_css("$taxonomy_csv_path/taxonomy_csv.css");
110
111 return drupal_get_form('taxonomy_csv_form_import');
112 }
113
114 /**
115 * Generates the taxonomy CSV import form.
116 *
117 * Form contain five fieldsets:
118 * - 1. What to import ?
119 * 1. What is content of the source ?
120 * - 2. Where are items to import ?
121 * 1. Source choice
122 * 1. Source select
123 * 2. Source file or text area
124 * 2. Source options
125 * 1. Source delimiter
126 * 2. Source enclosure
127 * - 3. Which vocabulary to import into (destination) ?
128 * 1. Destination type
129 * 2. Vocabulary choice
130 * - 4. How to import ?
131 * 1. Previous or existing terms
132 * 2. Specific import options depending on source content
133 * - 5. Advanced options
134 * 1. Tweaks for big and specific vocabularies
135 * 2. How to be notified
136 *
137 * As what will become existing terms depends on what is imported, dynamic
138 * options are used: only possible parameters are shown. All options are
139 * displayed if javascript is not activated.
140 *
141 * @ingroup forms
142 * @see taxonomy_csv_form_import_validate()
143 * @see taxonomy_csv_form_import_submit()
144 */
145 function taxonomy_csv_form_import($form_state) {
146 // Display main import form
147 $list_recommended_values = array(
148 'import_format' => TAXONOMY_CSV_FORMAT_ALONE_TERMS,
149 'source_choice' => 'text',
150 'import_delimiter' => 'comma',
151 'import_delimiter_custom' => '',
152 'import_enclosure' => 'none',
153 'import_enclosure_custom' => '',
154 'vocabulary_target' => 'autocreate',
155 'vocabulary_id' => 'choose_vocabulary', // Not used for security reason (avoid import mistake). Not to be translated.
156 'existing_items' => TAXONOMY_CSV_EXISTING_UPDATE,
157 'relations_create_subrelations' => FALSE,
158 'relations_all_vocabularies' => FALSE,
159 'disable_internal_cache' => FALSE,
160 'disable_hierarchy_check' => FALSE,
161 'hierarchy_level' => 2,
162 'disable_line_checks' => FALSE,
163 'disable_utf8_check' => FALSE,
164 'result_stats' => 'result_stats',
165 'result_terms' => 'result_terms',
166 'result_level' => 'notices',
167 'result_type' => 'by_message',
168 );
169
170 // Remember previous values to use in particular when reloading form.
171 // If not reloading form, then use previous saved value if exists, else recommended value.
172 // Warning: specific values 'text', 'path' and 'url are not saved here.
173 $list_previous_values = array();
174 foreach ($list_recommended_values as $key => $value) {
175 $list_previous_values[$key] = isset($form_state['values'][$key]) ?
176 $form_state['values'][$key] :
177 variable_get("taxonomy_csv_{$key}", $value);
178 }
179
180 $list_import_format = _taxonomy_csv_info_lists('list_import_format');
181
182 $list_import_delimiter = array(
183 'comma' => t('« , » (Comma)'),
184 'semicolon' => t('« ; » (Semicolon)'),
185 'tabulation' => t('« » (Tabulation)'),
186 'space' => t('« » (Space)'),
187 'currency_sign' => t('« ¤ » (Currency sign)'),
188 'custom_delimiter' => t('Custom delimiter'),
189 );
190
191 $list_import_enclosure = array(
192 'none' => t('None'),
193 'quotation' => t('« " » (Quotation mark)'),
194 'custom_enclosure' => t('Custom enclosure'),
195 );
196
197 $list_vocabulary_target = array(
198 'autocreate' => t('Autocreate a new vocabulary'),
199 'duplicate' => t('Duplicate an existing vocabulary'),
200 'existing' => t('Import in an existing vocabulary'),
201 );
202
203 $list_import_option = _taxonomy_csv_info_lists('list_import_option');
204
205 // Build form.
206 $form = array(
207 '#attributes' => array(
208 'enctype' => 'multipart/form-data',
209 )
210 );
211
212 // Used with recommended values button.
213 $form['list']['list_recommended_values'] = array(
214 '#type' => 'value',
215 '#value' => $list_recommended_values,
216 );
217
218 // Advertise if Pathauto module is activated. Issue http://drupal.org/node/540916.
219 if (module_exists('pathauto')) {
220 drupal_set_message(t("<strong>Warning</strong>: Pathauto module is activated.<br />This module slows down taxonomy import process and only few terms can be imported. It's advised to disabled it manually in !modules_section. Settings aren't lost when you disable it - and not uninstall it -.<br />After import process, you can reactivate Pathauto and eventually bulk generate aliases for newly imported terms.", array('!modules_section' => l(t("modules section"), 'admin/build/modules'))), 'error');
221 }
222
223 $form['format'] = array(
224 '#type' => 'fieldset',
225 '#title' => t('1. What do you want to import?'),
226 '#collapsible' => TRUE,
227 '#collapsed' => FALSE,
228 );
229
230 $form['format']['import_format'] = array(
231 '#type' => 'select',
232 '#title' => '',
233 '#options' => $list_import_format,
234 '#default_value' => $list_previous_values['import_format'],
235 '#required' => TRUE,
236 );
237
238 if (isset($_COOKIE['has_js'])) {
239 $form['format']['description_alone_terms'] = array(
240 '#type' => 'item',
241 '#description' => t('Only the term in the first column of each line is imported. Additional columns are ignored.'),
242 '#prefix' => '<div id="description_alone_terms">',
243 '#suffix' => '</div>',
244 );
245 $form['format']['description_fields_links'] = array(
246 '#type' => 'item',
247 '#description' => t('Allow to import full term definitions and links.') .'<br />'.
248 t('Format: term name, term id, vocabulary id, term description, weight, number of synonyms, number of first level parents, number of first level children, number of related terms, list of synonyms, list of first level parents ids, list of first level children ids, list of related terms ids, list of vocabulary ids of related terms.') .'<br/>'.
249 t('Only term name should be defined. Other values can be empty. Ids are not internal term ids or vocabulary ids, but a unique identifiant. Ids can be a number or a name. In most case, you can use true name. In fact, term ids need to be specific only for duplicate term names in order to identify each item. So for duplicates, you can use term name with a serial number. Main term id is only needed when term is a duplicate one.') .'<br />'.
250 t("With this source content, destination is determined by source. If third column is empty, a new vocabulary will be created. If it's a name or a number, a vocabulary will be created if it doesn't exist. This process is used for related terms too. If vocabulary of a related term is not defined, vocabulary of main term is used. Warning: It's not recommended to change the vocabulary of a term with links."),
251 '#prefix' => '<div id="description_fields_links">',
252 '#suffix' => '</div>',
253 );
254 $form['format']['description_flat'] = array(
255 '#type' => 'item',
256 '#description' => t('All items will be imported as terms.'),
257 '#prefix' => '<div id="description_flat">',
258 '#suffix' => '</div>',
259 );
260 $form['format']['description_tree_structure'] = array(
261 '#type' => 'item',
262 '#description' => t('Allow to create a tree structure (geography, classification...).') .'<br />'.
263 t('Format: The first term is imported as a root level parent, the second as child of first term, the third as child of second term and so on. The lower child is the last term of a line. Others are hierarchical parents.'),
264 '#prefix' => '<div id="description_tree_structure">',
265 '#suffix' => '</div>',
266 );
267 $form['format']['description_polyhierarchy'] = array(
268 '#type' => 'item',
269 '#description' => t('Allow to create a polyhierarchical structure (genealogy, complex nomenclatures...).') .'<br />'.
270 t('Format: The first term is imported as a root level parent, the second as child of first term, the third as child of second term and so on. The lower child is the last term of a line. Others are hierarchical parents.'),
271 '#prefix' => '<div id="description_polyhierarchy">',
272 '#suffix' => '</div>',
273 );
274 $form['format']['description_parents'] = array(
275 '#type' => 'item',
276 '#description' => t('Allow to create a polyhierarchical taxonomy (genealogy...).') .'<br />'.
277 t('First item is imported as a term and next ones as parents of first term. Unlike structure import, all parents are first level parents.'),
278 '#prefix' => '<div id="description_parents">',
279 '#suffix' => '</div>',
280 );
281 $form['format']['description_children'] = array(
282 '#type' => 'item',
283 '#description' => t('Allow to create a polyhierarchical taxonomy (genealogy...).') .'<br />'.
284 t('First item is imported as a term and next ones as children of first term. Unlike structure import, all children are first level children.'),
285 '#prefix' => '<div id="description_children">',
286 '#suffix' => '</div>',
287 );
288 $form['format']['description_relations'] = array(
289 '#type' => 'item',
290 '#description' => t('Allow to create relations between the term in the first column and next terms of the line.'),
291 '#prefix' => '<div id="description_relations">',
292 '#suffix' => '</div>',
293 );
294 $form['format']['description_fields'] = array(
295 '#type' => 'item',
296 '#description' => t('Import a full term definition') .'<br />'.
297 t('Format: term name, weight, description, list of synonyms.'),
298 '#prefix' => '<div id="description_fields">',
299 '#suffix' => '</div>',
300 );
301 $form['format']['description_descriptions'] = array(
302 '#type' => 'item',
303 '#description' => t('Allow to import descriptions of terms. The term is in the first column and the matching description is in the second column.'),
304 '#prefix' => '<div id="description_descriptions">',
305 '#suffix' => '</div>',
306 );
307 $form['format']['description_weights'] = array(
308 '#type' => 'item',
309 '#description' => t('Allow to import a weight of a term. The term is in the first column and the matching weight is in the second column.'),
310 '#prefix' => '<div id="description_weights">',
311 '#suffix' => '</div>',
312 );
313 $form['format']['description_synonyms'] = array(
314 '#type' => 'item',
315 '#description' => t('Allow to import synonyms of terms. Each line contains a term in the first column and next items are matching synonyms.'),
316 '#prefix' => '<div id="description_synonyms">',
317 '#suffix' => '</div>',
318 );
319 $form['format']['description_taxonomy_manager'] = array(
320 '#type' => 'item',
321 '#description' => t('Allow to import a vocabulary exported with Taxonomy manager.') .'<br />'.
322 t("Format: Each line contains: vocabulary id, term id, term name, term description and list of parents. In this format, order of all lines is important, because it's impossible to attach a parent to an item if this parent hasn't been imported in a previous line."),
323 '#prefix' => '<div id="description_taxonomy_manager">',
324 '#suffix' => '</div>',
325 );
326 }
327 $form['format']['info'] = array(
328 '#type' => 'item',
329 '#description' => t('Notice: currently, vocabulary structure is recommended to be imported first when multiple files are imported (with fields and links, flat, tree structure, polyhierarchy, parents or children choice). See <a href="!more_help_link">advanced help</a> for informations about types.', array('!more_help_link' => url('admin/help/taxonomy_csv'))),
330 );
331
332 $form['import'] = array(
333 '#type' => 'fieldset',
334 '#title' => t('2. Where are items to import?'),
335 '#collapsible' => TRUE,
336 '#collapsed' => FALSE,
337 '#attributes' => array('id' => 'edit-import'),
338 );
339
340 $form['import']['source_choice'] = array(
341 '#type' => 'select',
342 '#title' => '',
343 '#options' => array(
344 'text' => t('In the below text area'),
345 'path' => t('In a local file'),
346 'url' => t('In a distant file'),
347 ),
348 '#default_value' => $list_previous_values['source_choice'],
349 );
350
351 $form['import']['text'] = array(
352 '#type' => 'textarea',
353 '#title' => t('Terms to import'),
354 '#rows' => 3,
355 '#cols' => 80,
356 '#default_value' => isset($form_state['values']['text']) ? $form_state['values']['text'] : '',
357 '#description' => t('Write your csv formated terms directly in this text area.'),
358 );
359
360 $form['import']['path'] = array(
361 '#type' => 'file',
362 '#title' => t('CSV file'),
363 '#description' => t('Browse to the file') .'<br >'. (($max_size = parse_size(ini_get('upload_max_filesize'))) ? t('Due to server restrictions, the <strong>maximum upload file size is !max_size</strong>. Files that exceed this size will be disregarded.', array('!max_size' => format_size($max_size))) : ''),
364 );
365
366 $form['import']['url'] = array(
367 '#type' => 'textfield',
368 '#title' => t('CSV file'),
369 '#description' => t('Enter the url (http, ftp, file, path...)') .'<br >'. (($max_size = parse_size(ini_get('upload_max_filesize'))) ? t('Due to server restrictions, the <strong>maximum upload file size is !max_size</strong>. Files that exceed this size will be disregarded.', array('!max_size' => format_size($max_size))) : ''),
370 );
371
372 $form['import']['csv_format'] = array(
373 '#type' => 'fieldset',
374 '#title' => t('Advanced source settings (delimiter and enclosure)'),
375 '#description' => t('Notice: either you import terms by a file or by a text area, the csv format is the same. Default delimiter is a comma ("<strong><code> , </code></strong>"). Default enclosure is none, but quotation mark ("<strong><code> " </code></strong>") is automatically managed.'),
376 '#collapsible' => TRUE,
377 '#collapsed' => (
378 ($list_previous_values['import_delimiter'] == $list_recommended_values['import_delimiter'])
379 && ($list_previous_values['import_enclosure'] == $list_recommended_values['import_enclosure'])),
380 '#attributes' => array('id' => 'edit-csv-format'),
381 );
382
383 $form['import']['csv_format']['import_delimiter'] = array(
384 '#type' => 'select',
385 '#title' => t('CSV value delimiter'),
386 '#options' => $list_import_delimiter,
387 '#default_value' => $list_previous_values['import_delimiter'],
388 '#description' => t("Choose the delimiter used in the CSV file you want to import. Tabulation can't be used with text area import."),
389 '#attributes' => array('id' => 'delimiter'),
390 );
391
392 $form['import']['csv_format']['import_delimiter_custom'] = array(
393 '#type' => 'textfield',
394 '#title' => '',
395 '#default_value' => $list_previous_values['import_delimiter_custom'],
396 '#size' => 2,
397 '#maxlength' => 1,
398 );
399
400 $form['import']['csv_format']['import_enclosure'] = array(
401 '#type' => 'select',
402 '#title' => t('CSV value enclosure'),
403 '#options' => $list_import_enclosure,
404 '#default_value' => $list_previous_values['import_enclosure'],
405 '#description' => t('Choose the enclosure used in the CSV file you want to import.'),
406 '#attributes' => array('id' => 'enclosure'),
407 );
408
409 $form['import']['csv_format']['import_enclosure_custom'] = array(
410 '#type' => 'textfield',
411 '#title' => '',
412 '#default_value' => $list_previous_values['import_enclosure_custom'],
413 '#size' => 2,
414 '#maxlength' => 1,
415 );
416
417 $form['destination'] = array(
418 '#type' => 'fieldset',
419 '#title' => t('3. Which vocabulary do you want to import into?'),
420 '#collapsible' => TRUE,
421 '#collapsed' => FALSE,
422 '#description' => t('Terms can be imported into a new vocabulary or in an existing one. You can choose to duplicate an existing vocabulary too in order to check import. You might want to !add-new-vocab.', array(
423 '!add-new-vocab' => l(t('add a new vocabulary'), 'admin/content/taxonomy/add/vocabulary', array('query' => drupal_get_destination())),
424 )) .'<br />'.
425 t('With some import formats as "Fields and links", vocabulary destination is defined by source content and this option is not used.'),
426 '#attributes' => array('id' => 'edit-destination'),
427 );
428
429 $list_vocabularies = taxonomy_get_vocabularies();
430
431 if (count($list_vocabularies) == 0) {
432 $form['destination']['#description'] .= '<br />'. t("As there isn't any vocabulary, terms will be imported in a new automatically created vocabulary.");
433
434 $form['destination']['vocabulary_target'] = array(
435 '#type' => 'value',
436 '#value' => 'autocreate',
437 );
438
439 $form['destination']['vocabulary_id'] = array(
440 '#type' => 'value',
441 '#value' => 0,
442 );
443 }
444 else {
445 $form['destination']['vocabulary_target'] = array(
446 '#type' => 'select',
447 '#options' => $list_vocabulary_target,
448 '#default_value' => $list_previous_values['vocabulary_target'],
449 '#description' => t('
450 When you want to import a new taxonomy into an existing one, it is recommended to process in three steps in order to allow a good import.
451 <ul>
452 <li>First, check the import file with the < <em>Autocreate a new vocabulary</em> > option. Repeat this step while there are warnings and notices.</li>
453 <li>Second, check new and existing terms merge with the < <em>Duplicate an existing vocabulary</em> > option. This choice creates a duplicate of your target existing vocabulary and import your new terms into. Original nodes attachments are not duplicated.</li>
454 <li>Finally, you can import your file in the true vocabulary with the < <em>Import in an existing vocabulary</em> > option. This allows you to keep old links between existing terms and nodes.</li>
455 </ul>
456 If you only want to create a new vocabulary, the first choice is sufficient, unless when you have multiple files for one vocabulary.'),
457 );
458
459 $form['destination']['vocabulary_id'] = array(
460 '#type' => 'select',
461 '#title' => t('Vocabulary choice'),
462 '#options' => array(
463 'choose_vocabulary' => t('[Choose an existing vocabulary]'),
464 ),
465 '#default_value' => 'choose_vocabulary',
466 '#description' => t('The vocabulary you want to import the file into.'),
467 );
468 foreach ($list_vocabularies as $vid => $vocabulary) {
469 $form['destination']['vocabulary_id']['#options'][$vid] = $vocabulary->name;
470 }
471 }
472
473 $form['import_options'] = array(
474 '#type' => 'fieldset',
475 '#title' => t('4. How to import your terms?'),
476 '#required' => TRUE,
477 '#collapsible' => TRUE,
478 '#collapsed' => FALSE,
479 );
480
481 $form['import_options']['existing_items'] = array(
482 '#type' => 'radios',
483 '#title' => t('What will existing or previous imported terms become when a term with same name will be imported?'),
484 '#default_value' => $list_previous_values['existing_items'],
485 '#description' => t('This option allows to set what previous imported terms will become if a new line contains the same terms. Usually, it indicates an error or a unoptimized source, unless you allow duplicates.<br />
486 This option is used too with existing terms in the target vocabulary. Recommended value is to update and merge. If you choose to ignore previous or existing terms, the vocabulary will have duplicate terms.<br />
487 Some choices may be currently disabled.'),
488 );
489 if (isset($_COOKIE['has_js'])) {
490 // Store full list of generic existing_items and set only the correct one in order to keep all options possible with javascript and css.
491 $form['import_options']['existing_items']['#options'] = $list_import_option;
492
493 // Descriptions and examples of the option existing_items option.
494 $form['import_options']['help_alone_terms'] = array(
495 '#type' => 'item',
496 '#value' => t('Additional help:') .' '. t('Alone terms'),
497 '#description' => t('This option indicates whether existing terms with the same name should be updated or ignored. If ignored, duplicates may be created.'),
498 '#prefix' => '<div id="help_alone_terms">',
499 '#suffix' => '</div>',
500 );
501 $form['import_options']['help_fields_links'] = array(
502 '#type' => 'item',
503 '#value' => t('Additional help:') .' '. t('Full term fields and links'),
504 '#description' => t('This option indicates whether and how existing terms with the same name should be updated or ignored.') .'<br />'.
505 t('By nature, only one option can be chosen with this format.') .'<br />'.
506 t('<ul>
507 <li><em>"Update and merge"</em>: update term or create it if not exists and merge eventual item with new one.</li>
508 </ul>'
509 ),
510 '#prefix' => '<div id="help_fields_links">',
511 '#suffix' => '</div>',
512 );
513 $form['import_options']['help_flat'] = array(
514 '#type' => 'item',
515 '#value' => t('Additional help:') .' '. t('Terms'),
516 '#description' => t('This option indicates whether existing terms with the same name should be updated or ignored. If ignored, duplicates may be created.'),
517 '#prefix' => '<div id="help_flat">',
518 '#suffix' => '</div>',
519 );
520 $form['import_options']['help_tree_structure'] = array(
521 '#type' => 'item',
522 '#value' => t('Additional help:') .' '. t('Tree structure'),
523 '#description' => t('This option indicates whether and how existing terms with the same name should be updated or ignored.<br />
524 This option is used with last term of the line.') .'<br />'.
525 t('<ul>
526 <li><em>"Update and replace"</em>: each parent replaces eventual older ones.</li>
527 <li><em>"Ignore and create"</em>: child is always created and eventually its parents if they don\'t exist.</li>
528 <li><em>"Ignore and create all"</em>: Child and its parents are always created, even if they already exist. Duplicates may be created.</li>
529 </ul>'
530 ),
531 '#prefix' => '<div id="help_tree_structure">',
532 '#suffix' => '</div>',
533 );
534 $form['import_options']['help_polyhierarchy'] = array(
535 '#type' => 'item',
536 '#value' => t('Additional help:') .' '. t('Polyhierarchy'),
537 '#description' => t('This option indicates whether and how existing terms with the same name should be updated or ignored.') .'<br />'.
538 t('By nature, only one option can be chosen with this format.') .'<br />'.
539 t('<ul>
540 <li><em>"Update and merge"</em>: each child and parents are merged with old ones, except if the child has the same name than parent, in which case a new term is created, because a child cannot be a parent of itself. Warning: on next lines, direct children of this term name will be attached to the first imported term.</li>
541 </ul>'
542 ),
543 '#prefix' => '<div id="help_polyhierarchy">',
544 '#suffix' => '</div>',
545 );
546 $form['import_options']['help_parents'] = array(
547 '#type' => 'item',
548 '#value' => t('Additional help:') .' '. t('First level parents of a list of terms'),
549 '#description' => t('This option indicates whether and how existing terms with the same name should be updated or ignored.') .'<br />'.
550 t('<ul>
551 <li><em>"Update and merge"</em>: each child and parents are merged with old ones. No duplicate are created.</li>
552 <li><em>"Update and replace"</em>: each parent replaces eventual older ones.</li>
553 <li><em>"Ignore and create"</em>: child is always created and eventually its parents if they don\'t exist.</li>
554 <li><em>"Ignore and create all"</em>: Child and its parents are always created, even if they already exist. Duplicates may be created.</li>
555 </ul>'
556 ),
557 '#prefix' => '<div id="help_parents">',
558 '#suffix' => '</div>',
559 );
560 $form['import_options']['help_children'] = array(
561 '#type' => 'item',
562 '#value' => t('Additional help:') .' '. t('First level children of a list of terms'),
563 '#description' => t('This option indicates whether and how existing terms with the same name should be updated or ignored.') .'<br />'.
564 t('<ul>
565 <li><em>"Update and merge"</em>: each child and parents are merged with old ones.</li>
566 <li><em>"Update and replace"</em>: each parent replaces eventual older ones.</li>
567 <li><em>"Ignore and create"</em>: child is always created and eventually its parents if they don\'t exist.</li>
568 <li><em>"Ignore and create all"</em>: Child and its parents are always created, even if they already exist. Duplicates may be created.</li>
569 </ul>'
570 ),
571 '#prefix' => '<div id="help_children">',
572 '#suffix' => '</div>',
573 );
574 $form['import_options']['help_relations'] = array(
575 '#type' => 'item',
576 '#value' => t('Additional help:') .' '. t('Related terms'),
577 '#description' => t('This option indicates whether existing terms with the same name should be updated or ignored.
578 <p>For example, if existing related terms of term < <code>Drupal</code> > are < <code>Free</code> > and < <code>Open source</code> > and an imported line in the csv file is < <code>"Drupal","Knowledge management","Free"</code> >, then:') .'<br >'.
579 t('<ul>
580 <li><em>"Update and merge"</em> choice makes related terms of < <code>Drupal</code> > are now < <code>Free</code> >, < <code>Open source</code> > and < <code>Knowledge management</code> >;</li>
581 <li><em>"Update and replace"</em> choice makes related terms of < <code>Drupal</code> > are now < <code>Knowledge management</code> > and < <code>Free</code> >;</li>
582 <li><em>"Ignore and create"</em> choice makes two < <code>Drupal</code> > terms, one with existing related and other items and another one with the imported related terms < <code>Knowledge management</code> > and < <code>Free</code> >, which one has not been duplicated;</li>
583 <li><em>"Ignore and create all"</em> choice makes two < <code>Drupal</code> > as previously, but create too related term < <code>Free</code> > even if it exist.</li>
584 </ul></p>'
585 ),
586 '#prefix' => '<div id="help_relations">',
587 '#suffix' => '</div>',
588 );
589 $form['import_options']['help_fields'] = array(
590 '#type' => 'item',
591 '#value' => t('Additional help:') .' '. t('Full term definition'),
592 '#description' => t('This option indicates whether existing terms with the same name should be updated or ignored. If ignored, duplicates may be created.') .'<br />'.
593 t('<ul>
594 <li><em>"Update and merge"</em>: update term or create it if not exists and merge eventual description with new one.</li>
595 <li><em>"Update and replace"</em>: update term or create it if not exists and replace eventual description with new one.</li>
596 <li><em>"Ignore and create"</em>: term is always created.</li>
597 </ul>'
598 ),
599 '#prefix' => '<div id="help_fields">',
600 '#suffix' => '</div>',
601 );
602 $form['import_options']['help_descriptions'] = array(
603 '#type' => 'item',
604 '#value' => t('Additional help:') .' '. t('Descriptions'),
605 '#description' => t('This option indicates whether and how existing terms with the same name should be updated or ignored.') .'<br />'.
606 t('<ul>
607 <li><em>"Update and merge"</em>: update term or create it if not exists and merge eventual description with new one.</li>
608 <li><em>"Update and replace"</em>: update term or create it if not exists and replace eventual description with new one.</li>
609 <li><em>"Ignore and create"</em>: term is always created.</li>
610 </ul>'
611 ),
612 '#prefix' => '<div id="help_descriptions">',
613 '#suffix' => '</div>',
614 );
615 $form['import_options']['help_weights'] = array(
616 '#type' => 'item',
617 '#value' => t('Additional help:') .' '. t('Weights'),
618 '#description' => t('This option indicates whether and how existing terms with the same name should be updated or ignored.'),
619 '#prefix' => '<div id="help_weights">',
620 '#suffix' => '</div>',
621 );
622 $form['import_options']['help_synonyms'] = array(
623 '#type' => 'item',
624 '#value' => t('Additional help:') .' '. t('Synonyms'),
625 '#description' => t('This option indicates whether and how existing terms with the same name should be updated or ignored.') .'<br />'.
626 t('<ul>
627 <li><em>"Update and merge"</em>: update term or create it if not exists and merge eventual synonyms with new ones. Always remove duplicate synonyms.</li>
628 <li><em>"Update and replace"</em>: update term or create it if not exists and replace eventual synonyms with new ones.</li>
629 <li><em>"Ignore and create"</em>: term is always created.</li>
630 </ul>'
631 ),
632 '#prefix' => '<div id="help_synonyms">',
633 '#suffix' => '</div>',
634 );
635 $form['import_options']['help_taxonomy_manager'] = array(
636 '#type' => 'item',
637 '#value' => t('Additional help:') .' '. t('Taxonomy manager'),
638 '#description' => t("When a vocabulary is imported in an existing one, only third option (ignore existing terms) can be used.") .'<br />'.
639 t('This option indicates whether and how existing terms with the same name should be updated or ignored.') .'<br />'.
640 t('<ul>
641 <li><em>"Update and merge"</em>: update term or create it if not exists and merge eventual parents with new ones.</li>
642 <li><em>"Update and replace"</em>: update term or create it if not exists and replace eventual parents with new ones.</li>
643 <li><em>"Ignore and create"</em>: term is always created.</li>
644 </ul>'
645 ),
646 '#prefix' => '<div id="help_taxonomy_manager">',
647 '#suffix' => '</div>',
648 );
649 }
650 else {
651 // Use this form only if no javascript (or, in a next evolution, in a second step wizard).
652 $form['import_options']['#description'] = '<br />'. t("As you see this notice, javascript is not activated on your browser. Only options matching your source content and vocabulary destination needs to be set. Others won't be used. If you want specific examples and options, activate javascript or see <a href=\"!more_help_link\"> advanced help</a>.", array('!more_help_link' => url('admin/help/taxonomy_csv')));
653
654 $form['import_options']['existing_items']['#options'] = array_intersect_key($list_import_option, array_flip(array(
655 TAXONOMY_CSV_EXISTING_UPDATE,
656 TAXONOMY_CSV_EXISTING_UPDATE_MERGE,
657 TAXONOMY_CSV_EXISTING_UPDATE_REPLACE,
658 TAXONOMY_CSV_EXISTING_IGNORE,
659 TAXONOMY_CSV_EXISTING_IGNORE_CREATE,
660 TAXONOMY_CSV_EXISTING_IGNORE_ALL,
661 )));
662 }
663
664 // Specific options to import relations.
665 $form['import_options']['relations'] = array(
666 '#type' => 'fieldset',
667 '#title' => t('Specific settings of:') .' '. t('Related terms'),
668 '#collapsible' => TRUE,
669 '#collapsed' => FALSE,
670 '#description' => t('Set these options only if you import:') .' '. t('Related terms') .'.',
671 '#attributes' => array('id' => 'edit-relations'),
672 );
673 $form['import_options']['relations']['relations_create_subrelations'] = array(
674 '#type' => 'checkbox',
675 '#title' => t('Import subrelations'),
676 '#default_value' => $list_previous_values['relations_create_subrelations'],
677 '#description' => t('This checkbox allows to import subrelations of related terms and not only relations of first column term with others.
678 <p>For example, with the line < <code>"Paris","London","Bern","Roma"</code> >, default import is to make a link between < <code>Paris</code> > and each of three terms. There is no link between < <code>London</code> > and < <code>Bern</code> > neither < <code>Roma</code> >. Checking this option creates not only relations with first term, but all subrelations too: < <code>London</code> > and < <code>Bern</code> >, < <code>London</code> > and < <code>Roma</code> > and finally < <code>Bern</code> > and < <code>Roma</code> >.</p>'),
679 );
680 // Internal use only.
681 $form['import_options']['relations']['relations_all_vocabularies'] = array(
682 '#type' => 'value',
683 '#title' => t('Make relations with existing terms of all vocabularies'),
684 '#default_value' => $list_previous_values['relations_all_vocabularies'],
685 '#description' => t("This checkbox allows to create relations with existing terms in other vocabularies if they don't exist in selected vocabulary."),
686 '#disabled' => TRUE,
687 );
688
689 $form['advanced_options'] = array(
690 '#type' => 'fieldset',
691 '#title' => t('5. Advanced options'),
692 '#collapsible' => TRUE,
693 '#collapsed' => FALSE,
694 '#attributes' => array('id' => 'advanced_options'),
695 );
696
697 $form['advanced_options']['tweaks'] = array(
698 '#type' => 'fieldset',
699 '#title' => t('Tweaks for big or specific vocabularies'),
700 '#collapsible' => TRUE,
701 '#collapsed' => (
702 ($list_previous_values['disable_internal_cache'] == $list_recommended_values['disable_internal_cache'])
703 && ($list_previous_values['disable_hierarchy_check'] == $list_recommended_values['disable_hierarchy_check'])
704 && ($list_previous_values['disable_line_checks'] == $list_recommended_values['disable_line_checks'])
705 && ($list_previous_values['disable_utf8_check'] == $list_recommended_values['disable_utf8_check'])
706 ),
707 );
708
709 $form['advanced_options']['tweaks']['disable_internal_cache'] = array(
710 '#type' => 'checkbox',
711 '#title' => t('Disable internal cache'),
712 '#default_value' => $list_previous_values['disable_internal_cache'],
713 '#description' => t("To disable internal cache allows to import vocabularies of any size. Internal cache is used to speed up process, to reduce access to sql base an to be informed about process. When disabled, no information about results can be displayed except eventual first error or warning.<br />
714 It's recommended to disable cache if the imported vocabulary is too big (from 1000 or 10000 lines depending on the server), because it avoids memory congestion on server."),
715 );
716
717 $form['advanced_options']['tweaks']['disable_hierarchy_check'] = array(
718 '#type' => 'checkbox',
719 '#title' => t('Manually set vocabulary hierarchy'),
720 '#default_value' => $list_previous_values['disable_hierarchy_check'],
721 );
722 $form['advanced_options']['tweaks']['hierarchy_level'] = array(
723 '#type' => 'radios',
724 '#title' => '',
725 '#options' => _taxonomy_csv_info_lists('hierarchy_text'),
726 '#default_value' => $list_previous_values['hierarchy_level'],
727 '#prefix' => '<div id="hierarchy_level">',
728 '#suffix' => '</div>',
729 );
730 $form['advanced_options']['tweaks']['vocabulary_hierarchy_info'] = array(
731 '#type' => 'item',
732 '#value' => '',
733 '#description' => t('Because to calculate vocabulary hierarchy is memory intensive, this option allows to set hierarchy manually without verify it.'),
734 );
735
736 $form['advanced_options']['tweaks']['disable_line_checks'] = array(
737 '#type' => 'checkbox',
738 '#title' => t('Disable line checks'),
739 '#default_value' => $list_previous_values['disable_line_checks'],
740 '#description' => t('If you are sure that vocabulary to import is well formated (utf8, order of items...), you can disable checks.'),
741 );
742
743 $form['advanced_options']['tweaks']['disable_utf8_check'] = array(
744 '#type' => 'checkbox',
745 '#title' => t('Disable file conversion to UTF-8'),
746 '#description' => t('This checkbox allows to disable convert to UTF-8, what can resolve problems with some rare server configurations. Be sure your file is UTF-8 encoded when disabling this option. This option is not used with a textarea import.'),
747 );
748 if (function_exists('mb_detect_encoding')) {
749 $form['advanced_options']['tweaks']['disable_utf8_check']['#default_value'] = $list_previous_values['disable_utf8_check'];
750 }
751 else {
752 $form['advanced_options']['tweaks']['disable_utf8_check']['#default_value'] = TRUE;
753 $form['advanced_options']['tweaks']['disable_utf8_check']['#disabled'] = TRUE;
754 $form['advanced_options']['tweaks']['disable_utf8_check']['#description'] .= '<br />'. t('This checkbox is currently disabled, because iconv, GNU recode or mbstring for PHP are not installed on your server.');
755 }
756
757 $form['advanced_options']['result_display'] = array(
758 '#type' => 'fieldset',
759 '#title' => t('Results informations to display'),
760 '#collapsible' => TRUE,
761 '#collapsed' => (
762 ($list_previous_values['result_stats'] === $list_recommended_values['result_stats'])
763 && ($list_previous_values['result_terms'] === $list_recommended_values['result_terms'])
764 && ($list_previous_values['result_level'] == $list_recommended_values['result_level'])
765 && ($list_previous_values['result_type'] == $list_recommended_values['result_type'])
766 ),
767 );
768
769 $form['advanced_options']['result_display']['result_display_cache'] = array(
770 '#type' => 'item',
771 '#description' => t('Except first warning, no information can be displayed when internal cache is disabled.'),
772 '#prefix' => '<div id="result_display_cache">',
773 '#suffix' => '</div>',
774 );
775
776 $form['advanced_options']['result_display']['result_choices'] = array(
777 '#type' => 'checkboxes',
778 '#options' => array(
779 'result_stats' => t('Basic stats on imported terms'),
780 'result_terms' => t('List of imported terms'),
781 ),
782 '#default_value' => array(
783 $list_previous_values['result_stats'],
784 $list_previous_values['result_terms'],
785 ),
786 '#prefix' => '<div id="result_display_options">',
787 );
788
789 $form['advanced_options']['result_display']['result_level'] = array(
790 '#type' => 'radios',
791 '#title' => t('Log level'),
792 '#options' => array(
793 'none' => t('Only first warning'),
794 'warnings' => t('Warnings'),
795 'notices' => t('Warnings and notices'),
796 'infos' => t('Warnings, notices and informations'),
797 // 'full' => t('Errors, warnings, notices and informations for each term'),
798 ),
799 '#default_value' => $list_previous_values['result_level'],
800 );
801
802 $form['advanced_options']['result_display']['result_type'] = array(
803 '#type' => 'radios',
804 '#title' => t('Group warnings'),
805 '#options' => array(
806 'by_message' => t('By message (compact view)'),
807 'by_line' => t('By line (list view)'),
808 // 'by_collapse' => t('Group warnings and notices by line (collapsible view)'),
809 ),
810 '#default_value' => $list_previous_values['result_type'],
811 '#prefix' => '<div id="result_type">',
812 '#suffix' => '</div>',
813 );
814
815 $form['advanced_options']['result_display']['result_info'] = array(
816 '#type' => 'item',
817 '#description' => t('Warning: display warnings, notices and informations, especially by line, can help you to detect issues when submitted list of terms is not clean, but it may be memory intensive.'),
818 '#suffix' => '</div>',
819 );
820
821 $form['import_submit'] = array(
822 '#type' => 'submit',
823 '#value' => t('Import'),
824 );
825
826 $form['recommended_values_submit'] = array(
827 '#type' => 'submit',
828 '#value' => t('Default values'),
829 '#validate' => array('_taxonomy_csv_form_recommended_values'),
830 );
831
832 return $form;
833 }
834
835 /**
836 * Handles CSV import form validation.
837 *
838 * @see taxonomy_csv_form_import()
839 */
840 function taxonomy_csv_form_import_validate($form, &$form_state) {
841 $options = &$form_state['values'];
842
843 // First, simplify values to be compatible with Api.
844
845 // Load source local file. Check is made by Api.
846 // 'url' and 'text' are loaded and checked by Api.
847 if ($options['source_choice'] == 'path') {
848 $options['file'] = file_save_upload('path');
849 }
850 // Clean textarea in order to decrease memory usage.
851 if ($options['source_choice'] != 'text') {
852 $options['text'] = '';
853 }
854
855 // Define true delimiter.
856 $delimiter = array(
857 'comma' => ',',
858 'semicolon' => ';',
859 'tabulation' => "\t",
860 'space' => ' ',
861 'currency_sign' => '¤',
862 'custom_delimiter' => $options['import_delimiter_custom'],
863 );
864 $options['delimiter'] = $delimiter[$options['import_delimiter']];
865
866 // Define true enclosure.
867 $enclosure = array(
868 'none' => '',
869 'quotation' => '"',
870 'custom_enclosure' => $options['import_enclosure_custom'],
871 );
872 $options['enclosure'] = $enclosure[$options['import_enclosure']];
873
874 // Define result preferences.
875 foreach ($options['result_choices'] as $key => $value) {
876 $options[$key] = $value;
877 }
878
879 // Second, make API checks and eventually update options by reference.
880 $messages = _taxonomy_csv_vocabulary_import_check_options($options);
881
882 // Non API checks.
883 if (($options['import_delimiter'] == 'custom_delimiter')
884 && (empty($options['import_delimiter_custom']))) {
885 $messages['import_delimiter_custom'] = t('You choose to use a custom delimiter, but your delimiter is empty.');
886 }
887
888 if (($options['import_enclosure'] == 'custom_enclosure')
889 && (empty($options['import_enclosure_custom']))) {
890 $messages['import_enclosure_custom'] = t('You choose to use a custom enclosure, but your enclosure is empty.');
891 }
892
893 if (($options['import_delimiter'] == 'custom_delimiter')
894 && (drupal_strlen($options['import_delimiter_custom']) > 1)) {
895 $messages['import_delimiter_custom'] = t('Delimiter should have only one character.');
896 }
897 if (($options['import_enclosure'] == 'custom_enclosure')
898 && (drupal_strlen($options['import_enclosure_custom']) > 1)) {
899 $messages['import_enclosure_custom'] = t('Enclosure should have only zero or one character.');
900 }
901
902 // Validate form.
903 foreach ($messages as $item => $message) {
904 if (in_array($item, $options)) {
905 form_set_error($item, $message);
906 }
907 else {
908 drupal_set_message($message, 'error');
909 }
910 }
911 }
912
913 /**
914 * Handles CSV import form submission and launch batch set.
915 *
916 * @see taxonomy_csv_form_import()
917 */
918 function taxonomy_csv_form_import_submit($form, &$form_state) {
919 // Remember last preferences and prepare only options to be sent to Api.
920 foreach (array(
921 'import_format',
922 'source_choice',
923 'import_delimiter',
924 'import_delimiter_custom',
925 'import_enclosure',
926 'import_enclosure_custom',
927 'vocabulary_target',
928 'vocabulary_id',
929 'existing_items',
930 'relations_create_subrelations',
931 'relations_all_vocabularies',
932 'disable_internal_cache',
933 'disable_hierarchy_check',
934 'hierarchy_level',
935 'disable_line_checks',
936 'disable_utf8_check',
937 'result_stats',
938 'result_terms',
939 'result_level',
940 'result_type',
941 ) as $option) {
942 variable_set("taxonomy_csv_$option", $form_state['values'][$option]);
943 $options[$option] = $form_state['values'][$option];
944 }
945 // Finish to prepare $options. Unset useless options for api.
946 $options['internal_cache'] = !$options['disable_internal_cache'];
947 $options['hierarchy_check'] = !$options['disable_hierarchy_check'];
948 $options['line_checks'] = !$options['disable_line_checks'];
949 $options['utf8_check'] = !$options['disable_utf8_check'];
950 unset($options['disable_internal_cache']);
951 unset($options['disable_hierarchy_check']);
952 unset($options['disable_line_checks']);
953 unset($options['disable_utf8_check']);
954 $options['delimiter'] = $form_state['values']['delimiter'];
955 $options['enclosure'] = $form_state['values']['enclosure'];
956 unset($options['import_delimiter']);
957 unset($options['import_delimiter_custom']);
958 unset($options['import_enclosure']);
959 unset($options['import_enclosure_custom']);
960 $options['file'] = $form_state['values']['file'];
961 if ($options['source_choice'] == 'text') {
962 $options['text'] = &$form_state['values']['text'];
963 unset($form_state['values']['text']);
964 }
965 $options['path'] = $form_state['values']['path'];
966 $options['url'] = $form_state['values']['url'];
967
968 // Prepares process batch (will be automatically processed when returns).
969 taxonomy_csv_vocabulary_import($options);
970
971 // End of form process. Reinitialize choices.
972 unset($form_state['values']);
973 unset($form_state['storage']);
974 $form_state['rebuild'] = TRUE;
975 }
976
977 /**
978 * Menu callback of the main export form.
979 */
980 function taxonomy_csv_form_export_prepare() {
981 // Invoke taxonomy_csv api (defines and functions).
982 $taxonomy_csv_path = drupal_get_path('module', 'taxonomy_csv');
983 require_once("$taxonomy_csv_path/taxonomy_csv.api.inc");
984
985 // Javascript and css allow to show only available options depending user's choice.
986 drupal_add_js("$taxonomy_csv_path/taxonomy_csv.js");
987 drupal_add_css("$taxonomy_csv_path/taxonomy_csv.css");
988
989 return drupal_get_form('taxonomy_csv_form_export');
990 }
991
992 /**
993 * Generates the taxonomy CSV export form.
994 *
995 * Form contain three fieldsets:
996 * - 1. How to export (format of csv file) ?
997 * - 2. Which vocabulary to export ?
998 * - 3. How to export ?
999 * 1. Csv delimiter
1000 * 2. Csv enclosure
1001 * 3. Csv end of line
1002 *
1003 * @ingroup forms
1004 * @see taxonomy_csv_form_export_validate()
1005 * @see taxonomy_csv_form_export_submit()
1006 */
1007 function taxonomy_csv_form_export($form_state) {
1008 // Display main export form
1009 $list_recommended_values = array(
1010 'export_format' => TAXONOMY_CSV_FORMAT_ALONE_TERMS,
1011 'export_delimiter' => 'comma',
1012 'export_delimiter_custom' => '',
1013 'export_enclosure' => 'none',
1014 'export_enclosure_custom' => '',
1015 'export_line_ending' => 'Unix',
1016 'export_order' => 'name',
1017 'fields_links_terms_ids' => 'name_if_needed',
1018 'fields_links_vocabularies_ids' => 'none',
1019 );
1020
1021 // Remember previous values to use in particular when reloading form.
1022 // If not reloading form, then use previous saved value if exists, else recommended value.
1023 $list_previous_values = array();
1024 foreach ($list_recommended_values as $key => $value) {
1025 $list_previous_values[$key] = isset($form_state['values'][$key]) ?
1026 $form_state['values'][$key] :
1027 variable_get("taxonomy_csv_{$key}", $value);
1028 }
1029
1030 $list_export_format = _taxonomy_csv_info_lists('list_export_format');
1031
1032 $list_export_delimiter = array(
1033 'comma' => t('« , » (Comma)'),
1034 'semicolon' => t('« ; » (Semicolon)'),
1035 'tabulation' => t('« » (Tabulation)'),
1036 'space' => t('« » (Space)'),
1037 'currency_sign' => t('« ¤ » (Currency sign)'),
1038 'custom_delimiter' => t('Custom delimiter'),
1039 );
1040
1041 $list_export_enclosure = array(
1042 'none' => t('None'),
1043 'quotation' => t('« " » (Quotation mark)'),
1044 'custom_enclosure' => t('Custom enclosure'),
1045 );
1046
1047 $list_export_line_ending = array(
1048 'Unix' => t('Linux / Unix'),
1049 'Mac' => t('Mac'),
1050 'Microsoft DOS' => t('Microsoft DOS'),
1051 );
1052
1053 $list_export_order = array(
1054 'name' => t('Alphabetic order'),
1055 'tid' => t('Internal order'),
1056 'weight' => t('Weight'),
1057 );
1058
1059 // Build form.
1060 $form = array(
1061 '#attributes' => array(
1062 'enctype' => 'multipart/form-data',
1063 )
1064 );
1065
1066 $list_vocabularies = taxonomy_get_vocabularies();
1067
1068 if (count($list_vocabularies) == 0) {
1069 $form['info'] = array(
1070 '#type' => 'item',
1071 '#value' => t("As there isn't any vocabulary, nothing can be exported..."),
1072 );
1073
1074 return $form;
1075 }
1076 // Else there are vocabularies.
1077
1078 // Used with recommended values button.
1079 $form['list']['list_recommended_values'] = array(
1080 '#type' => 'value',
1081 '#value' => $list_recommended_values,
1082 );
1083
1084 $form['format'] = array(
1085 '#type' => 'fieldset',
1086 '#title' => t('1. What do you want to export?'),
1087 '#collapsible' => TRUE,
1088 '#collapsed' => FALSE,
1089 );
1090
1091 $form['format']['export_format'] = array(
1092 '#type' => 'select',
1093 '#title' => '',
1094 '#options' => $list_export_format,
1095 '#default_value' => $list_previous_values['export_format'],
1096 '#required' => TRUE,
1097 );
1098
1099 $form['format']['info'] = array(
1100 '#type' => 'item',
1101 '#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 />'.
1102 t('Only "fields and links" format manages duplicate term names. In all case, you will be notified if a duplicate is found.'),
1103 );
1104
1105