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

Contents of /contributions/modules/uc_edi/uc_edi.module

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


Revision 1.1 - (show annotations) (download) (as text)
Thu May 22 19:16:54 2008 UTC (18 months ago) by rszrama
Branch: MAIN
CVS Tags: DRUPAL-5--1-0, HEAD
Branch point for: DRUPAL-5
File MIME type: text/x-php
Initial upload of the Ubercart EDI module.  Allows for exporting orders on a cron run according to a set pattern.  These files are then passed onto a fulfillment house for orders to be shipped.  Can also process receipt files to act on orders once the fulfillment house has processed them.
1 <?php
2 // $Id$
3
4 /**
5 * @file
6 * EDI order import and export module, defaulting to tab delimited files.
7 *
8 * This module only interfaces with the Ubercart e-commerce suite:
9 * http://www.ubercart.org
10 */
11
12 /*******************************************************************************
13 * Hook Functions (Drupal)
14 ******************************************************************************/
15
16 /**
17 * Implementation of hook_menu().
18 */
19 function uc_edi_menu($may_cache) {
20 if ($may_cache) {
21 $items[] = array(
22 'path' => 'admin/store/settings/edi',
23 'title' => t('EDI import/export'),
24 'description' => t('Adjust the settings for EDI import and export.'),
25 'callback' => 'drupal_get_form',
26 'callback arguments' => array('uc_edi_settings_form'),
27 'access' => user_access('administer edi orders'),
28 'type' => MENU_NORMAL_ITEM,
29 );
30 $items[] = array(
31 'path' => 'admin/store/settings/edi/help',
32 'title' => t('EDI help topics'),
33 'description' => t('Find information on certain parts of the EDI module.'),
34 'callback' => 'uc_edi_admin_help',
35 'access' => user_access('administer edi orders'),
36 'type' => MENU_CALLBACK,
37 );
38
39 $items[] = array(
40 'path' => 'admin/store/orders/edi',
41 'title' => t('EDI import/export'),
42 'description' => t('Manually import or export an order EDI file.'),
43 'callback' => 'uc_edi_order_admin',
44 'access' => user_access('administer edi orders'),
45 'type' => MENU_NORMAL_ITEM,
46 );
47 $items[] = array(
48 'path' => 'admin/store/orders/edi/download',
49 'title' => t('EDI file download'),
50 'description' => t('Download and archived exported order EDI files.'),
51 'callback' => 'uc_edi_export_download',
52 'access' => user_access('download edi orders'),
53 'type' => MENU_NORMAL_ITEM,
54 );
55 }
56 else{
57 $items[] = array(
58 'path' => 'admin/store/orders/edi/download/file/'. arg(6),
59 'callback' => 'uc_edi_download_file',
60 'callback arguments' => array(arg(6)),
61 'access' => user_access('download edi orders'),
62 'type' => MENU_CALLBACK,
63 );
64 $items[] = array(
65 'path' => 'admin/store/orders/edi/download/archive/'. arg(6),
66 'callback' => 'uc_edi_archive_file',
67 'callback arguments' => array(arg(6)),
68 'access' => user_access('download edi orders'),
69 'type' => MENU_CALLBACK,
70 );
71 }
72
73 return $items;
74 }
75
76 /**
77 * Implementation of hook_perm().
78 */
79 function uc_edi_perm() {
80 return array('administer edi orders', 'download edi orders');
81 }
82
83 /**
84 * Implementation of hook_cron().
85 */
86 function uc_edi_cron() {
87 // Decide if it's time to import orders.
88 if (variable_get('uc_edi_order_import_freq', '1 second') != 'never') {
89 $time = strtotime(variable_get('uc_edi_order_import_freq', '1 second') .' ago');
90 if (variable_get('uc_edi_last_order_import', 0) < $time) {
91 _import_orders();
92 }
93 }
94
95 // Decide if it's time to export orders.
96 if (variable_get('uc_edi_order_export_freq', '1 day')) {
97 $time = strtotime(variable_get('uc_edi_order_export_freq', '1 day') .' ago');
98 if (variable_get('uc_edi_last_order_export', 0) < $time) {
99 _export_orders();
100 }
101 }
102 }
103
104
105 /*******************************************************************************
106 * Hook Functions (Ubercart)
107 ******************************************************************************/
108
109 /**
110 * Implementation of hook_order_state().
111 */
112 function uc_edi_order_state() {
113 $states[] = array(
114 'id' => 'edi_processing',
115 'title' => t('EDI processing'),
116 'weight' => 15,
117 'scope' => 'general',
118 );
119
120 return $states;
121 }
122
123 /******************************************************************************
124 * Callback Functions and Forms
125 ******************************************************************************/
126
127 // Displays the settings form for all EDI related functions.
128 function uc_edi_settings_form() {
129 if ((trim(variable_get('uc_edi_order_import_dir', '')) == '' ||
130 trim(variable_get('uc_edi_order_import_archive_dir', '')) == '' ||
131 trim(variable_get('uc_edi_order_export_dir', '')) == '') &&
132 empty($_POST['form_id'])) {
133 drupal_set_message(t('One or more required directory fields need to be filled out. It is recommended that you use a directory outside of your document root for improved security. You may specify an absolute path on the server or a relative path from the Drupal directory.'), 'error');
134 }
135
136 $form['import'] = array(
137 '#type' => 'fieldset',
138 '#title' => t('Import settings'),
139 '#collapsible' => TRUE,
140 '#collapsed' => FALSE,
141 );
142 $form['import']['orders'] = array(
143 '#type' => 'fieldset',
144 '#title' => t('Order import settings'),
145 '#collapsible' => TRUE,
146 '#collapsed' => TRUE,
147 );
148 $form['import']['orders']['uc_edi_order_import_dir'] = array(
149 '#type' => 'textfield',
150 '#title' => t('Import directory'),
151 '#description' => t('The directory path to search for data files ready for import. Omit the trailing slash.'),
152 '#default_value' => variable_get('uc_edi_order_import_dir', ''),
153 );
154 $form['import']['orders']['uc_edi_order_import_archive_dir'] = array(
155 '#type' => 'textfield',
156 '#title' => t('Import archive directory'),
157 '#description' => t('The directory path to move processed data files to for storage. Omit the trailing slash.'),
158 '#default_value' => variable_get('uc_edi_order_import_archive_dir', ''),
159 );
160 $form['import']['orders']['uc_edi_order_import_extension'] = array(
161 '#type' => 'textfield',
162 '#title' => t('Import file extension'),
163 '#description' => t('Enter the file extension expected for order import files.'),
164 '#default_value' => variable_get('uc_edi_order_import_extension', 'edi'),
165 '#maxlength' => 6,
166 );
167 $form['import']['orders']['uc_edi_order_import_delimiter'] = array(
168 '#type' => 'select',
169 '#title' => t('Import pattern delimiter'),
170 '#options' => drupal_map_assoc(array('comma', 'pipe', 'tab')),
171 '#default_value' => variable_get('uc_edi_order_import_delimiter', 'tab'),
172 );
173 $form['import']['orders']['uc_edi_order_import_freq'] = array(
174 '#type' => 'select',
175 '#title' => t('Import frequency'),
176 '#description' => t('The frequency at which automatic imports should occur.'),
177 '#options' => array(
178 '1 second' => t('Every cron run'),
179 '1 hour' => t('Once an hour'),
180 '6 hours' => t('Every six hours'),
181 '12 hours' => t('Every twelve hours'),
182 '1 day' => t('Once a day'),
183 'never' => t('Never'),
184 ),
185 '#default_value' => variable_get('uc_edi_order_import_freq', '1 second'),
186 );
187 foreach (uc_order_status_list('general') as $status) {
188 $options[$status['id']] = $status['title'];
189 }
190 $form['import']['orders']['uc_edi_imported_order_status'] = array(
191 '#type' => 'select',
192 '#title' => t('Imported order status'),
193 '#description' => t('Select a status for orders to be moved to when a response is received for that order.'),
194 '#options' => $options,
195 '#default_value' => variable_get('uc_edi_imported_order_status', 'completed'),
196 );
197 $form['import']['orders']['uc_edi_order_import_rules'] = array(
198 '#type' => 'textarea',
199 '#title' => t('Order import rules'),
200 '#description' => t('Order import rules have set patterns and keywords. <a href="!url">Click here</a> for help.', array('!url' => url('admin/store/settings/edi/help'))),
201 '#default_value' => variable_get('uc_edi_order_import_rules', _default_order_import_rules()),
202 );
203
204 $form['export'] = array(
205 '#type' => 'fieldset',
206 '#title' => t('Export settings'),
207 '#collapsible' => TRUE,
208 '#collapsed' => FALSE,
209 );
210 $form['export']['orders'] = array(
211 '#type' => 'fieldset',
212 '#title' => t('Order export settings'),
213 '#collapsible' => TRUE,
214 '#collapsed' => TRUE,
215 );
216 $form['export']['orders']['uc_edi_order_export_dir'] = array(
217 '#type' => 'textfield',
218 '#title' => t('Export directory'),
219 '#description' => t('The directory path for exported data files. Omit the trailing slash.'),
220 '#default_value' => variable_get('uc_edi_order_export_dir', ''),
221 );
222 $form['export']['orders']['uc_edi_order_export_archive_dir'] = array(
223 '#type' => 'textfield',
224 '#title' => t('Export archive directory'),
225 '#description' => t('The directory path for archiving exported data files. Omit the trailing slash.'),
226 '#default_value' => variable_get('uc_edi_order_export_archive_dir', ''),
227 );
228 $form['export']['orders']['uc_edi_order_export_prefix'] = array(
229 '#type' => 'textfield',
230 '#title' => t('Export file prefix'),
231 '#description' => t('Enter a prefix to use for your exported order files. Leave blank for none.'),
232 '#default_value' => variable_get('uc_edi_order_export_prefix', 'export-'),
233 '#maxlength' => 10,
234 );
235 $form['export']['orders']['uc_edi_order_export_extension'] = array(
236 '#type' => 'textfield',
237 '#title' => t('Export file extension'),
238 '#description' => t('Enter the file extension to use for your exported order files.'),
239 '#default_value' => variable_get('uc_edi_order_export_extension', 'edi'),
240 '#maxlength' => 6,
241 );
242 $form['export']['orders']['uc_edi_order_export_freq'] = array(
243 '#type' => 'select',
244 '#title' => t('Export frequency'),
245 '#description' => t('The frequency at which automatic exports should occur.'),
246 '#options' => array(
247 '1 second' => t('Every cron run'),
248 '1 hour' => t('Once an hour'),
249 '6 hours' => t('Every six hours'),
250 '12 hours' => t('Every twelve hours'),
251 '1 day' => t('Once a day'),
252 'never' => t('Never'),
253 ),
254 '#default_value' => variable_get('uc_edi_order_export_freq', '1 day'),
255 );
256 foreach (uc_order_status_list('edi_processing') as $status) {
257 $options[$status['id']] = $status['title'];
258 }
259 $form['export']['orders']['uc_edi_export_order_status'] = array(
260 '#type' => 'select',
261 '#title' => t('Ready for export order status'),
262 '#description' => t('Select a status used to mark orders as ready for export.'),
263 '#options' => $options,
264 '#default_value' => variable_get('uc_edi_export_order_status', 'edi_export'),
265 );
266 $form['export']['orders']['uc_edi_exported_order_status'] = array(
267 '#type' => 'select',
268 '#title' => t('Exported order status'),
269 '#description' => t('Select a status used to mark orders that have been exported.'),
270 '#options' => $options,
271 '#default_value' => variable_get('uc_edi_exported_order_status', 'edi_pending'),
272 );
273 $form['export']['orders']['uc_edi_exported_order_message'] = array(
274 '#type' => 'textfield',
275 '#title' => t('Export order comment'),
276 '#description' => t('Enter a message displayed on orders when an order gets exported.'),
277 '#default_value' => variable_get('uc_edi_exported_order_message', '-'),
278 );
279 $form['export']['orders']['uc_edi_order_export_pattern'] = array(
280 '#type' => 'textarea',
281 '#title' => t('Order export pattern'),
282 '#description' => t('This is the pattern used for each order in the export file.<br />Separate values by commas and use any order field keyword, i.e. !delivery_first_name.<br />Use: !_ to add a line break, !products to add the products, !delivery_name, !billing_name.<br />Add (#) to any key where # is the maximum length you want the value to be.'),
283 '#default_value' => variable_get('uc_edi_order_export_pattern', _default_order_export_pattern()),
284 );
285 $form['export']['orders']['uc_edi_order_product_export_pattern'] = array(
286 '#type' => 'textarea',
287 '#title' => t('Order product export pattern'),
288 '#description' => t('This is the pattern used for each order product in the export file.<br />Separate values by commas and use any product field keyword, i.e. !qty.<br />Use: !_ to add a line break, !# for the incremented order line number.'),
289 '#default_value' => variable_get('uc_edi_order_product_export_pattern', _default_order_product_export_pattern()),
290 );
291 $form['export']['orders']['uc_edi_order_export_delimiter'] = array(
292 '#type' => 'select',
293 '#title' => t('Export pattern delimiter'),
294 '#options' => drupal_map_assoc(array('comma', 'pipe', 'tab', 'nothing')),
295 '#default_value' => variable_get('uc_edi_order_export_delimiter', 'tab'),
296 );
297 $form['export']['orders']['uc_edi_order_next_batch_id'] = array(
298 '#type' => 'textfield',
299 '#title' => t('Next order batch ID'),
300 '#description' => t('<b>DISABLED:</b> Adjusting this value may result in duplicate batch IDs. Adjustments must be made in the database.<br />The batch ID is incremented for every export and useful for tracking.'),
301 '#default_value' => variable_get('uc_edi_order_next_batch_id', 1000),
302 '#disabled' => TRUE,
303 );
304
305 return system_settings_form($form);
306 }
307
308 function uc_edi_settings_form_validate($form_id, $form_values) {
309 if (trim($form_values['uc_edi_order_import_dir']) != '' &&
310 !is_dir($form_values['uc_edi_order_import_dir'])) {
311 form_set_error('uc_edi_order_import_dir', t('You have specified a non-existent order import directory.'));
312 }
313 if (trim($form_values['uc_edi_order_archive_dir']) != '' &&
314 !is_dir($form_values['uc_edi_order_archive_dir'])) {
315 form_set_error('uc_edi_order_archive_dir', t('You have specified a non-existent order archive directory.'));
316 }
317 if (trim($form_values['uc_edi_order_export_dir']) != '' &&
318 !is_dir($form_values['uc_edi_order_export_dir'])) {
319 form_set_error('uc_edi_order_export_dir', t('You have specified a non-existent order export directory.'));
320 }
321 }
322
323 // Displays the help page for select EDI topics.
324 function uc_edi_admin_help() {
325 $output = '<b>'. t('Order import rules') .':</b><br /><p>'
326 . t('You may specify as many rules as you want to process order import files. Rules consist of a line identifier and action separated by | characters. Rules should be separated by line breaks (press enter after each one). Multiple rules may all use the same identifier, and they will all be applied for any matching lines in the import file.')
327 .'</p><p>'. t('Import files are parsed line by line, and each line may be handled differently based on the first value in the line. This first value is the identifier that should be used to refer to lines of that type. Use * to denote a rule that applies to any line.')
328 .'</p><p>'. t('When a line is processed, it is broken apart by the delimiter you have set for import files. Each piece may be referred to in actions by its number in sequence, i.e. #1, #2, #3.')
329 .'</p><p>'. t('You may set an action to perform only if a certain value exists in the line. Use ?3 at the start of an action and it will only be performed if the line has a value in the third place. Use !3 to instead do something if the value does not exist. Separate as many of these conditions as you want by colons, i.e. ?8:!10:oc:...')
330 .'</p><p>'. t('The following commands may be used with value substitution:');
331
332 $items = array(
333 t('<b>Specify the order ID</b> - id:2 (This must precede other actions to specify which value should be used as the order ID.)'),
334 t('<b>Update the order status</b> - us (Updates to the value specified in the order import settings.)'),
335 t('<b>Add an order comment</b> - oc:Comment message.'),
336 t('<b>Add an admin comment</b> - ac:Comment message.'),
337 t('<b>Log text to the watchdog</b> - wd:Watchdog message.'),
338 );
339
340 $output .= theme('item_list', $items);
341
342 $output .= '</p><p>'. t("How about an example? The following rules: <pre>ORD|id:2|us|oc:Your order has shipped via #3 with tracking number #4.</pre> When applied to this line in a comma delimited import file: <pre>ORD,234,UPS,1Z1730398193</pre> Would add an order comment to the order to show the customer their tracking information and update the order status.") .'</p>';
343
344 return $output;
345 }
346
347 // Displays the admin page for manual order importing and exporting.
348 function uc_edi_order_admin() {
349 $result = db_query("SELECT order_id FROM {uc_orders} WHERE order_status = '%s' ORDER BY order_id", variable_get('uc_edi_export_order_status', 'edi_export'));
350
351 $orders = array();
352 while ($order = db_fetch_object($result)) {
353 $orders[] = $order->order_id;
354 }
355
356 $output = drupal_get_form('uc_edi_order_admin_form', $orders);
357
358 return $output;
359 }
360
361 function uc_edi_order_admin_form($orders) {
362 $form['import'] = array(
363 '#type' => 'fieldset',
364 '#title' => t('Order import details'),
365 '#collapsible' => TRUE,
366 '#collapsed' => FALSE,
367 );
368
369 // Grab all valid files in the import directory.
370 $files = _get_import_files(variable_get('uc_edi_order_import_dir', ''), variable_get('uc_edi_order_import_extension', 'edi'));
371
372 // Figure out how many seconds remain till the next import will run.
373 if (variable_get('uc_edi_order_import_freq', '1 second') != 'never') {
374 $elapsed = time() - variable_get('uc_edi_last_order_import', 0);
375 $needed = time() - strtotime(variable_get('uc_edi_order_import_freq', '1 second') .' ago');
376 $seconds = $needed - $elapsed;
377 }
378 else {
379 $seconds = t('(auto import disabled) 0');
380 }
381
382 $form['import']['import_info'] = array(
383 '#value' => '<div><b>'. t('There are !count files ready to import in !seconds seconds:', array('!count' => count($files), '!seconds' => $seconds < 0 ? 0 : $seconds))
384 .'</b><br />'. implode(', ', $files) .'<p></p></div>',
385 );
386 $form['import']['import_now'] = array(
387 '#type' => 'submit',
388 '#value' => t('Import orders now'),
389 );
390 $form['import']['reset_import'] = array(
391 '#type' => 'submit',
392 '#value' => t('Reset import timer'),
393 );
394
395 $form['export'] = array(
396 '#type' => 'fieldset',
397 '#title' => t('Order export details'),
398 '#collapsible' => TRUE,
399 '#collapsed' => FALSE,
400 );
401
402 // Figure out how many seconds remain till the next export will run.
403 if (variable_get('uc_edi_order_export_freq', '1 day') != 'never') {
404 $elapsed = time() - variable_get('uc_edi_last_order_export', 0);
405 $needed = time() - strtotime(variable_get('uc_edi_order_export_freq', '1 day') .' ago');
406 $seconds = $needed - $elapsed;
407 }
408 else {
409 $seconds = t('(auto export disabled) 0');
410 }
411
412 $form['export']['export_info'] = array(
413 '#value' => '<div><b>'. t('There are !count orders ready to export in !seconds seconds:', array('!count' => count($orders), '!seconds' => $seconds < 0 ? 0 : $seconds))
414 .'</b><br />'. implode(', ', $orders) .'<p></p></div>',
415 );
416
417 // Display a fieldset with a preview of the export file.
418 $form['export']['export_preview'] = array(
419 '#type' => 'fieldset',
420 '#title' => t('Order export preview'),
421 '#collapsible' => TRUE,
422 '#collapsed' => TRUE,
423 );
424 foreach ($orders as $order_id) {
425 $order = uc_order_load($order_id);
426 $preview .= uc_edi_generate_order_export($order);
427 }
428 if (empty($preview)) {
429 $preview = t('No orders awaiting export.');
430 }
431 $form['export']['export_preview']['contents'] = array(
432 '#value' => '<div><pre>'. $preview .'</pre></div>',
433 );
434
435 $form['export']['export_now'] = array(
436 '#type' => 'submit',
437 '#value' => t('Export orders now'),
438 );
439 $form['export']['reset_export'] = array(
440 '#type' => 'submit',
441 '#value' => t('Reset export timer'),
442 );
443
444 return $form;
445 }
446
447 function uc_edi_order_admin_form_submit($form_id, $form_values) {
448 switch ($form_values['op']) {
449 case t('Import orders now'):
450 _import_orders();
451 drupal_set_message(t('Order import files have been processed.'));
452 break;
453 case t('Reset import timer'):
454 variable_set('uc_edi_last_order_import', time());
455 drupal_set_message(t('Order import timer reset.'));
456 break;
457 case t('Export orders now'):
458 $filename = _export_orders();
459 drupal_set_message(t('Order export file !file created.', array('!file' => $filename)));
460 break;
461 case t('Reset export timer'):
462 variable_set('uc_edi_last_order_export', time());
463 drupal_set_message(t('Order export timer reset.'));
464 break;
465 }
466 }
467
468 function uc_edi_export_download(){
469 $output = '';
470
471 $files = file_scan_directory(variable_get('uc_edi_order_export_dir', ''), '.*\\.'. variable_get('uc_edi_order_export_extension', 'edi'), array('.', '..', 'CVS'), 0, false);
472 $rows = array();
473 foreach ($files as $file){
474 $rows[] = array($file->basename, l(t('Download'), 'admin/store/orders/edi/download/file/'. $file->basename), l(t('Archive'), 'admin/store/orders/edi/download/archive/'. $file->basename));
475 }
476 $header = array(t('Order export file'), array('data' => t('Actions'), 'colspan' => 2));
477 if (count($rows)){
478 $output .= theme('table', $header, $rows);
479 }
480 else{
481 $output .= t('No order EDI export files were found in the export directory.');
482 }
483
484 return $output;
485 }
486
487 function uc_edi_download_file($filename = ''){
488 $file = variable_get('uc_edi_order_export_dir', '') .'/'. $filename;
489
490 if (file_exists($file)) {
491 $data = fopen($file,'rb');
492 ob_end_clean();
493
494 $headers = array(
495 'Content-Length:'. filesize($file),
496 'Content-Disposition: attachment; filename="'. basename($file) .'"',
497 'Content-Type: application/octet-stream'
498 );
499 foreach ($headers as $header) {
500 $header = preg_replace('/\r?\n(?!\t| )/', '', $header);
501 drupal_set_header($header);
502 }
503
504 while (!feof($data)) {
505 print fread($data, 1024);
506 }
507 fclose($data);
508 exit();
509 }
510 else{
511 drupal_not_found();
512 }
513 }
514
515 function uc_edi_archive_file($filename = ''){
516 $filename = variable_get('uc_edi_order_export_dir', '') .'/'. $filename;
517 if (file_move($filename, variable_get('uc_edi_order_export_archive_dir', ''))){
518 drupal_set_message(t('Order EDI export file %file was archived successfully.', array('%file' => $filename)));
519 }
520 drupal_goto('admin/store/orders/edi/download');
521 }
522
523 /*******************************************************************************
524 * Module and Helper Functions
525 ******************************************************************************/
526
527 /**
528 * Create an export file containing $contents!
529 *
530 * @param $type
531 * The type of export file to create: order
532 * @param $contents
533 * A string containing the contents of the file.
534 * @return
535 * The filename of the created export file.
536 */
537 function uc_edi_create_export($type, $contents) {
538 switch ($type) {
539 case 'order':
540 // Generate the order export filename.
541 $filename = variable_get('uc_edi_order_export_prefix', 'export-')
542 . mktime() .'.'. variable_get('uc_edi_order_export_extension', 'edi');
543
544 if (!$file = fopen(variable_get('uc_edi_order_export_dir', '') .'/'. $filename, 'wb')) {
545 watchdog('uc_edi', t('Problem creating order export file. Check your EDI settings and directory permissions.'), WATCHDOG_ERROR);
546 return;
547 }
548
549 fwrite($file, $contents);
550 fclose($file);
551
552 watchdog('uc_edi', t('Order export file !filename created.', array('!filename' => $filename)));
553
554 return $filename;
555 }
556 }
557
558 // Return the text output for an individual order.
559 function uc_edi_generate_order_export($order) {
560 $pattern = explode(',', variable_get('uc_edi_order_export_pattern', _default_order_export_pattern()));
561 $delimiter = _get_delimiter();
562
563 $values = uc_edi_order_values($order);
564
565 // Process the orders here, add the data to the current output string.
566 foreach ($pattern as $key) {
567 $key = trim($key);
568 if (substr($key, 0, 1) == '!' && strpos($key, '(') > 0) {
569 $match = substr($key, 0, strpos($key, '('));
570 $length = intval(trim(substr($key, strpos($key, '(')), '()'));
571 }
572 else {
573 $match = $key;
574 $length = FALSE;
575 }
576
577 if ($match == '!_') {
578 $output .= "\n";
579 }
580 elseif ($match == '!products') {
581 $output .= $values[$match];
582 }
583 elseif (!isset($values[$match])) {
584 $output .= $key . $delimiter;
585 }
586 else {
587 if ($length != FALSE) {
588 $temp = substr((string)$values[$match], 0, $length);
589 if (strlen($temp) < $length) {
590 $temp = $temp . str_repeat(' ', $length - strlen($temp));
591 }
592 $output .= $temp . $delimiter;
593 }
594 else {
595 $output .= $values[$match] . $delimiter;
596 }
597 }
598 }
599
600 if (substr($output, -1) !== "\n") {
601 $output .= "\n";
602 }
603
604 return $output;
605 }
606
607 function uc_edi_generate_order_product_export($product) {
608 $pattern = explode(',', variable_get('uc_edi_order_product_export_pattern', _default_order_product_export_pattern()));
609 $delimiter = _get_delimiter();
610
611 $values = uc_edi_order_product_values($product);
612
613 // Process the orders here, add the data to the current output string.
614 foreach ($pattern as $key) {
615 $key = trim($key);
616 if (substr($key, 0, 1) == '!' && strpos($key, '(') > 0) {
617 $match = substr($key, 0, strpos($key, '('));
618 $length = intval(trim(substr($key, strpos($key, '(')), '()'));
619 }
620 else {
621 $match = $key;
622 $length = FALSE;
623 }
624
625 if ($match == '!_') {
626 $output .= "\n";
627 }
628 elseif (!isset($values[$match])) {
629 $output .= $key . $delimiter;
630 }
631 else {
632 if ($length != FALSE) {
633 $temp = substr((string)$values[$match], 0, $length);
634 if (strlen($temp) < $length) {
635 $temp = $temp . str_repeat(' ', $length - strlen($temp));
636 }
637 $output .= $temp . $delimiter;
638 }
639 else {
640 $output .= $values[$match] . $delimiter;
641 }
642 }
643 }
644
645 if (substr($output, -1) !== "\n") {
646 $output .= "\n";
647 }
648
649 return $output;
650 }
651
652 // Returns a list of replacement values for order export patterns.
653 function uc_edi_order_values($order) {
654 static $data;
655
656 $order = (array) $order;
657
658 foreach (array_keys($order) as $key) {
659 if (!is_array($order[$key]) && !is_object($order[$key])) {
660 $values['!'. $key] = $order[$key];
661 }
662 }
663
664 // Build the products lines.
665 if (is_array($order['products'])) {
666 variable_set('uc_edi_order_product_line_number', 1);
667 foreach ($order['products'] as $product) {
668 $products .= uc_edi_generate_order_product_export($product);
669 }
670 $values['!products'] = $products;
671 }
672
673 // This is just an incremental value arbitrarily starting at 1000.
674 // Adjust this value to have a different starting batch ID.
675 $values['!batch_id'] = variable_get('uc_edi_order_next_batch_id', 1000);
676 variable_set('uc_edi_order_next_batch_id', $values['!batch_id'] + 1);
677
678 // This is a helper value combining the first and last names.
679 $values['!delivery_name'] = $order['delivery_first_name'] .' '. $order['delivery_last_name'];
680 $values['!billing_name'] = $order['billing_first_name'] .' '. $order['billing_last_name'];
681
682 // Add the zone code and country name values.
683 if (!isset($data['zone_code'][$order['delivery_zone']])) {
684 $values['!delivery_zone_code'] = uc_get_zone_code($order['delivery_zone']);
685 $data['zone_code'][$order['delivery_zone']] = $values['!delivery_zone_code'];
686 }
687 else {
688 $values['!delivery_zone_code'] = $data['zone_code'][$order['delivery_zone']];
689 }
690 if (!isset($data['zone_code'][$order['billing_zone']])) {
691 $values['!billing_zone_code'] = uc_get_zone_code($order['billing_zone']);
692 $data['zone_code'][$order['billing_zone']] = $values['!billing_zone_code'];
693 }
694 else {
695 $values['!billing_zone_code'] = $data['zone_code'][$order['delivery_zone']];
696 }
697
698 if ($order['delivery_country'] == 124 || $order['delivery_country'] == 840) {
699 $values['!delivery_country_name'] = ' ';
700 }
701 else {
702 if (!isset($data['country_name'][$order['delivery_country']])) {
703 $values['!delivery_country_name'] = db_result(db_query("SELECT country_name FROM {uc_countries} WHERE country_id = %d", $order['delivery_country']));
704 $data['country_name'][$order['delivery_country']] = $values['!delivery_country_name'];
705 }
706 else {
707 $values['!delivery_country_name'] = $data['country_name'][$order['delivery_country']];
708 }
709 }
710 if ($order['billing_country'] == 124 || $order['billing_country'] == 840) {
711 $values['!billing_country_name'] = ' ';
712 }
713 else {
714 if (!isset($data['country_name'][$order['billing_country']])) {
715 $values['!billing_country_name'] = db_result(db_query("SELECT country_name FROM {uc_countries} WHERE country_id = %d", $order['billing_country']));
716 $data['country_name'][$order['billing_country']] = $values['!billing_country_name'];
717 }
718 else {
719 $values['!billing_country_name'] = $data['country_name'][$order['billing_country']];
720 }
721 }
722
723 if ($order['delivery_country'] == 124 || $order['delivery_country'] == 840) {
724 $values['!delivery_country_code'] = ' ';
725 }
726 else {
727 if (!isset($data['country_code'][$order['delivery_country']])) {
728 $values['!delivery_country_code'] = db_result(db_query("SELECT country_iso_code_3 FROM {uc_countries} WHERE country_id = %d", $order['delivery_country']));
729 $data['country_code'][$order['delivery_country']] = $values['!delivery_country_code'];
730 }
731 else {
732 $values['!delivery_country_code'] = $data['country_code'][$order['delivery_country']];
733 }
734 }
735 if ($order['billing_country'] == 124 || $order['billing_country'] == 840) {
736 $values['!billing_country_code'] = ' ';
737 }
738 else {
739 if (!isset($data['country_code'][$order['billing_country']])) {
740 $values['!billing_country_code'] = db_result(db_query("SELECT country_iso_code_3 FROM {uc_countries} WHERE country_id = %d", $order['billing_country']));
741 $data['country_code'][$order['billing_country']] = $values['!billing_country_code'];
742 }
743 else {
744 $values['!billing_country_code'] = $data['country_code'][$order['billing_country']];
745 }
746 }
747
748 $values['!spacer'] = ' ';
749
750 $price = 0;
751 foreach ($order['line_items'] as $line) {
752 if ($line['type'] == 'shipping') {
753 $price += $line['amount'];
754 }
755 }
756 $values['!uc_shipping_charges'] = (string) round($price, 2);
757
758 return $values;
759 }
760
761 // Returns a list of replacement values for product export patterns.
762 function uc_edi_order_product_values($product) {
763 $product = (array) $product;
764
765 foreach (array_keys($product) as $key) {
766 if (!is_array($product[$key]) && !is_object($product[$key])) {
767 $values['!'. $key] = $product[$key];
768 }
769 }
770
771 $values['!batch_id'] = variable_get('uc_edi_order_next_batch_id', 1000);
772 $values['!#'] = variable_get('uc_edi_order_product_line_number', 1);
773 variable_set('uc_edi_order_product_line_number', $values['!#'] + 1);
774
775 $values['!spacer'] = ' ';
776
777 return $values;
778 }
779
780
781 // Load and parse all available import files and archive them when done.
782 function _import_orders() {
783 $delimiter = _get_delimiter('uc_edi_order_import_delimiter');
784 $dir = variable_get('uc_edi_order_import_dir', '');
785 $files = _get_import_files($dir, variable_get('uc_edi_order_import_extension', 'edi'));
786
787 foreach (explode("\n", variable_get('uc_edi_order_import_rules', _default_order_import_rules())) as $rule) {
788 $parts = explode("|", $rule);
789 $rules[array_shift($parts)][] = $parts;
790 }
791
792 // Up the execution time just in case. ;)
793 set_time_limit(300);
794
795 foreach ($files as $file) {
796 $data = file_get_contents($dir .'/'. $file);
797 $lines = explode("\n", $data);
798 foreach ($lines as $line) {
799 $line = trim($line);
800 $values = explode($delimiter, $line);
801
802 if (!empty($values[0])) {
803 if (isset($rules[$values[0]])) {
804 foreach ($rules[$values[0]] as $rule) {
805 _process_order_import_rule($rule, $values);
806 }
807 }
808 if (isset($rules['*'])) {
809 foreach ($rules['*'] as $rule) {
810 _process_order_import_rule($rule, $values);
811 }
812 }
813 }
814 }
815
816 // Move the file to the archive directory if we're done with it.
817 rename($dir .'/'. $file, variable_get('uc_edi_order_import_archive_dir', '') .'/'. $file);
818 }
819
820 variable_set('uc_edi_last_order_import', time());
821 }
822
823 // Load all valid orders and create the export file in the specified directory.
824 function _export_orders() {
825 $result = db_query("SELECT order_id FROM {uc_orders} WHERE order_status = '%s' ORDER BY order_id", variable_get('uc_edi_export_order_status', 'edi_export'));
826
827 $update_status = variable_get('uc_edi_exported_order_status', 'edi_pending');
828 while ($order = db_fetch_object($result)) {
829 // Load each valid order and create its export string.
830 $order = uc_order_load($order->order_id);
831 $output .= uc_edi_generate_order_export($order);
832
833 uc_order_update_status($order->order_id, $update_status);
834 uc_order_comment_save($order->order_id, 0, variable_get('uc_edi_exported_order_message', '-'), 'order', $update_status);
835 uc_order_comment_save($order->order_id, 0, t('Order exported by EDI module.'), 'admin');
836 }
837
838 // Don't bother creating an export if no data was created.
839 if (!empty($output)) {
840 $filename = uc_edi_create_export('order', $output);
841 }
842
843 variable_set('uc_edi_last_order_export', time());
844
845 return $filename;
846 }
847
848 // Returns an array of filenames for files ready to be imported.
849 function _get_import_files($dir, $extension) {
850 $files = array();
851 if (is_dir($dir)) {
852 if ($dh = opendir($dir)) {
853 while (($file = readdir($dh)) !== FALSE) {
854 switch (filetype($dir .'/'. $file)) {
855 case 'file':
856 $len = strlen($extension) + 1;
857 if (substr($file, -$len, $len) == '.'. $extension) {
858 $files[] = $file;
859 }
860 break;
861 }
862 }
863 closedir($dh);
864 }
865 }
866
867 return $files;
868 }
869
870 // Returns the default order import rules.
871 function _default_order_import_rules() {
872 $rules = "ORD|id:2|us|oc:Your order has shipped via #3 with tracking number #4.";
873
874 return $rules;
875 }
876
877 // Process an order import rule!
878 function _process_order_import_rule($rule, $values) {
879 $order_id = 0;
880
881 for ($i = 0; $i < count($values); $i++) {
882 $replace['#'. ($i + 1)] = $values[$i];
883 }
884
885 foreach ($rule as $part) {
886 $perform = TRUE;
887
888 // Evaluate conditions to see if we should perform the actions.
889 while (substr($part, 0, 1) == '?' || substr($part, 0, 1) == '!') {
890 $val = intval(substr($part, 1, strpos($part, ':') - 1));
891 if (substr($part, 0, 1) == '?') {
892 if (!isset($replace['#'. $val])) {
893 $perform = FALSE;
894 }
895 }
896 if (substr($part, 0, 1) == '!') {
897 if (isset($replace['#'. $val])) {
898 $perform = FALSE;
899 }
900 }
901 $part = substr($part, strpos($part, ':') + 1);
902 }
903
904 if ($perform) {
905 switch (substr($part, 0, 2)) {
906 // Set the order ID from the import file line.
907 case 'id':
908 $key = intval(substr($part, 3));
909 $order_id = intval($replace['#'. $key]);
910 break;
911
912 // Update an order status.
913 case 'us':
914 if ($order_id > 0) {
915 uc_order_update_status($order_id, variable_get('uc_edi_imported_order_status', 'completed'));
916 }
917 break;
918
919 // Add an order comment to the order for customers to see.
920 case 'oc':
921 if ($order_id > 0) {
922 $comment = strtr(substr($part, 3), $replace);
923 $status = db_result(db_query("SELECT order_status FROM {uc_orders} WHERE order_id = %d", $order_id));
924 uc_order_comment_save($order_id, 0, $comment, 'order', $status);
925 }
926 break;
927
928 // Add an admin comment to the order.
929 case 'ac':
930 if ($order_id > 0) {
931 $comment = strtr(substr($part, 3), $replace);
932 uc_order_comment_save($order_id, 0, $comment, 'admin');
933 }
934 break;
935
936 // Log a line to the watchdog.
937 case 'wd':
938 $message = strtr(substr($part, 3), $replace);
939 watchdog('uc_edi', $message);
940 break;
941
942 default:
943 break;
944 }
945 }
946 }
947 }
948
949 // Returns the default order export pattern.
950 function _default_order_export_pattern() {
951 // This is an example order export pattern.
952 $pattern = '01, !billing_name(29), !order_id(6), !uid(10), !_, 02, !delivery_name(30), !delivery_street1(20), !delivery_street2(20), !_, 03, !delivery_city(15), !delivery_zone_code(2), !delivery_country_name(10), !delivery_postal_code(13), !_, 04, !delivery_phone(15), !spacer(15), !primary_email(41), !_, !products, 10, !billing_name(30), !billing_street1(30), !_, 11, !billing_street2(30), !billing_city(15), !billing_zone_code(2), !billing_country_name(20), !billing_postal_code(13), !_, 12, !billing_phone(15), !billing_first_name(15), !primary_email(41)';
953
954 return $pattern;
955 }
956
957 // Returns the default order product export pattern.
958 function _default_order_product_export_pattern() {
959 // This is an example product export pattern.
960 $pattern = '05, !#(3), !spacer(3), !qty(11), EA, !price(16), !spacer(4), !model(15)';
961
962 return $pattern;
963 }
964
965 // Returns the delimiter string.
966 function _get_delimiter($var = 'uc_edi_order_export_delimiter', $default = 'tab') {
967 switch (variable_get($var, $default)) {
968 case 'tab':
969 return "\t";
970 case 'comma':
971 return ',';
972 case 'pipe':
973 return '|';
974 case 'nothing':
975 return '';
976 }
977 }
978

  ViewVC Help
Powered by ViewVC 1.1.2