Projet

Général

Profil

Paste
Télécharger (9,69 ko) Statistiques
| Branche: | Révision:

root / drupal7 / sites / all / modules / node_export / formats / dsv.inc @ cb17e347

1
<?php
2

    
3
/**
4
 * @file
5
 * The Node export DSV format handler.
6
 *
7
 * Adds configurable DSV format to Node export.
8
 */
9

    
10
/**
11
 * Settings callback.
12
 */
13
function node_export_dsv_settings($form, $form_state) {
14
  $settings['dsv'] = array(
15
    '#type' => 'fieldset',
16
    '#title' => t('DSV format settings'),
17
    '#description' => t(
18
     'Select how your DSV output will be formatted - this must be configured the
19
     same on both sites.  By default this is configured to RFC4180 CSV format
20
     where the delimiter is a comma (,), the enclosure is a double-quote ("),
21
     and the seperator is CRLF (\r\n).  Not all configurations may be possible,
22
     use wisely.  Enclosure will only be used to escape values that contain any
23
     of the configured strings.  Additionally single-quotes will be used to
24
     escape values that are equivalent to reserved words (NULL, TRUE, FALSE).'
25
    ),
26
    '#collapsible' => TRUE,
27
    '#collapsed' => TRUE,
28
  );
29

    
30
  $settings['dsv']['node_export_dsv_delimiter'] = array(
31
    '#type' => 'textfield',
32
    '#title' => t('Value delimiter'),
33
    '#size' => 5,
34
    '#maxlength' => 255,
35
    '#default_value' => variable_get('node_export_dsv_delimiter', ','),
36
    '#required' => TRUE,
37
  );
38

    
39
  $settings['dsv']['node_export_dsv_enclosure'] = array(
40
    '#type' => 'textfield',
41
    '#title' => t('Escape enclosure'),
42
    '#size' => 5,
43
    '#maxlength' => 255,
44
    '#default_value' => variable_get('node_export_dsv_enclosure', '"'),
45
    '#required' => TRUE,
46
  );
47

    
48
  $settings['dsv']['node_export_dsv_seperator'] = array(
49
    '#type' => 'textfield',
50
    '#title' => t('Record seperator'),
51
    '#size' => 5,
52
    '#maxlength' => 255,
53
    '#default_value' => variable_get('node_export_dsv_seperator', '\r\n'),
54
    '#required' => TRUE,
55
  );
56

    
57
  $settings['dsv']['node_export_dsv_escape_eol'] = array(
58
    '#type' => 'checkbox',
59
    '#title' => t('Always escape values containing line breaks'),
60
    '#default_value' => variable_get('node_export_dsv_escape_eol', 1),
61
    '#description' => t('This is to overcome problems where Windows injects CRLF line breaks.'),
62
  );
63

    
64
  return $settings;
65
}
66

    
67
function node_export_dsv_string($string) {
68
  $replace = array(
69
   '\n' => "\n",
70
   '\r' => "\r",
71
   '\t' => "\t",
72
   '\v' => "\v",
73
   '\e' => "\e",
74
   '\f' => "\f",
75
  );
76
  return str_replace(array_keys($replace), array_values($replace), $string);
77
}
78

    
79
/**
80
 * Export callback.
81
 */
82
function node_export_dsv_export($nodes, $format) {
83
  $delimiter = node_export_dsv_string(variable_get('node_export_dsv_delimiter', ','));
84
  $enclosure = node_export_dsv_string(variable_get('node_export_dsv_enclosure', '"'));
85
  $seperator = node_export_dsv_string(variable_get('node_export_dsv_seperator', '\r\n'));
86
  $escape_eol = variable_get('node_export_dsv_escape_eol', 1);
87
  return node_export_dsv_encode($nodes, $delimiter, $enclosure, $seperator, $escape_eol);
88
}
89

    
90
/**
91
 * Build DSV string.
92
 */
93
function node_export_dsv_encode($nodes, $delimiter, $enclosure, $seperator, $escape_eol) {
94
  $encoded_nodes = array();
95
  $dsv_lines = array();
96

    
97
  $node_keys = array();
98
  foreach (array_keys($nodes) as $node_key) {
99
    $new_node_key = 'node_' . $node_key;
100
    $node_keys[] = $new_node_key;
101
    node_export_dsv_encode_node($encoded_nodes, $new_node_key, $nodes[$node_key]);
102
  }
103

    
104
  $dsv_lines['node_export_dsv_header'] = array_keys($encoded_nodes);
105

    
106
  foreach (array_keys($encoded_nodes) as $header_value) {
107
    $encoded_nodes[$header_value] = array_merge(array_fill_keys($node_keys, NULL), $encoded_nodes[$header_value]);
108
    foreach (array_keys($encoded_nodes[$header_value]) as $encoded_node_key) {
109
      $dsv_lines[$encoded_node_key][$header_value] = $encoded_nodes[$header_value][$encoded_node_key];
110
    }
111
  }
112

    
113
  return node_export_dsv_array_to_dsv($dsv_lines, $delimiter, $enclosure, $seperator, $escape_eol);
114
}
115

    
116
/**
117
 * Process a node and update $header and $encoded_nodes accordingly.
118
 */
119
function node_export_dsv_encode_node(&$encoded_nodes, $node_key, $var, $parent = NULL) {
120

    
121
  foreach ($var as $k => &$v) {
122

    
123
    // Get the new header value.
124
    $header_value = node_export_dsv_encode_header_value($parent, $var, $k);
125

    
126
    if (is_object($v) || is_array($v)) {
127
      // Recurse through the structure.
128
      node_export_dsv_encode_node($encoded_nodes, $node_key, $v, $header_value);
129
    }
130
    else {
131
      // Create a safe text version of this value and store it against the header using a safe key.
132
      $encoded_nodes[$header_value][$node_key] = node_export_dsv_encode_sanitize_value($v);
133
    }
134
  }
135
}
136

    
137
/**
138
 * Encode a value.
139
 */
140
function node_export_dsv_encode_sanitize_value($var) {
141
    if (is_numeric($var)) {
142
      return $var;
143
    }
144
    elseif (is_bool($var)) {
145
      return ($var ? 'TRUE' : 'FALSE');
146
    }
147
    elseif (is_null($var)) {
148
      return 'NULL';
149
    }
150
    elseif (is_string($var) && !empty($var)) {
151
      // Single-quote strings that could be confused for null or boolean.
152
      if (in_array(strtoupper($var), array('TRUE', 'FALSE', 'NULL'))) {
153
        $var = "'" . $var . "'";
154
      }
155

    
156
      return $var;
157
    }
158
    else {
159
      return '';
160
    }
161
}
162

    
163
/**
164
 * Decode a value.
165
 */
166
function node_export_dsv_decode_sanitize_value($var) {
167
  // Allow numeric, bool, and null values to pass right back as is.
168
  if (is_numeric($var) || is_bool($var) || is_null($var)) {
169
    return $var;
170
  }
171
  // Allow the special case strings back as is.
172
  elseif (in_array(strtoupper($var), array("'TRUE'", "'FALSE'", "'NULL'"))) {
173
    return $var;
174
  }
175
  // Assume this is a string.
176
  return "'" . str_replace("'", "\'", $var) . "'";
177
}
178

    
179
/**
180
 * Create header value from $parents, $var, and $k.
181
 */
182
function node_export_dsv_encode_header_value($parents, $var, $k) {
183
  if (is_null($parents)) {
184
    // Special case; on the first level do not prefix the key.
185
    $header_value = $k;
186
  }
187
  elseif (is_object($var)) {
188
    $header_value = $parents . "->" . $k;
189
  }
190
  elseif (is_array($var)) {
191
    $header_value = $parents . "['" . $k . "']";
192
  }
193
  return $header_value;
194
}
195

    
196
/**
197
 * Import callback.
198
 */
199
function node_export_dsv_import($code_string) {
200
  $delimiter = node_export_dsv_string(variable_get('node_export_dsv_delimiter', ','));
201
  $enclosure = node_export_dsv_string(variable_get('node_export_dsv_enclosure', '"'));
202
  $seperator = node_export_dsv_string(variable_get('node_export_dsv_seperator', '\r\n'));
203
  return node_export_dsv_decode($code_string, $delimiter, $enclosure, $seperator);
204
}
205

    
206
/**
207
 *  Interpret a DSV string.
208
 */
209
function node_export_dsv_decode($code_string, $delimiter, $enclosure, $seperator) {
210
  // Get array data from DSV.
211
  $array = @node_export_dsv_dsv_to_array($code_string, $delimiter, $enclosure, $seperator);
212

    
213
  // If the first two rows are of equal length, we can assume this is a DSV.
214
  // Also checks there are a decent number of fields.
215
  if (!empty($array[0]) && !empty($array[1]) && count($array[0]) > 10 && count($array[0]) == count($array[1])) {
216
    $nodes = array();
217

    
218
    // Assume row 0 is the header, and the rest of the rows are the nodes.
219
    $header = array_shift($array);
220

    
221
    // Build the nodes.
222
    foreach ($array as &$row) {
223
      $node = (object)array();
224
      foreach ($row as $key => $item) {
225
        $item = node_export_dsv_decode_sanitize_value($item);
226
        eval('$node->' . $header[$key] . ' = ' . $item . ';');
227
      }
228
      $nodes[] = $node;
229
    }
230

    
231
    return $nodes;
232
  }
233
}
234

    
235
/**
236
 *  Encode DSV.
237
 */
238
function node_export_dsv_array_to_dsv($array, $delimiter, $enclosure, $seperator, $escape_eol) {
239
  $lines = array();
240
  foreach ($array as $line) {
241
    $out_item = array();
242
    foreach ($line as $item) {
243
      if (stripos($item, $enclosure) !== FALSE) {
244
        $item = str_replace($enclosure, $enclosure . $enclosure, $item);
245
      }
246
      if (
247
        (stripos($item, $delimiter) !== FALSE)
248
        || (stripos($item, $enclosure) !== FALSE)
249
        || (stripos($item, $seperator) !== FALSE)
250
        || ($escape_eol && stripos($item, "\n") !== FALSE)
251
      ) {
252
        $item = $enclosure . $item . $enclosure;
253
      }
254
      $out_item[] = $item;
255
    }
256
    $lines[] = implode($delimiter, $out_item);
257
  }
258
  return implode($seperator, $lines);
259
}
260

    
261
/**
262
 *  Decode DSV.
263
 */
264
function node_export_dsv_dsv_to_array($string, $delimiter, $enclosure, $seperator) {
265
  $lines = array();
266
  $out_item = array();
267
  $count = strlen($string);
268
  $escape = FALSE;
269
  $double_escape = FALSE;
270
  $position = 0;
271
  $i = 0;
272
  $seperators = str_split($seperator);
273

    
274
  while ($i < $count) {
275
    $c = $string[$i];
276

    
277
    // Determine whether this is an EOL.
278
    $is_eol = TRUE;
279
    for ($j = 0; $j < count($seperators); $j++) {
280
      if (!isset($string[$i + $j]) || $string[$i + $j] != $seperators[$j]) {
281
        $is_eol = FALSE;
282
        break;
283
      }
284
    }
285

    
286
    if ($is_eol) {
287
      if ($escape) {
288
        $out_item[$position] .= $c;
289
      }
290
      else {
291
        $i += count($seperators);
292
        $lines[] = $out_item;
293
        $out_item = array();
294
        $position = 0;
295
        continue;
296
      }
297
    }
298
    elseif ($c == $delimiter) {
299
      if ($escape) {
300
        $out_item[$position] .= $c;
301
      }
302
      else {
303
        if ($string[$i - 1] == $delimiter) {
304
          $out_item[$position] .= '';
305
        }
306
        $position++;
307
        $escape = FALSE;
308
        $double_escape = FALSE;
309
      }
310
    }
311
    elseif ($c == $enclosure) {
312
      if ($double_escape) {
313
        $out_item[$position] .= $enclosure;
314
        $double_escape = FALSE;
315
      }
316
      if ($escape) {
317
        $escape = FALSE;
318
        $double_escape = TRUE;
319
      }
320
      else {
321
        $escape = TRUE;
322
        $double_escape = FALSE;
323
      }
324
    }
325
    else {
326
      if ($double_escape) {
327
        $out_item[$position] .= $enclosure;
328
        $double_escape = FALSE;
329
      }
330
      $out_item[$position] .= $c;
331
    }
332
    $i++;
333
  }
334
  if (!empty($out_item)) {
335
    $lines[] = $out_item;
336
  }
337
  return $lines;
338
}
339

    
340
/**
341
 * Callback for actions.
342
 */
343
function node_export_dsv_action_form($context, &$form_state) {
344
  return node_export_action_form($context, $form_state, 'dsv');
345
}