/[drupal]/contributions/modules/ubercart/uc_importer/uc_importer.module
ViewVC logotype

Contents of /contributions/modules/ubercart/uc_importer/uc_importer.module

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


Revision 1.7 - (show annotations) (download) (as text)
Thu Jul 10 12:41:02 2008 UTC (16 months, 2 weeks ago) by islandusurper
Branch: MAIN
CVS Tags: HEAD
Branch point for: DRUPAL-6--2
Changes since 1.6: +315 -284 lines
File MIME type: text/x-php
Begin the Ubercart 6.x-2.x branch.
1 <?php
2 // $Id$
3
4 /**
5 * @file
6 *
7 * XML product importer and exporter.
8 *
9 * Imports and exports product nodes, as well as the taxonomy vocabularies,
10 * categories, manufacturers, classes, and attributes that are associated with them.
11 *
12 * Coded by Lyle Mantooth.
13 */
14
15 /**
16 * Do not save objects if the database already contains their names.
17 */
18 define('UC_IMPORTER_DO_NOTHING', 0);
19
20 /**
21 * Replace objects if the database already contains their names.
22 */
23 define('UC_IMPORTER_REPLACE', 1);
24
25 /**
26 * Append '_#' to the names of objects already in the database.
27 */
28 define('UC_IMPORTER_INCREMENT', 2);
29
30 /******************************************************************************
31 * Drupal Hooks *
32 ******************************************************************************/
33
34 /**
35 * Implementation of hook_perm().
36 */
37 function uc_importer_perm() {
38 return array('import', 'export');
39 }
40
41 /**
42 * Implementation of hook_menu().
43 */
44 function uc_importer_menu($may_cache) {
45 $items = array();
46
47 if ($may_cache) {
48 $items[] = array('path' => 'admin/store/products/export',
49 'access' => user_access('export'),
50 'title' => t('Export products'),
51 'callback' => 'uc_importer_export_page',
52 'type' => MENU_NORMAL_ITEM,
53 );
54 $items[] = array('path' => 'admin/store/products/import',
55 'access' => user_access('import'),
56 'title' => t('Import products'),
57 'callback' => 'uc_importer_import_page',
58 'type' => MENU_NORMAL_ITEM,
59 );
60 $items[] = array('path' => 'admin/store/settings/importer',
61 'access' => user_access('import'),
62 'title' => t('Importer settings'),
63 'description' => t('Configure the importer settings.'),
64 'callback' => 'drupal_get_form',
65 'callback arguments' => array('uc_importer_admin_settings'),
66 'type' => MENU_NORMAL_ITEM,
67 );
68 }
69
70 return $items;
71 }
72
73 /******************************************************************************
74 * Menu Callbacks *
75 ******************************************************************************/
76
77 /**
78 * Configure the importer behaviour when handling duplicate objects.
79 *
80 * @ingroup forms
81 * @see uc_importer_admin_settings_validate
82 * @see uc_importer_admin_settings_submit
83 */
84 function uc_importer_admin_settings() {
85 $form = array();
86
87 $options = array(
88 UC_IMPORTER_DO_NOTHING => t('Do not save the new item.'),
89 UC_IMPORTER_REPLACE => t('Overwrite the existing item.'),
90 UC_IMPORTER_INCREMENT => t('Save the new item as a separate entity,'),
91 );
92 $form['uc_importer_vocabulary_duplicates'] = array('#type' => 'radios',
93 '#title' => t('How should similarly named vocabularies be handled during import?'),
94 '#options' => $options,
95 '#default_value' => variable_get('uc_importer_vocabulary_duplicates', UC_IMPORTER_DO_NOTHING),
96 );
97 $form['uc_importer_category_duplicates'] = array('#type' => 'radios',
98 '#title' => t('How should similarly named categories be handled during import?'),
99 '#options' => $options,
100 '#default_value' => variable_get('uc_importer_category_duplicates', UC_IMPORTER_DO_NOTHING),
101 );
102 $form['uc_importer_class_duplicates'] = array('#type' => 'radios',
103 '#title' => t('How should similarly named classes be handled during import?'),
104 '#options' => $options,
105 '#default_value' => variable_get('uc_importer_class_duplicates', UC_IMPORTER_DO_NOTHING),
106 );
107 $form['uc_importer_attribute_duplicates'] = array('#type' => 'radios',
108 '#title' => t('How should similarly named attributes be handled during import?'),
109 '#options' => $options,
110 '#default_value' => variable_get('uc_importer_attribute_duplicates', UC_IMPORTER_DO_NOTHING),
111 );
112 $form['uc_importer_product_duplicates'] = array('#type' => 'radios',
113 '#title' => t('How should similarly identified products be handled during import?'),
114 '#options' => $options,
115 '#default_value' => variable_get('uc_importer_product_duplicates', UC_IMPORTER_DO_NOTHING),
116 );
117 $account = user_load(array('uid' => variable_get('uc_importer_user', 0)));
118 $form['uc_importer_user'] = array('#type' => 'textfield',
119 '#title' => t('Authored by'),
120 '#maxlength' => 60,
121 '#autocomplete_path' => 'user/autocomplete',
122 '#default_value' => $account ? $account->name : '',
123 '#description' => t('The "author" of imported products. Leave blank for %anonymous.', array('%anonymous' => variable_get('anonymous', t('Anonymous'))))
124 );
125
126 $form['buttons']['submit'] = array('#type' => 'submit', '#value' => t('Save configuration') );
127 $form['buttons']['reset'] = array('#type' => 'submit', '#value' => t('Reset to defaults') );
128
129 if (!empty($_POST) && form_get_errors()) {
130 drupal_set_message(t('The settings have not been saved because of the errors.'), 'error');
131 }
132
133 return $form;
134 }
135
136 /**
137 * Validation handler for uc_importer_admin_settings().
138 *
139 * Allow only existing users to be authors of imported nodes.
140 */
141 function uc_importer_admin_settings_validate($form_id, $form_values) {
142 if (!empty($form_values['uc_importer_user']) && !($account = user_load(array('name' => $form_values['uc_importer_user'])))) {
143 // The use of empty() is mandatory in the context of usernames
144 // as the empty string denotes the anonymous user. In case we
145 // are dealing with an anonymous user we set the user ID to 0.
146 form_set_error('uc_importer_user', t('The username %name does not exist.', array('%name' => $form_values['uc_importer_user'])));
147 }
148 }
149
150 /**
151 * Submit handler for uc_importer_admin_settings().
152 */
153 function uc_importer_admin_settings_submit($form_id, $form_values) {
154 if ($op == t('Reset to defaults')) {
155 variable_del('uc_importer_handle_duplicates');
156 variable_del('uc_importer_user');
157 drupal_set_message(t('The configuration options have been reset to their default values.'));
158 }
159 else {
160 if ($account = user_load(array('name' => $form_values['uc_importer_user']))) {
161 variable_set('uc_importer_user', $account->uid);
162 }
163 else {
164 variable_set('uc_importer_user', 0);
165 }
166 variable_set('uc_importer_vocabulary_duplicates', $form_values['uc_importer_vocabulary_duplicates']);
167 variable_set('uc_importer_category_duplicates', $form_values['uc_importer_category_duplicates']);
168 variable_set('uc_importer_class_duplicates', $form_values['uc_importer_class_duplicates']);
169 variable_set('uc_importer_attribute_duplicates', $form_values['uc_importer_attribute_duplicates']);
170 variable_set('uc_importer_product_duplicates', $form_values['uc_importer_product_duplicates']);
171 drupal_set_message(t('The configuration options have been saved.'));
172 }
173 }
174
175 /**
176 * Wrapper function to generate a page to hold the export form.
177 */
178 function uc_importer_export_page() {
179 uc_add_js(drupal_get_path('module', 'uc_product') .'/uc_product.js', 'module');
180 $output = '';
181 $nids = array();
182 $args = func_get_args();
183 foreach ($args as $nid) {
184 if (is_numeric($nid)) {
185 $nids[] = (int)$nid;
186 }
187 }
188 $settings = array(
189 'div' => '#products-selector',
190 'class' => 'product-ubrowser',
191 'vid' => variable_get('uc_catalog_vid', 0),
192 'filter' => implode(',', module_invoke_all('product_types')),
193 'search' => 'true',
194 'nids' => 'true',
195 'nodesg' => 'product',
196 'nodepl' => 'products',
197 'multi' => 'true',
198 'select' => 'buffer_products("'. file_create_url('') .'")',
199 );
200
201 if (module_exists('uc_catalog') && variable_get('uc_catalog_vid', 0)) {
202 $output .= ubrowser($settings, 'products-selector');
203 $output .= drupal_get_form('uc_importer_export_buffer_form', $nids);
204 }
205 else {
206 $output .= drupal_get_form('uc_importer_export_form');
207 }
208
209 return $output;
210 }
211
212 /**
213 * Wrapper function to generate a page to hold the import form.
214 */
215 function uc_importer_import_page() {
216 return drupal_get_form('uc_importer_import_form');
217 }
218
219 /******************************************************************************
220 * Module Functions *
221 ******************************************************************************/
222
223 /**
224 * Choose the nodes to export.
225 *
226 * @ingroup forms
227 * @see uc_importer_export_form_submit
228 */
229 function uc_importer_export_form() {
230 $form = array();
231
232 $products = array();
233 $result = db_query(db_rewrite_sql("SELECT nid, model FROM {uc_products}"));
234 while ($product = db_fetch_object($result)) {
235 $products[$product->nid] = $product->model;
236 }
237 $form['nids'] = array('#type' => 'select',
238 '#multiple' => true,
239 '#title' => t('Products'),
240 '#options' => $products,
241 '#description' => t('Hold "Ctrl" to select multiple items.'),
242 );
243 $form['submit'] = array('#type' => 'submit', '#value' => t('Export'));
244
245 return $form;
246 }
247
248 /**
249 * Submit handler for uc_importer_form().
250 */
251 function uc_importer_export_form_submit($form_id, $form_values) {
252 if (count($form_values['nids'])) {
253 $xml = uc_importer_export((array)$form_values['nids']);
254 if ($file = file_save_data($xml, file_directory_temp() .'/uc_export.xml', FILE_EXISTS_REPLACE)) {
255 //drupal_set_message(print_r($file, true));
256 file_transfer($file, array(
257 'Content-Type: application/xml; charset=utf-8',
258 'Content-Length: '. filesize($file),
259 'Content-Disposition: attachment; filename="uc_export.xml"',
260 ));
261 }
262 }
263 }
264
265 /**
266 * Form to collect the id numbers of all the store components to be exported.
267 *
268 * @ingroup forms
269 * @see uc_importer_export_buffer_form_submit
270 */
271 function uc_importer_export_buffer_form($nids) {
272 $form = array();
273
274 $buffer = '';
275 foreach ($nids as $nid) {
276 $node = node_load($nid);
277 $buffer .= theme('imagecache', 'uc_thumbnail', $node->field_image_cache[0]['filepath'], $node->field_image_cache[0]['alt'], $node->field_image_cache[0]['title']);
278 }
279 $form['#attributes'] = array('class' => 'product-buffer');
280 $form['thumbnails'] = array('#type' => 'markup',
281 '#value' => '<div id="buffer-images"></div>',
282 );
283 $form['products'] = array('#type' => 'hidden',
284 );
285 $form['reset'] = array('#type' => 'submit',
286 '#value' => t('Reset'),
287 );
288 $form['submit'] = array('#type' => 'submit',
289 '#value' => t('Export'),
290 );
291
292 return $form;
293 }
294
295 /**
296 * Submit handler for uc_importer_export_buffer_form().
297 *
298 * Generate an XML file from the products listed and upload it to the user.
299 */
300 function uc_importer_export_buffer_form_submit($form_id, $form_values) {
301 $item = menu_get_item(menu_get_active_item());
302 //drupal_set_message(print_r($form_values, true));
303 if ($form_values['op'] == t('Reset')) {
304 return $item['path'];
305 }
306 else {
307 $products = array_filter(explode('/', $form_values['products']));
308 //drupal_set_message('<pre>'. print_r($products, true) .'</pre>');
309 $xml = uc_importer_export($products);
310 if ($file = file_save_data($xml, file_directory_temp() .'/uc_export.xml', FILE_EXISTS_REPLACE)) {
311 //drupal_set_message(print_r($file, true));
312 file_transfer($file, array(
313 'Content-Type: application/xml',
314 'Content-Length: '. filesize($file),
315 'Content-Disposition: attachment; filename="'. $file .'"',
316 ));
317 }
318 }
319 }
320
321 /**
322 * Upload form for an XML file to be imported.
323 *
324 * @ingroup forms
325 * @see uc_importer_import_form_submit
326 */
327 function uc_importer_import_form() {
328 $form = array();
329 $form['#attributes'] = array('enctype' => "multipart/form-data");
330
331 $form['file'] = array('#type' => 'file',
332 '#title' => t('Import XML File'),
333 );
334 $form['directory'] = array('#type' => 'textfield',
335 '#title' => t('Directory containing XML files'),
336 );
337 $form['submit'] = array('#type' => 'submit',
338 '#value' => t('Import'),
339 );
340
341 return $form;
342 }
343
344 /**
345 * Submit function for uc_importer_import_form().
346 */
347 function uc_importer_import_form_submit($form_id, $form_values) {
348 $file = file_check_upload('file');
349 if ($file) {
350 $file = file_save_upload($file);
351 drupal_set_message(t('File uploaded successfully.'));
352 //drupal_set_message('<pre>'. print_r($file, true) .'</pre>');
353 if ($xml = file_get_contents($file->filepath)) {
354 uc_importer_import($xml);
355 }
356 }
357 else if ($form_values['directory']) {
358 file_scan_directory(file_directory_path() .'/'. $form_values['directory'], '.*\.xml$', array('.', '..', 'CVS'), 'uc_import_directory_parse');
359 }else {
360 drupal_set_message(t('Error: File failed to upload.'), 'error');
361 }
362 }
363
364 /**
365 * Constructs the XML representation of the store from the ids given.
366 *
367 * @param $nids
368 * An array of product ids.
369 * @return
370 * XML data to be sent.
371 */
372 function uc_importer_export($nids) {
373 $data = array(
374 'vocabularies' => array(),
375 'categories' => array(),
376 'manufacturers' => array(),
377 'attributes' => array(),
378 'classes' => array(),
379 'products' => array(),
380 );
381 foreach ($nids as $nid) {
382 $data['products'][] = $nid;
383 $node = node_load($nid);
384 if (uc_product_class_load($node->type)) {
385 $data['classes'][] = $node->type;
386 }
387 if (module_exists('taxonomy')) {
388 foreach ($node->taxonomy as $tid => $term) {
389 $data['vocabularies'][] = $term->vid;
390 foreach (taxonomy_get_parents_all($term->tid) as $parent) {
391 // First $parent is $term, so no special case needed
392 $data['categories'][] = $parent->tid;
393 }
394 if (module_exists('uc_manufacturer') && $term->vid == variable_get('uc_manufacturer_vid', 0)) {
395 $data['manufacturers'][] = $tid;
396 }
397 }
398 }
399 if (module_exists('uc_attribute')) {
400 $data['attributes'] += array_keys(uc_product_get_attributes($nid));
401 }
402 }
403 foreach ($data as $type => $ids) {
404 $data[$type] = array_unique($ids);
405 }
406 drupal_set_message('<pre>'. print_r($data, true) .'</pre>');
407 $xml = '<?xml version="1.0" encoding="utf-8" ?>'. "\n";
408 $xml .= '<store xmlns="http://www.ubercart.org" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://www.ubercart.org http://www.ubercart.org/files/store.xsd">';
409 if (is_array($data['vocabularies']) && !empty($data['categories'])) {
410 $xml .= _uc_importer_export_vocabularies($data['vocabularies']);
411 }
412 if (is_array($data['categories']) && !empty($data['categories'])) {
413 $xml .= _uc_importer_export_categories($data['categories']);
414 }
415 if (is_array($data['manufacturers']) && !empty($data['manufacturers'])) {
416 $xml .= _uc_importer_export_manufacturers($data['manufacturers']);
417 }
418 if (is_array($data['attributes']) && !empty($data['attributes'])) {
419 $xml .= _uc_importer_export_attributes($data['attributes']);
420 }
421 if (is_array($data['classes']) && !empty($data['classes'])) {
422 $xml .= _uc_importer_export_classes($data['classes']);
423 }
424 if (is_array($data['products']) && !empty($data['products'])) {
425 $xml .= _uc_importer_export_products($data['products']);
426 }
427 if (is_array($data['orders']) && !empty($data['orders'])) {
428 $xml .= _uc_importer_export_orders($data['orders']);
429 }
430 $xml .= uc_importer_invoke('export', 'store', $nids);
431 $xml .= '</store>';
432
433 //drupal_set_message(htmlspecialchars($xml));
434 return $xml;
435 }
436
437 /**
438 * Export vocabularies as XML.
439 */
440 function _uc_importer_export_vocabularies($vocabularies) {
441 $xml .= '<vocabularies>';
442 foreach ($vocabularies as $vid) {
443 $xml .= '<vocabulary>';
444 $vocabulary = taxonomy_get_vocabulary($vid);
445 $xml .= '<id>'. $vocabulary->vid .'</id>';
446 $xml .= '<name>'. htmlspecialchars($vocabulary->name, ENT_QUOTES, "UTF-8") .'</name>';
447 $xml .= '<description>'. htmlspecialchars($vocabulary->description, ENT_QUOTES, "UTF-8") .'</description>';
448 $xml .= '<relations>'. htmlspecialchars($vocabulary->relations, ENT_QUOTES, "UTF-8") .'</relations>';
449 $xml .= '<hierarchy>'. $vocabulary->hierarchy .'</hierarchy>';
450 $xml .= '<multiple>'. $vocabulary->multiple .'</multiple>';
451 $xml .= '<required>'. $vocabulary->required .'</required>';
452 $xml .= '<tags>'. $vocabulary->tags .'</tags>';
453 $xml .= '<weight>'. $vocabulary->weight .'</weight>';
454 foreach ($vocabulary->nodes as $type) {
455 $xml .= '<nodes>'. $type .'</nodes>';
456 }
457 $xml .= uc_importer_invoke('export', 'vocabulary', $vid);
458 $xml .= '</vocabulary>';
459 }
460 $xml .= '</vocabularies>';
461 return $xml;
462 }
463
464 /**
465 * Export categories as XML.
466 */
467 function _uc_importer_export_categories($categories) {
468 $xml .= '<categories>';
469 foreach ($categories as $tid) {
470 $xml .= '<category>';
471 $term = taxonomy_get_term($tid);
472 $parents = taxonomy_get_parents($tid);
473 $xml .= '<id>'. $term->tid .'</id>';
474 $xml .= '<vid>'. $term->vid .'</vid>';
475 $xml .= '<name>'. htmlspecialchars($term->name, ENT_QUOTES, "UTF-8") .'</name>';
476 $xml .= '<description>'. htmlspecialchars($term->description, ENT_QUOTES, "UTF-8") .'</description>';
477 foreach ($parents as $parent) {
478 $xml .= '<parent>'. $parent->tid .'</parent>';
479 }
480 $xml .= uc_importer_invoke('export', 'category', $tid);
481 $xml .= '</category>';
482 }
483 $xml .= '</categories>';
484 return $xml;
485 }
486
487 /**
488 * Export manufacturers as XML.
489 */
490 function _uc_importer_export_manufacturers($manufacturers) {
491 $xml = '<manufacturers>';
492 foreach ($manufacturers as $tid) {
493 $manufacturer = uc_manufacturer_load($tid);
494 $xml .= '<manufacturer>';
495 $xml .= '<id>'. $manufacturer->tid .'</id>';
496 $xml .= '<name>'. htmlspecialchars($manufacturer->name, ENT_QUOTES, "UTF-8") .'</name>';
497 $xml .= isset($manufacturer->url) && !empty($manufacturer->url) ? ('<url>'. $manufacturer->url .'</url>') : '';
498 $xml .= isset($manufacturer->phone_no) && !empty($manufacturer->phone_no) ? ('<phone_no>'. $manufacturer->phone_no .'</phone_no>') : '';
499 $xml .= isset($manufacturer->fax_no) && !empty($manufacturer->fax_no) ? ('<fax_no>'. $manufacturer->fax_no .'</fax_no>') : '';
500 $xml .= uc_importer_invoke('export', 'manufacturer', $tid);
501 $xml .= '</manufacturer>';
502 }
503 $xml .= '</manufacturers>';
504 return $xml;
505 }
506
507 /**
508 * Export product attributes as XML.
509 */
510 function _uc_importer_export_attributes($attributes) {
511 $xml = '<attributes>';
512 foreach ($attributes as $aid) {
513 $attribute = uc_attribute_load($aid);
514 $xml .= '<attribute>';
515 $xml .= '<id>'. $attribute->aid .'</id>';
516 $xml .= '<name>'. htmlspecialchars($attribute->name, ENT_QUOTES, "UTF-8") .'</name>';
517 $xml .= '<ordering>'. $attribute->ordering .'</ordering>';
518 if (is_array($attribute->options) && count($attribute->options)) {
519 $xml .= '<options>';
520 foreach ($attribute->options as $option) {
521 $xml .= '<option>';
522 $xml .= '<id>'. $option->oid .'</id>';
523 $xml .= '<name>'. htmlspecialchars($option->name, ENT_QUOTES, "UTF-8") .'</name>';
524 $xml .= '<price>'. $option->price .'</price>';
525 $xml .= '<weight>'. $option->weight .'</weight>';
526 $xml .= '<ordering>'. $option->ordering .'</ordering>';
527 $xml .= uc_importer_invoke('export', 'option', $option->oid);
528 $xml .= '</option>';
529 }
530 $xml .= '</options>';
531 }
532 $xml .= uc_importer_invoke('export', 'attribute', $aid);
533 $xml .= '</attribute>';
534 }
535 $xml .= '</attributes>';
536 return $xml;
537 }
538
539 /**
540 * Export product node types as XML.
541 */
542 function _uc_importer_export_classes($classes) {
543 $xml = '<classes>';
544 foreach ($classes as $pcid) {
545 $class = uc_product_class_load($pcid);
546 $xml .= '<class>';
547 $xml .= '<id>'. $class->pcid .'</id>';
548 $xml .= '<name>'. htmlspecialchars($class->name, ENT_QUOTES, "UTF-8") .'</name>';
549 $xml .= '<description>'. htmlspecialchars($class->description, ENT_QUOTES, "UTF-8") .'</description>';
550 $xml .= uc_importer_invoke('export', 'class', $pcid);
551 $xml .= '</class>';
552 }
553 $xml .= '</classes>';
554 return $xml;
555 }
556
557 /**
558 * Export products as XML.
559 */
560 function _uc_importer_export_products($products) {
561 $xml = '<products>';
562 foreach ($products as $nid) {
563 $xml .= '<product>';
564 $product = node_load($nid);
565 $xml .= '<unique_hash>'. $product->unique_hash .'</unique_hash>';
566 $xml .= '<id>'. $product->nid .'</id>';
567 $xml .= '<type>'. $product->type .'</type>';
568 $xml .= '<name>'. htmlspecialchars($product->title, ENT_QUOTES, "UTF-8") .'</name>';
569 $xml .= '<description>'. htmlspecialchars($product->body, ENT_QUOTES, "UTF-8") .'</description>';
570 $xml .= '<model>'. htmlspecialchars($product->model, ENT_QUOTES, "UTF-8") .'</model>';
571 if (module_exists('uc_manufacturer')) {
572 $manufacturer = uc_product_get_manufacturer($product->nid);
573 $xml .= isset($manufacturer->tid) ? ('<manufacturer>'. htmlspecialchars($manufacturer->name, ENT_QUOTES, "UTF-8") .'</manufacturer>') : '';
574 }
575 $xml .= isset($product->list_price) ? ('<list_price>'. $product->list_price .'</list_price>') : '';
576 $xml .= isset($product->cost) ? ('<cost>'. $product->cost .'</cost>') : '';
577 $xml .= '<sell_price>'. $product->sell_price .'</sell_price>';
578 $xml .= '<weight>'. $product->weight .'</weight>';
579 $xml .= '<weight_units>'. $product->weight_units .'</weight_units>';
580 $xml .= '<length>'. $product->length .'</length>';
581 $xml .= '<width>'. $product->width .'</width>';
582 $xml .= '<height>'. $product->height .'</height>';
583 $xml .= '<length_units>'. $product->length_units .'</length_units>';
584 $xml .= '<pkg_qty>'. $product->pkg_qty .'</pkg_qty>';
585 $xml .= '<default_qty>'. $product->default_qty .'</default_qty>';
586 $xml .= '<shippable>'. $product->shippable .'</shippable>';
587 if (isset($product->field_image_cache) && file_exists($product->field_image_cache[0]['filepath'])) {
588 foreach ($product->field_image_cache as $image) {
589 $xml .= '<image>';
590 $xml .= '<path>'. $GLOBALS['base_url'] .'/'. dirname($image['filepath']) .'/'. rawurlencode(basename($image['filepath'])) .'</path>';
591 if (!empty($image['alt'])) {
592 $xml .= '<alt>'. $image['alt'] .'</alt>';
593 }
594 if (!empty($image['title'])) {
595 $xml .= '<title>'. $image['title'] .'</title>';
596 }
597 $xml .= '</image>';
598 }
599 }
600 if (module_exists('content')) {
601 $type = content_types($product->type);
602 if (count($type['fields'])) {
603 $field_xml = '';
604 foreach ($type['fields'] as $field) {
605 if ($field['field_name'] != 'field_image_cache') {
606 $node_field = isset($product->$field['field_name']) ? $product->$field['field_name'] : array();
607 if (count($node_field)) {
608 $field_xml .= '<field>';
609 $field_xml .= '<name>'. $field['field_name'] .'</name>';
610 foreach ($node_field as $columns) {
611 $field_xml .= '<delta>';
612 foreach ($columns as $name => $value) {
613 $field_xml .= '<'. $name .'>'. $value .'</'. $name .'>';
614 }
615 $field_xml .= '</delta>';
616 }
617 $field_xml .= '</field>';
618 }
619 }
620 }
621 if ($field_xml) {
622 $xml .= "<fields>$field_xml</fields>";
623 }
624 }
625 }
626 if (module_exists('taxonomy')) {
627 $terms = taxonomy_node_get_terms($product->nid);
628 $xml .= '<categories>';
629 foreach ($terms as $term) {
630 $xml .= '<category>';
631 $xml .= '<id>'. $term->tid .'</id>';
632 $xml .= '</category>';
633 }
634 $xml .= '</categories>';
635 }
636 if (module_exists('uc_attribute')) {
637 $attributes = uc_product_get_attributes($product->nid);
638 if (!empty($attributes)) {
639 $xml .= '<attributes>';
640 foreach ($attributes as $attribute) {
641 $xml .= '<attribute>';
642 $xml .= '<id>'. $attribute->aid .'</id>';
643 $xml .= '<name>'. htmlspecialchars($attribute->name, ENT_QUOTES, "UTF-8") .'</name>';
644 $xml .= '<ordering>'. $attribute->ordering .'</ordering>';
645 $xml .= '<default_option>'. $attribute->default_option .'</default_option>';
646 if (!empty($attribute->options)) {
647 $xml .= '<options>';
648 foreach ($attribute->options as $option) {
649 $xml .= '<option>';
650 $xml .= '<id>'. $option->oid .'</id>';
651 $xml .= '<name>'. htmlspecialchars($option->name, ENT_QUOTES, "UTF-8") .'</name>';
652 $xml .= '<price>'. $option->price .'</price>';
653 $xml .= '<weight>'. $option->weight .'</weight>';
654 $xml .= '<ordering>'. $option->ordering .'</ordering>';
655 $xml .= uc_importer_invoke('export', 'product-option', $product->nid, $option->oid);
656 $xml .= '</option>';
657 }
658 $xml .= '</options>';
659 }
660 $xml .= uc_importer_invoke('export', 'product-attribute', $product->nid, $attribute->aid);
661 $xml .= '</attribute>';
662 }
663 $xml .= '</attributes>';
664 }
665 $result = db_query("SELECT combination, model FROM {uc_product_adjustments} WHERE nid = %d", $product->nid);
666 if (db_num_rows($result)) {
667 $xml .= '<adjustments>';
668 while ($adjustment = db_fetch_object($result)) {
669 $xml .= '<adjustment>';
670 $xml .= '<combination>'. htmlspecialchars($adjustment->combination, ENT_QUOTES, "UTF-8") .'</combination>';
671 $xml .= '<model>'. htmlspecialchars($adjustment->model, ENT_QUOTES, "UTF-8") .'</model>';
672 $xml .= uc_importer_invoke('export', 'adjustment', $adjustment, $product->nid);
673 $xml .= '</adjustment>';
674 }
675 $xml .= '</adjustments>';
676 }
677 }
678 $xml .= uc_importer_invoke('export', 'product', $product->nid);
679 $xml .= '</product>';
680 }
681 $xml .= '</products>';
682 return $xml;
683 }
684
685 /**
686 * Export orders as XML.
687 */
688 function _uc_importer_export_orders($orders) {
689 $xml = '<orders>';
690 foreach ($orders as $order_id) {
691 $order = uc_order_load($order_id);
692 if (!empty($order)) {
693 $xml .= '<order>';
694 $xml .= '<order_status>'. uc_order_status_data($order->order_status, 'title') .'</order_status>';
695 $xml .= '<order_total>'. $order->order_total .'</order_total>';
696 $xml .= '<primary_email>'. htmlspecialchars($order->primary_email, ENT_QUOTES, "UTF-8") .'</primary_email>';
697 $xml .= '<delivery_first_name>'. htmlspecialchars($order->delivery_first_name, ENT_QUOTES, "UTF-8") .'</delivery_first_name>';
698 $xml .= '<delivery_last_name>'. htmlspecialchars($order->delivery_last_name, ENT_QUOTES, "UTF-8") .'</delivery_last_name>';
699 $xml .= '<delivery_phone>'. htmlspecialchars($order->delivery_phone, ENT_QUOTES, "UTF-8") .'</delivery_phone>';
700 $xml .= '<delivery_company>'. htmlspecialchars($order->delivery_company, ENT_QUOTES, "UTF-8") .'</delivery_company>';
701 $xml .= '<delivery_street1>'. htmlspecialchars($order->delivery_street1, ENT_QUOTES, "UTF-8") .'</delivery_street1>';
702 $xml .= '<delivery_street2>'. htmlspecialchars($order->delivery_street2, ENT_QUOTES, "UTF-8") .'</delivery_street2>';
703 $xml .= '<delivery_city>'. htmlspecialchars($order->delivery_city, ENT_QUOTES, "UTF-8") .'</delivery_city>';
704 $xml .= '<delivery_zone>'. $order->delivery_zone .'</delivery_zone>';
705 $xml .= '<delivery_zip>'. htmlspecialchars($order->delivery_zip, ENT_QUOTES, "UTF-8") .'</delivery_zip>';
706 $xml .= '<delivery_country>'. $order->delivery_country .'</delivery_country>';
707 $xml .= '<billing_first_name>'. htmlspecialchars($order->billing_first_name, ENT_QUOTES, "UTF-8") .'</billing_first_name>';
708 $xml .= '<billing_last_name>'. htmlspecialchars($order->billing_last_name, ENT_QUOTES, "UTF-8") .'</billing_last_name>';
709 $xml .= '<billing_phone>'. htmlspecialchars($order->billing_phone, ENT_QUOTES, "UTF-8") .'</billing_phone>';
710 $xml .= '<billing_company>'. htmlspecialchars($order->billing_company, ENT_QUOTES, "UTF-8") .'</billing_company>';
711 $xml .= '<billing_street1>'. htmlspecialchars($order->billing_street1, ENT_QUOTES, "UTF-8") .'</billing_street1>';
712 $xml .= '<billing_street2>'. htmlspecialchars($order->billing_street2, ENT_QUOTES, "UTF-8") .'</billing_street2>';
713 $xml .= '<billing_city>'. htmlspecialchars($order->billing_city, ENT_QUOTES, "UTF-8") .'</billing_city>';
714 $xml .= '<billing_zone>'. $order->billing_zone .'</billing_zone>';
715 $xml .= '<billing_zip>'. htmlspecialchars($order->billing_zip, ENT_QUOTES, "UTF-8") .'</billing_zip>';
716 $xml .= '<billing_country>'. $order->billing_country .'</billing_country>';
717 $xml .= '<payment_method>'. $order->payment_method .'</payment_method>';
718 if (!empty($order->products)) {
719 $xml .= '<products>';
720 foreach ($order->products as $product) {
721 $xml .= '<product>';
722 $xml .= '<qty>'. $product->qty .'</qty>';
723 $xml .= '<name>'. htmlspecialchars($product->title, ENT_QUOTES, "UTF-8") .'</name>';
724 if ($product->manufacturer) {
725 $xml .= '<manufacturer>'. htmlspecialchars($product->manufacturer, ENT_QUOTES, "UTF-8") .'</manufacturer>';
726 }
727 $xml .= '<model>'. htmlspecialchars($product->model, ENT_QUOTES, "UTF-8") .'</model>';
728 $xml .= '<cost>'. $product->cost .'</cost>';
729 $xml .= '<price>'. $product->price .'</price>';
730 $xml .= '<weight>'. $product->weight .'</weight>';
731 $xml .= '<data>'. htmlspecialchars($product->data, ENT_QUOTES, "UTF-8") .'</data>';
732 $xml .= uc_importer_invoke('export', 'order-product', $order_id, $product->order_product_id);
733 $xml .= '</product>';
734 }
735 $xml .= '</products>';
736 $quote = $order->quote;
737 $xml .= '<quote>';
738 $xml .= '<method>'. $quote['method'] .'</method>';
739 $xml .= '<accessorials>'. $quote['accessorials'] .'</accessorials>';
740 $xml .= '<rate>'. $quote['rate'] .'</rate>';
741 $xml .= '<quote_form>'. htmlspecialchars($quote['quote_form'], ENT_QUOTES, "UTF-8") .'</quote_form>';
742 $xml .= uc_importer_invoke('export', 'quote', $order_id);
743 $xml .= '</quote>';
744 if (!empty($order->line_items)) {
745 $xml .= '<line_items>';
746 foreach ($order->line_items as $line_item) {
747 $xml .= '<line_item>';
748 $xml .= '<type>'. $line_item['type'] .'</type>';
749 $xml .= '<title>'. htmlspecialchars($line_item['title'], ENT_QUOTES, "UTF-8") .'</title>';
750 $xml .= '<amount>'. $line_item['amount'] .'</amount>';
751 $xml .= '<weight>'. $line_item['weight'] .'</weight>';
752 $xml .= uc_importer_invoke('export', 'line_item', $line_item->line_item_id);
753 $xml .= '</line_item>';
754 }
755 $xml .= '</line_items>';
756 }
757 }
758 $xml .= uc_importer_invoke('export', 'order', $order_id);
759 $xml .= '</order>';
760 }
761 }
762 $xml .= '</orders>';
763 return $xml;
764 }
765
766 /**
767 * Imports an XML document into the database.
768 *
769 * The script checks for objects that have the same names as those in the XML
770 * document. If it finds a duplicate, it may replace that object with the XML,
771 * create a new object with marker indicating its imported status, or abort the
772 * importing of that particular object.
773 *
774 * @param $xml
775 * String of XML data. It should conform to the schema located at
776 * http://www.ubercart.org/files/store.xsd
777 */
778 function uc_importer_import($xml) {
779 include_once(drupal_get_path('module', 'uc_store') .'/includes/simplexml.php');
780 global $user, $active_db;
781
782 $error = '';
783 /* $data = new DOMDocument();
784 $data->loadXML($xml);
785
786 if (!$data) {
787 $error = "Error: Could not load XML.";
788 }
789 else { */
790 /* if (!($data->schemaValidate('http://www.ubercart.org/files/store.xsd'))) {
791 $error = "Error: XML is not validated by schema.";
792 }
793 else { */
794 $id_map = array('vocabularies' => array(), 'categories' => array(), 'manufacturers' => array(), 'attributes' => array(), 'options' => array(), 'classes' => array(), 'products' => array());
795 $store = new JSimpleXML();
796 $store->loadString($xml);
797 if (module_exists('taxonomy')) {
798 if (isset($store->document->vocabularies)) {
799 foreach ($store->document->vocabularies[0]->vocabulary as $vocabulary_data) {
800 $name = (string)$vocabulary_data->name[0]->data();
801 $result = db_query("SELECT vid FROM {vocabulary} WHERE name = '%s'", $name);
802 if (db_num_rows($result) && variable_get('uc_importer_vocabulary_duplicates', UC_IMPORTER_DO_NOTHING) != UC_IMPORTER_INCREMENT) {
803 $id_map['vocabularies'][(string)$vocabulary_data->id[0]->data()] = db_result($result);
804 }
805 else {
806 $vocab = array(
807 'name' => html_entity_decode((string)$vocabulary_data->name[0]->data(), ENT_QUOTES, "UTF-8"),
808 'description' => html_entity_decode((string)$vocabulary_data->description[0]->data(), ENT_QUOTES, "UTF-8"),
809 'relations' => (int)$vocabulary_data->relations[0]->data(),
810 'hierarchy' => (int)$vocabulary_data->hierarchy[0]->data(),
811 'multiple' => (int)$vocabulary_data->multiple[0]->data(),
812 'required' => (int)$vocabulary_data->required[0]->data(),
813 'tags' => (int)$vocabulary_data->tags[0]->data(),
814 'weight' => (int)$vocabulary_data->weight[0]->data(),
815 );
816 foreach ($vocabulary_data->nodes as $node_type) {
817 $vocab['nodes'][(string)$node_type->data()] = true;
818 }
819 taxonomy_save_vocabulary($vocab);
820 $id_map['vocabularies'][(int)$vocabulary_data->id[0]->data()] = db_result(db_query("SELECT id FROM {sequences} WHERE name = '{vocabulary}_vid'"));
821 }
822 module_invoke_all('xml_importer', 'vocabulary', taxonomy_get_vocabulary($id_map['vocabularies'][(int)$vocabulary_data->id[0]->data()]), $vocabulary_data, $store, $id_map);
823 }
824 }
825 $categories = array();
826 if (isset($store->document->categories)) {
827 $new_categories = array();
828 foreach ($store->document->categories[0]->category as $category_data) {
829 $name =(string)$category_data->name[0]->data();
830 $result = db_query("SELECT tid FROM {term_data} WHERE name = '%s'", $name);
831 if (db_num_rows($result) && variable_get('uc_importer_category_duplicates', UC_IMPORTER_DO_NOTHING) != UC_IMPORTER_INCREMENT) {
832 $id_map['categories'][(string)$category_data->id[0]->data()] = db_result($result);
833 }
834 else {
835 $tid = db_next_id('{term_data}_tid');
836 $vid = isset($id_map['vocabularies'][(int)$category_data->vid[0]->data()]) ? $id_map['vocabularies'][(int)$category_data->vid[0]->data()] : variable_get('uc_catalog_vid', 0);
837 $id_map['categories'][(string)$category_data->id[0]->data()] = $tid;
838 $new_categories[] = $tid;
839 db_query("INSERT INTO {term_data} (tid, vid, name, description) VALUES (%d, %d, '%s', '%s')", $tid, $vid, html_entity_decode((string)$category_data->name[0]->data(), ENT_QUOTES, "UTF-8"), html_entity_decode((string)$category_data->description[0]->data(), ENT_QUOTES, "UTF-8"));
840 }
841 }
842 foreach ($store->document->categories[0]->category as $category_data) {
843 if (in_array($id_map['categories'][(string)$category_data->id[0]->data()], $new_categories)) {
844 $parent = 0;
845 if (isset($category_data->parent)) {
846 $parent = (string)$category_data->parent[0]->data();
847 }
848
849 switch ($GLOBALS['db_type']) {
850 case 'mysqli':
851 case 'mysql':
852 db_query("INSERT IGNORE INTO {term_hierarchy} (tid, parent) VALUES (%d, %d)", $id_map['categories'][(string)$category_data->id[0]->data()], $id_map['categories'][$parent]);
853 break;
854 case 'pgsql':
855 db_query("INSERT INTO {term_hierarchy} (tid, parent) VALUES (%d, %d)", $id_map['categories'][(string)$category_data->id[0]->data()], $id_map['categories'][$parent]);
856 break;
857 }
858 }
859
860 module_invoke_all('xml_importer', 'category', taxonomy_get_term($id_map['categories'][(string)$category_data->id[0]->data()]), $category_data, $store, $id_map);
861 }
862 }
863 db_query("DELETE FROM {term_hierarchy} WHERE tid = parent");
864 }
865 if (module_exists('uc_manufacturer')) {
866 if (isset($store->document->manufacturers)) {
867 foreach ($store->document->manufacturers[0]->manufacturer as $manufacturer_data) {
868 $manufacturer = new stdClass();
869 foreach ($manufacturer_data->children() as $datum) {
870 $manufacturer->{$datum->name()} = (string)$datum->data();
871 }
872 $result = db_query("SELECT tid FROM {term_data} WHERE name LIKE '%s\\__' OR name LIKE '%s'", $manufacturer->name, $manufacturer->name);
873 if ($tid = db_result($result)) {
874 $manufacturer->tid = $tid;
875 $id_map['manufacturers'][(int)$manufacturer->id] = $tid;
876 if (in_array($tid, $new_categories)) {
877 drupal_execute('taxonomy_form_term', (array)$manufacturer, variable_get('uc_manufacturer_vid', 0), array('tid' => $tid));
878 }
879 else {
880 switch (variable_get('uc_importer_category_duplicates', UC_IMPORTER_DO_NOTHING)) {
881 case UC_IMPORTER_REPLACE:
882 drupal_execute('taxonomy_form_term', (array)$manufacturer, variable_get('uc_manufacturer_vid', 0), array('tid' => $tid));
883 break;
884 case UC_IMPORTER_INCREMENT:
885 $manufacturer->name .= '_'. db_num_rows($result);
886 drupal_execute('taxonomy_form_term', (array)$manufacturer, variable_get('uc_manufacturer_vid', 0));
887 break;
888 }
889 }
890 }
891 else {
892 drupal_execute('taxonomy_form_term', (array)$manufacturer, variable_get('uc_manufacturer_vid', 0));
893 $id_map['manufacturers'][(int)$manufacturer->id] = db_result(db_query("SELECT id FROM {sequences} WHERE name = '{term_data}_tid'"));
894 }
895 module_invoke_all('xml_importer', 'manufacturer', uc_manufacturer_load($id_map['manufacturers'][(int)$manufacturer->id]), $manufacturer_data, $store, $id_map);
896 }
897 }
898 }
899 if (module_exists('uc_attribute')) {
900 if (isset($store->document->attributes)) {
901 foreach ($store->document->attributes[0]->attribute as $attribute_data) {
902 $attribute = new stdClass();
903 $attribute->name = html_entity_decode((string)$attribute_data->name[0]->data(), ENT_QUOTES, "UTF-8");
904 $attribute->ordering = isset($attribute_data->ordering) ? (int)$attribute_data->ordering[0]->data() : 0;
905 $result = db_query("SELECT aid FROM {uc_attributes} WHERE name LIKE '%s\\__' OR name LIKE '%s'", $attribute->name, $attribute->name);
906 if ($aid = db_result($result)) {
907 if (variable_get('uc_importer_attribute_duplicates', UC_IMPORTER_DO_NOTHING) == UC_IMPORTER_INCREMENT) {
908 $attribute->name .= '_'. db_num_rows($result);
909 drupal_execute('uc_attribute_form', (array)$attribute);
910 }
911 }
912 else {
913 drupal_execute('uc_attribute_form', (array)$attribute);
914 $aid = db_result(db_query("SELECT aid FROM {uc_attributes} WHERE name = '%s'", $attribute->name));
915 }
916 if ($aid) {
917 $id_map['attributes'][(string)$attribute_data->id[0]->data()] = $aid;
918 $attribute->options = array();
919 if (isset($attribute_data->options)) {
920 foreach ($attribute_data->options[0]->option as $option_data) {
921 $option = new stdClass();
922 $option->name = html_entity_decode((string)$option_data->name[0]->data(), ENT_QUOTES, "UTF-8");
923 $option->price = isset($option_data->price) ? (float)$option_data->price[0]->data() : 0;
924 $option->weight = isset($option_data->weight) ? (float)$option_data->weight[0]->data() : 0;
925 $option->ordering = isset($option_data->ordering) ? (integer)$option_data->ordering[0]->data() : 0;
926 $result = db_query("SELECT oid FROM {uc_attribute_options} WHERE aid = %d AND (name LIKE '%s\\__' OR name LIKE '%s')", $aid, $option->name, $option->name);
927 if ($oid = db_result($result)) {
928 switch (variable_get('uc_importer_attribute_duplicates', UC_IMPORTER_DO_NOTHING)) {
929 case UC_IMPORTER_INCREMENT:
930 $option->name .= '_'. db_num_rows($result);
931 drupal_execute('uc_attribute_option_form', (array)$option, $aid);
932 $id_map['options'][(string)$option_data->id[0]->data()] = db_result(db_query("SELECT MAX(oid) FROM {uc_attribute_options}"));
933 break;
934 case UC_IMPORTER_REPLACE:
935