| 1 |
<?php |
<?php |
| 2 |
// $Id$ |
// $Id: node_export.module,v 1.1.2.2 2009/09/08 10:14:12 danielb Exp $ |
| 3 |
|
|
| 4 |
/** |
/** |
| 5 |
* @file |
* @file |
| 6 |
* The Node Export module. |
* The Node Export module. |
| 7 |
* |
* |
| 8 |
* Allows users to export an existing node and then import it into another Drupal installation. |
* Allows users to export nodes and then import them into another Drupal installation. |
| 9 |
*/ |
*/ |
| 10 |
|
|
| 11 |
|
// Define the files subdirectory |
| 12 |
|
define("NODE_EXPORT", "node-export"); |
| 13 |
|
|
| 14 |
/** |
/** |
| 15 |
* Implementation of hook_help(). |
* Implementation of hook_help(). |
| 16 |
*/ |
*/ |
| 19 |
case 'admin/help#node_export': |
case 'admin/help#node_export': |
| 20 |
$output = '<p>'. t('The Node export module allows users to export an existing node and then import it into another Drupal installation.') .'</p>'; |
$output = '<p>'. t('The Node export module allows users to export an existing node and then import it into another Drupal installation.') .'</p>'; |
| 21 |
$output .= '<p>'. t('Users with the "export node" permission can utilize this functionality. A new tab will appear on node pages with the word "Export".') .'</p>'; |
$output .= '<p>'. t('Users with the "export node" permission can utilize this functionality. A new tab will appear on node pages with the word "Export".') .'</p>'; |
| 22 |
|
$output .= '<p>'. t('It is also possible to do bulk exports, with the "export bulk nodes" permission, via Content admin (admin/content/node) or using "Views Bulk Operations".') .'</p>'; |
| 23 |
|
$output .= '<p>'. t('Importing nodes is done via the "Node Export: Import" page (admin/content/import) and can be done by those with the "import nodes" permission.') .'</p>'; |
| 24 |
return $output; |
return $output; |
| 25 |
} |
} |
| 26 |
} |
} |
| 40 |
'access arguments' => array('administer site configuration'), |
'access arguments' => array('administer site configuration'), |
| 41 |
'page callback' => 'drupal_get_form', |
'page callback' => 'drupal_get_form', |
| 42 |
'page arguments' => array('node_export_settings'), |
'page arguments' => array('node_export_settings'), |
| 43 |
'title' => 'Export module', |
'title' => 'Node Export', |
| 44 |
'file' => 'node_export.pages.inc', |
'description' => 'Configure the settings for Node Export.', |
|
'description' => 'Allows users to export (copy then edit) an existing node.', |
|
| 45 |
); |
); |
| 46 |
$items['node/%node/node_export'] = array( |
$items['node/%node/node_export'] = array( |
| 47 |
'access callback' => 'node_export_access', |
'access callback' => 'node_export_access', |
| 50 |
'page arguments' => array(1), |
'page arguments' => array(1), |
| 51 |
'title' => 'Export', |
'title' => 'Export', |
| 52 |
'weight' => 5, |
'weight' => 5, |
|
'file' => 'node_export.pages.inc', |
|
| 53 |
'type' => MENU_LOCAL_TASK, |
'type' => MENU_LOCAL_TASK, |
| 54 |
); |
); |
| 55 |
$items['admin/content/import'] = array( |
$items['admin/content/import'] = array( |
| 56 |
'access arguments' => array('import nodes'), |
'access arguments' => array('import nodes'), |
| 57 |
'page callback' => 'node_export_node_import', |
'page callback' => 'drupal_get_form', |
| 58 |
'title' => 'Import', |
'page arguments' => array('node_export_import_form'), |
| 59 |
'file' => 'node_export.pages.inc', |
'title' => 'Node Export: Import', |
| 60 |
'type' => MENU_NORMAL_ITEM, |
'type' => MENU_NORMAL_ITEM, |
| 61 |
'description' => 'Allows users to import a node from another site.', |
'description' => 'Import nodes that were exported with <em>Node Export</em>.', |
| 62 |
); |
); |
| 63 |
return $items; |
return $items; |
| 64 |
} |
} |
| 65 |
|
|
| 66 |
|
/** |
| 67 |
|
* Check menu access to export a node. |
| 68 |
|
*/ |
| 69 |
function node_export_access($node) { |
function node_export_access($node) { |
| 70 |
global $user; |
global $user; |
| 71 |
// Check basic permissions first. |
// Check basic permissions first. |
| 80 |
return $access; |
return $access; |
| 81 |
} |
} |
| 82 |
|
|
| 83 |
|
/** |
| 84 |
|
* Check whether exporting this type is permitted. |
| 85 |
|
*/ |
| 86 |
function node_export_is_permitted($type) { |
function node_export_is_permitted($type) { |
| 87 |
$omitted = variable_get('node_export_omitted', array()); |
$omitted = variable_get('node_export_omitted', array()); |
| 88 |
return empty($omitted[$type]); |
return empty($omitted[$type]); |
| 89 |
} |
} |
| 90 |
|
|
| 91 |
/** |
/** |
| 92 |
* Implementation of hook_mode_type(). |
* Implementation of hook_node_type(). |
| 93 |
*/ |
*/ |
| 94 |
function node_export_node_type($op, $type_obj) { |
function node_export_node_type($op, $type_obj) { |
| 95 |
|
|
| 118 |
); |
); |
| 119 |
} |
} |
| 120 |
|
|
|
|
|
| 121 |
/** |
/** |
| 122 |
* Implementation of hook_node_operations(). |
* Implementation of hook_node_operations(). |
| 123 |
*/ |
*/ |
| 144 |
$node_codes[] = node_export_node_export(node_load($nid), TRUE, 1); |
$node_codes[] = node_export_node_export(node_load($nid), TRUE, 1); |
| 145 |
} |
} |
| 146 |
$node_code = "array(\n ". implode(",\n ", $node_codes) .",\n)"; |
$node_code = "array(\n ". implode(",\n ", $node_codes) .",\n)"; |
| 147 |
drupal_set_message(drupal_get_form('node_export_form', $node_code)); |
if (variable_get('node_export_bulk_code', 'copy') == 'copy') { |
| 148 |
|
drupal_set_message(drupal_get_form('node_export_form', $node_code)); |
| 149 |
|
} |
| 150 |
|
else { |
| 151 |
|
node_export_get_file($nodes, $node_code, TRUE); |
| 152 |
|
} |
| 153 |
|
} |
| 154 |
|
|
| 155 |
|
/** |
| 156 |
|
* Generate text file. |
| 157 |
|
* @param $nodes |
| 158 |
|
* An array of nids. |
| 159 |
|
* @param $node_code |
| 160 |
|
* The text output. |
| 161 |
|
*/ |
| 162 |
|
function node_export_get_file($nodes, $node_code, $bulk = FALSE) { |
| 163 |
|
$filename_data = array(); |
| 164 |
|
$filename_data['count'] = count($nodes); |
| 165 |
|
$filename_data['time'] = time(); |
| 166 |
|
|
| 167 |
|
// Add a list of nids |
| 168 |
|
if (count($nodes) <= variable_get('node_export_file_list', 10)) { |
| 169 |
|
$filename_data['list'] = '['. implode(',', $nodes) .']'; |
| 170 |
|
} |
| 171 |
|
if ($bulk) { |
| 172 |
|
$name = variable_get('node_export_bulk_filename', 'node-export[nid-list]([node-count]-nodes).[timestamp].export'); |
| 173 |
|
} |
| 174 |
|
else { |
| 175 |
|
$name = variable_get('node_export_node_filename', 'node-export[nid-list].[timestamp].export'); |
| 176 |
|
} |
| 177 |
|
if (module_exists('token')) { |
| 178 |
|
$name = token_replace($name, 'Node export filename', $filename_data, '[', ']'); |
| 179 |
|
} |
| 180 |
|
else { |
| 181 |
|
// So it works without token. |
| 182 |
|
$name = str_replace('[nid-list]', $filename_data['list'], $name); |
| 183 |
|
$name = str_replace('[node-count]', $filename_data['count'], $name); |
| 184 |
|
$name = str_replace('[timestamp]', $filename_data['time'], $name); |
| 185 |
|
} |
| 186 |
|
header('Content-type: text/plain'); |
| 187 |
|
header('Content-Disposition: attachment; filename="'. $name .'"'); |
| 188 |
|
print($node_code); |
| 189 |
|
drupal_goto($_GET['q']); // This may not seem like it does anything, but trust me on this. |
| 190 |
|
} |
| 191 |
|
|
| 192 |
|
/** |
| 193 |
|
* Implementation of hook_token_values(). |
| 194 |
|
*/ |
| 195 |
|
function node_export_token_values($type, $object = NULL, $options = array()) { |
| 196 |
|
if ($type == 'Node export filename') { |
| 197 |
|
$tokens['nid-list'] = $object['list']; |
| 198 |
|
$tokens['node-count'] = $object['count']; |
| 199 |
|
$tokens['timestamp'] = $object['time']; |
| 200 |
|
return $tokens; |
| 201 |
|
} |
| 202 |
|
} |
| 203 |
|
|
| 204 |
|
/** |
| 205 |
|
* Implementation of hook_token_list(). |
| 206 |
|
*/ |
| 207 |
|
function node_export_token_list($type = 'all') { |
| 208 |
|
if ($type == 'Node export filename') { |
| 209 |
|
$tokens['Node export filename']['nid-list'] = t("Comma seperated list of node ids in square brackets (if available)."); |
| 210 |
|
$tokens['Node export filename']['node-count'] = t("The number of nodes exported."); |
| 211 |
|
$tokens['Node export filename']['timestamp'] = t("The timestamp when the file was generated."); |
| 212 |
|
return $tokens; |
| 213 |
|
} |
| 214 |
|
} |
| 215 |
|
|
| 216 |
|
/** |
| 217 |
|
* Handles the bits of the form that are specific to the token module. |
| 218 |
|
*/ |
| 219 |
|
function node_export_settings_token_bits(&$form, $key, $group = 'basic') { |
| 220 |
|
if (module_exists('token')) { |
| 221 |
|
$form[$group][$key .'_token_help'] = array( |
| 222 |
|
'#title' => t('Replacement patterns'), |
| 223 |
|
'#type' => 'fieldset', |
| 224 |
|
'#collapsible' => TRUE, |
| 225 |
|
'#collapsed' => TRUE, |
| 226 |
|
); |
| 227 |
|
$form[$group][$key .'_token_help']['help'] = array( |
| 228 |
|
'#value' => theme('token_help', 'Node export filename'), |
| 229 |
|
); |
| 230 |
|
} |
| 231 |
|
else { |
| 232 |
|
$form[$group][$key]['#description'] = t('Get the !token module for more options.', array('!token' => l(t('token'), 'http://www.drupal.org/project/token'))); |
| 233 |
|
} |
| 234 |
|
} |
| 235 |
|
|
| 236 |
|
/** |
| 237 |
|
* Menu callback to configure module settings. |
| 238 |
|
*/ |
| 239 |
|
function node_export_settings() { |
| 240 |
|
|
| 241 |
|
$form['basic'] = array( |
| 242 |
|
'#type' => 'fieldset', |
| 243 |
|
'#title' => t('General settings'), |
| 244 |
|
); |
| 245 |
|
$form['basic']['node_export_method'] = array( |
| 246 |
|
'#type' => 'radios', |
| 247 |
|
'#title' => t('Method to use when importing a node'), |
| 248 |
|
'#options' => array('prepopulate' => t('Prepopulate the node form fields'), 'save-edit' => t('Save as a new node then edit')), |
| 249 |
|
'#default_value' => variable_get('node_export_method', 'prepopulate'), |
| 250 |
|
); |
| 251 |
|
$form['basic']['node_export_node_code'] = array( |
| 252 |
|
'#type' => 'radios', |
| 253 |
|
'#title' => t('Node export code delivery'), |
| 254 |
|
'#options' => array('copy' => t('Textarea filled with export code'), 'file' => t('Text file download')), |
| 255 |
|
'#default_value' => variable_get('node_export_node_code', 'copy'), |
| 256 |
|
); |
| 257 |
|
$form['basic']['node_export_node_filename'] = array( |
| 258 |
|
'#type' => 'textfield', |
| 259 |
|
'#title' => t('Filename pattern'), |
| 260 |
|
'#default_value' => variable_get('node_export_node_filename', 'node-export[nid-list].[timestamp].export'), |
| 261 |
|
'#size' => 120, |
| 262 |
|
); |
| 263 |
|
node_export_settings_token_bits(&$form, 'node_export_node_filename'); |
| 264 |
|
$form['basic']['node_export_bulk_code'] = array( |
| 265 |
|
'#type' => 'radios', |
| 266 |
|
'#title' => t('Bulk node export code delivery'), |
| 267 |
|
'#options' => array('copy' => t('Textarea filled with export code'), 'file' => t('Text file download')), |
| 268 |
|
'#default_value' => variable_get('node_export_bulk_code', 'copy'), |
| 269 |
|
); |
| 270 |
|
$form['basic']['node_export_bulk_filename'] = array( |
| 271 |
|
'#type' => 'textfield', |
| 272 |
|
'#title' => t('Filename pattern (bulk)'), |
| 273 |
|
'#default_value' => variable_get('node_export_bulk_filename', 'node-export[nid-list]([node-count]-nodes).[timestamp].export'), |
| 274 |
|
'#size' => 120, |
| 275 |
|
); |
| 276 |
|
node_export_settings_token_bits(&$form, 'node_export_bulk_filename'); |
| 277 |
|
$form['basic']['node_export_file_list'] = array( |
| 278 |
|
'#type' => 'textfield', |
| 279 |
|
'#title' => t('Nid list limit max'), |
| 280 |
|
'#default_value' => variable_get('node_export_file_list', 10), |
| 281 |
|
'#size' => 6, |
| 282 |
|
'#maxlength' => 30, |
| 283 |
|
'#description' => t('If there are more than this many nodes, the list of node ids for the filename will not be built.'), |
| 284 |
|
); |
| 285 |
|
|
| 286 |
|
$form['publishing'] = array( |
| 287 |
|
'#type' => 'fieldset', |
| 288 |
|
'#title' => t('Reset values on import'), |
| 289 |
|
); |
| 290 |
|
$types = node_get_types('names'); |
| 291 |
|
|
| 292 |
|
foreach ($types as $type => $name) { |
| 293 |
|
$form['publishing'][$type] = array( |
| 294 |
|
'#type' => 'fieldset', |
| 295 |
|
'#title' => $name, |
| 296 |
|
'#description' => t('Reset these values when importing nodes of type @s.', array('@s' => $name)), |
| 297 |
|
); |
| 298 |
|
$form['publishing'][$type]['node_export_reset_'. $type] = array( |
| 299 |
|
'#type' => 'checkbox', |
| 300 |
|
'#title' => t('Publishing options (status, moderate, promote, sticky, and revision)'), |
| 301 |
|
'#default_value' => variable_get('node_export_reset_'. $type, FALSE), |
| 302 |
|
); |
| 303 |
|
$form['publishing'][$type]['node_export_reset_created_'. $type] = array( |
| 304 |
|
'#type' => 'checkbox', |
| 305 |
|
'#title' => t('Created time (<em>Authored on</em> date)'), |
| 306 |
|
'#default_value' => variable_get('node_export_reset_created_'. $type, TRUE), |
| 307 |
|
); |
| 308 |
|
$form['publishing'][$type]['node_export_reset_menu_'. $type] = array( |
| 309 |
|
'#type' => 'checkbox', |
| 310 |
|
'#title' => t('Menu link'), |
| 311 |
|
'#default_value' => variable_get('node_export_reset_menu_'. $type, TRUE), |
| 312 |
|
); |
| 313 |
|
$form['publishing'][$type]['node_export_reset_path_'. $type] = array( |
| 314 |
|
'#type' => 'checkbox', |
| 315 |
|
'#title' => t('URL path'), |
| 316 |
|
'#default_value' => variable_get('node_export_reset_path_'. $type, TRUE), |
| 317 |
|
); |
| 318 |
|
$form['publishing'][$type]['node_export_reset_book_mlid_'. $type] = array( |
| 319 |
|
'#type' => 'checkbox', |
| 320 |
|
'#title' => t('Book menu link'), |
| 321 |
|
'#default_value' => variable_get('node_export_reset_book_mlid_'. $type, TRUE), |
| 322 |
|
); |
| 323 |
|
} |
| 324 |
|
// Need the variable default key to be something that's never a valid node type. |
| 325 |
|
$form['omit'] = array( |
| 326 |
|
'#type' => 'fieldset', |
| 327 |
|
'#title' => t('Content types that are not to be exported - omitted due to incompatibility'), |
| 328 |
|
); |
| 329 |
|
$form['omit']['node_export_omitted'] = array( |
| 330 |
|
'#type' => 'checkboxes', |
| 331 |
|
'#title' => t('Omitted content types'), |
| 332 |
|
'#default_value' => variable_get('node_export_omitted', array()), |
| 333 |
|
'#options' => $types, |
| 334 |
|
'#description' => t('Select any node types which should <em>never</em> be exported. Typically you should will want to select here all node types for which importing fails (e.g. image nodes).'), |
| 335 |
|
); |
| 336 |
|
|
| 337 |
|
return system_settings_form($form); |
| 338 |
|
} |
| 339 |
|
|
| 340 |
|
/** |
| 341 |
|
* Exports a node - populate a node code form |
| 342 |
|
* set $return_code to TRUE to not return form but the code instead. |
| 343 |
|
*/ |
| 344 |
|
function node_export_node_export($original_node, $return_code = FALSE, $iteration = 0) { |
| 345 |
|
if (isset($original_node->nid)) { |
| 346 |
|
global $user; |
| 347 |
|
|
| 348 |
|
if (node_export_is_permitted($original_node->type)) { |
| 349 |
|
$node = drupal_clone($original_node); |
| 350 |
|
|
| 351 |
|
drupal_set_title(t('Export of !title', array('!title' => check_plain($node->title)))); |
| 352 |
|
|
| 353 |
|
// Fix taxonomy array |
| 354 |
|
if (isset($node->taxonomy) && count($node->taxonomy)) { |
| 355 |
|
$vocabularies = taxonomy_get_vocabularies(); |
| 356 |
|
$new_taxonomy = array(); |
| 357 |
|
foreach ($node->taxonomy as $term) { |
| 358 |
|
// Free-tagging vocabularies need a different format |
| 359 |
|
if ($vocabularies[$term->vid]->tags) { |
| 360 |
|
$new_taxonomy['tags'][$term->vid][] = $term->name; |
| 361 |
|
} |
| 362 |
|
else { |
| 363 |
|
$new_taxonomy[$term->vid][$term->tid] = $term->tid; |
| 364 |
|
} |
| 365 |
|
} |
| 366 |
|
if (isset($new_taxonomy['tags']) && count($new_taxonomy['tags'])) { |
| 367 |
|
// Comma seperate the tags |
| 368 |
|
foreach ($new_taxonomy['tags'] as $vid => $tags) { |
| 369 |
|
$new_taxonomy['tags'][$vid] = implode(', ', $tags); |
| 370 |
|
} |
| 371 |
|
} |
| 372 |
|
$node->taxonomy = $new_taxonomy; |
| 373 |
|
} |
| 374 |
|
|
| 375 |
|
// Fix menu array |
| 376 |
|
$node->menu = node_export_get_menu($original_node); |
| 377 |
|
|
| 378 |
|
// Let other modules do special fixing up. |
| 379 |
|
// The function signature is: hook_export_node_alter(&$node, $original_node, $method) |
| 380 |
|
// Where $method is 'export' |
| 381 |
|
drupal_alter('node_export_node', $node, $original_node, 'export'); |
| 382 |
|
$node_code = node_export_node_encode($node, $iteration); |
| 383 |
|
if ($return_code) { |
| 384 |
|
return $node_code; |
| 385 |
|
} |
| 386 |
|
if (variable_get('node_export_node_code', 'copy') == 'copy') { |
| 387 |
|
return drupal_get_form('node_export_form', $node_code); |
| 388 |
|
} |
| 389 |
|
else { |
| 390 |
|
node_export_get_file(array($original_node->nid), $node_code); |
| 391 |
|
} |
| 392 |
|
} |
| 393 |
|
} |
| 394 |
|
} |
| 395 |
|
|
| 396 |
|
/** |
| 397 |
|
* Export Form |
| 398 |
|
*/ |
| 399 |
|
function node_export_form($form_state, $code) { |
| 400 |
|
$form = array(); |
| 401 |
|
$form['export'] = array( |
| 402 |
|
'#type' => 'textarea', |
| 403 |
|
'#title' => t('Node Code'), |
| 404 |
|
'#default_value' => $code, |
| 405 |
|
'#rows' => 30, |
| 406 |
|
'#description' => t('Copy this code and then on the site you want to import to, go to the Import Node link under Content Management, and paste it in there.'), |
| 407 |
|
'#attributes' => array( |
| 408 |
|
'style' => 'width: 97%;', |
| 409 |
|
), |
| 410 |
|
); |
| 411 |
|
return $form; |
| 412 |
|
} |
| 413 |
|
|
| 414 |
|
/** |
| 415 |
|
* Check if all types in the import exist. Return TRUE/FALSE. |
| 416 |
|
*/ |
| 417 |
|
function node_export_import_types_check($import) { |
| 418 |
|
$types_exist = TRUE; |
| 419 |
|
if (is_array($import)) { |
| 420 |
|
foreach ($import as $new_node) { |
| 421 |
|
if (node_get_types('name', $new_node) == FALSE) { |
| 422 |
|
$types_exist = $new_node->type; |
| 423 |
|
} |
| 424 |
|
} |
| 425 |
|
} |
| 426 |
|
else { |
| 427 |
|
$new_node = $import; |
| 428 |
|
if (node_get_types('name', $new_node) == FALSE) { |
| 429 |
|
$types_exist = $new_node->type; |
| 430 |
|
} |
| 431 |
|
} |
| 432 |
|
|
| 433 |
|
if ($types_exist !== TRUE) { |
| 434 |
|
drupal_set_message(t('Error encountered during import. Node type %t unknown on this site. No nodes imported.', array('%t' => $types_exist)), 'error'); |
| 435 |
|
$types_exist = FALSE; |
| 436 |
|
} |
| 437 |
|
|
| 438 |
|
return $types_exist; |
| 439 |
|
} |
| 440 |
|
|
| 441 |
|
/** |
| 442 |
|
* Implementation of hook_theme(). |
| 443 |
|
*/ |
| 444 |
|
function node_export_theme() { |
| 445 |
|
return array( |
| 446 |
|
'node_export_node_prepopulate' => array( |
| 447 |
|
'arguments' => array( |
| 448 |
|
'element' => NULL, |
| 449 |
|
), |
| 450 |
|
), |
| 451 |
|
); |
| 452 |
|
} |
| 453 |
|
|
| 454 |
|
/** |
| 455 |
|
* Import Form |
| 456 |
|
*/ |
| 457 |
|
function node_export_import_form($form_state) { |
| 458 |
|
|
| 459 |
|
if (isset($form_state['storage']['values'])) { |
| 460 |
|
$values = &$form_state['storage']['values']; |
| 461 |
|
if ($values['file']) { |
| 462 |
|
$file = unserialize($values['file']); |
| 463 |
|
if (file_exists($file->filepath)) { |
| 464 |
|
$node_code = file_get_contents($file->filepath); |
| 465 |
|
unlink($file->filepath); |
| 466 |
|
} |
| 467 |
|
} |
| 468 |
|
elseif ($values['code']) { |
| 469 |
|
$node_code = trim($values['code']); |
| 470 |
|
} |
| 471 |
|
} |
| 472 |
|
|
| 473 |
|
if (isset($node_code)) { |
| 474 |
|
$import = node_export_node_decode($node_code); |
| 475 |
|
$types_exist = node_export_import_types_check($import); |
| 476 |
|
if ($types_exist) { |
| 477 |
|
if (is_array($import)) { |
| 478 |
|
foreach ($import as $new_node) { |
| 479 |
|
$new_nid = node_export_node_save($new_node); |
| 480 |
|
drupal_set_message(t("Imported !node", array('!node' => l($new_node->title, 'node/'. $new_nid)))); |
| 481 |
|
} |
| 482 |
|
drupal_goto('admin/content/node'); |
| 483 |
|
} |
| 484 |
|
else { |
| 485 |
|
return node_export_node_check($import); |
| 486 |
|
} |
| 487 |
|
} |
| 488 |
|
} |
| 489 |
|
|
| 490 |
|
$form = array(); |
| 491 |
|
$form['#attributes'] = array( |
| 492 |
|
'enctype' => "multipart/form-data", |
| 493 |
|
); |
| 494 |
|
$form['#prefix'] = t('<p>You may import nodes by pasting or uploading the results of exported nodes. </p>'); |
| 495 |
|
$method = variable_get('node_export_method', 'prepopulate'); |
| 496 |
|
if ($method == 'prepopulate') { |
| 497 |
|
$form['#prefix'] .= t('<p>If you are importing a single node, you will be given a prepopulated node add form which you must save to create the node.</p>'); |
| 498 |
|
} |
| 499 |
|
elseif ($method == 'save-edit') { |
| 500 |
|
$form['#prefix'] .= t('<p>If you are importing a single node, the node will be created and you will then be taken to the node edit page.</p>'); |
| 501 |
|
} |
| 502 |
|
$form['#prefix'] .= t('<p>To change this behaviour, <a href="/admin/settings/node_export">configure the settings</a>.</p>'); |
| 503 |
|
|
| 504 |
|
$form['upload'] = array( |
| 505 |
|
'#type' => 'fieldset', |
| 506 |
|
'#title' => t('Upload file'), |
| 507 |
|
'#collapsible' => TRUE, |
| 508 |
|
'#collapsed' => !$values['file'], |
| 509 |
|
); |
| 510 |
|
$form['upload']['file'] = array( |
| 511 |
|
'#type' => 'file', |
| 512 |
|
'#description' => t('To clear this field, !r.', array('!r' => l(t('reset the form'), $_GET['q']))) |
| 513 |
|
); |
| 514 |
|
$form['paste'] = array( |
| 515 |
|
'#type' => 'fieldset', |
| 516 |
|
'#title' => t('Paste code'), |
| 517 |
|
'#collapsible' => TRUE, |
| 518 |
|
'#collapsed' => !$values['code'], |
| 519 |
|
); |
| 520 |
|
$form['paste']['code'] = array( |
| 521 |
|
'#type' => 'textarea', |
| 522 |
|
'#default_value' => '', |
| 523 |
|
'#rows' => 30, |
| 524 |
|
'#description' => t('Cut and paste the results of an <em>Export Node</em> here.'), |
| 525 |
|
); |
| 526 |
|
$form['#redirect'] = FALSE; |
| 527 |
|
$form['submit'] = array( |
| 528 |
|
'#type' => 'submit', |
| 529 |
|
'#value' => t('Import'), |
| 530 |
|
'#suffix' => l(t('Reset the form'), $_GET['q']), |
| 531 |
|
); |
| 532 |
|
return $form; |
| 533 |
|
} |
| 534 |
|
|
| 535 |
|
/** |
| 536 |
|
* Validate function for beautifer form. |
| 537 |
|
*/ |
| 538 |
|
function node_export_import_form_validate($form, &$form_state) { |
| 539 |
|
if ($form_state['clicked_button']['#id'] == 'edit-submit' && |
| 540 |
|
!$_FILES['files']['name']['file'] && |
| 541 |
|
!$form_state['values']['code']) { |
| 542 |
|
drupal_set_message(t('Please upload a file or paste code to import.'), 'error'); |
| 543 |
|
form_set_error('', NULL); |
| 544 |
|
} |
| 545 |
|
} |
| 546 |
|
|
| 547 |
|
/** |
| 548 |
|
* Submit function for import form. |
| 549 |
|
*/ |
| 550 |
|
function node_export_import_form_submit($form, &$form_state) { |
| 551 |
|
if ($_FILES['files']['name']['file']) { |
| 552 |
|
$original = $_FILES['files']['name']['file']; |
| 553 |
|
$directory = file_directory_path() .'/'. NODE_EXPORT; |
| 554 |
|
if (file_check_directory($directory, FILE_CREATE_DIRECTORY)) { |
| 555 |
|
$save = file_save_upload('file', array(), $directory, FILE_EXISTS_RENAME); |
| 556 |
|
if (!$save) { |
| 557 |
|
drupal_set_message(t('Error: Node export could not save file.'), 'error'); |
| 558 |
|
} |
| 559 |
|
else { |
| 560 |
|
$save->original = $original; |
| 561 |
|
form_set_value($form['upload']['file'], serialize($save), $form_state); |
| 562 |
|
} |
| 563 |
|
} |
| 564 |
|
else { |
| 565 |
|
drupal_set_message(t('Error: Node export could not access files directory.'), 'error'); |
| 566 |
|
} |
| 567 |
|
} |
| 568 |
|
$form_state['storage']['values'] = $form_state['values']; |
| 569 |
|
} |
| 570 |
|
|
| 571 |
|
/** |
| 572 |
|
* Menu callback: prompt the user to confirm the operation |
| 573 |
|
* @return |
| 574 |
|
* A prepopulate form (if required). |
| 575 |
|
*/ |
| 576 |
|
function node_export_node_check($node) { |
| 577 |
|
|
| 578 |
|
$method = variable_get('node_export_method', 'prepopulate'); |
| 579 |
|
|
| 580 |
|
switch ($method) { |
| 581 |
|
case 'save-edit': |
| 582 |
|
$new_nid = node_export_node_save($node); |
| 583 |
|
drupal_goto('node/'. $new_nid .'/edit'); |
| 584 |
|
break; |
| 585 |
|
case 'prepopulate': |
| 586 |
|
default: |
| 587 |
|
include_once(drupal_get_path('module', 'node') .'/node.pages.inc'); |
| 588 |
|
return node_export_node_prepopulate($node); |
| 589 |
|
break; |
| 590 |
|
} |
| 591 |
|
} |
| 592 |
|
|
| 593 |
|
/** |
| 594 |
|
* Exports a node - prepopulate a node editing form |
| 595 |
|
* @return |
| 596 |
|
* A prepopulate form. |
| 597 |
|
*/ |
| 598 |
|
function node_export_node_prepopulate($original_node) { |
| 599 |
|
if (node_export_is_permitted($original_node->type)) { |
| 600 |
|
$node = node_export_node_clone($original_node, "prepopulate"); |
| 601 |
|
$form_id = $node->type .'_node_form'; |
| 602 |
|
$form = array(); |
| 603 |
|
$form['node_form']['#value'] = drupal_get_form($form_id, $node); |
| 604 |
|
$form['#theme'] = 'node_export_node_prepopulate'; |
| 605 |
|
$form['#action'] = url('node/add/'. $node->type); |
| 606 |
|
return $form; |
| 607 |
|
} |
| 608 |
|
} |
| 609 |
|
|
| 610 |
|
/** |
| 611 |
|
* Theme function facilitates rendering of prepopulate form. |
| 612 |
|
*/ |
| 613 |
|
function theme_node_export_node_prepopulate($element) { |
| 614 |
|
return $element['node_form']['#value']; |
| 615 |
|
} |
| 616 |
|
|
| 617 |
|
/** |
| 618 |
|
* Exports a node by directly saving it. |
| 619 |
|
*/ |
| 620 |
|
function node_export_node_save($original_node) { |
| 621 |
|
if (node_export_is_permitted($original_node->type)) { |
| 622 |
|
$node = node_export_node_clone($original_node, "save-edit"); |
| 623 |
|
node_save($node); |
| 624 |
|
return $node->nid; |
| 625 |
|
} |
| 626 |
|
} |
| 627 |
|
|
| 628 |
|
/** |
| 629 |
|
* Prepare a clone of the node during import. |
| 630 |
|
*/ |
| 631 |
|
function node_export_node_clone($original_node, $mode) { |
| 632 |
|
global $user; |
| 633 |
|
|
| 634 |
|
$node = drupal_clone($original_node); |
| 635 |
|
|
| 636 |
|
$node->nid = NULL; |
| 637 |
|
$node->vid = NULL; |
| 638 |
|
|
| 639 |
|
$node->name = $user->name; |
| 640 |
|
$node->uid = $user->uid; |
| 641 |
|
|
| 642 |
|
if (variable_get('node_export_reset_created_'. $node->type, TRUE)) { |
| 643 |
|
$node->created = NULL; |
| 644 |
|
} |
| 645 |
|
|
| 646 |
|
if (variable_get('node_export_reset_menu_'. $node->type, TRUE)) { |
| 647 |
|
$node->menu = NULL; |
| 648 |
|
} |
| 649 |
|
|
| 650 |
|
if (variable_get('node_export_reset_path_'. $node->type, TRUE)) { |
| 651 |
|
$node->path = NULL; |
| 652 |
|
} |
| 653 |
|
|
| 654 |
|
if (variable_get('node_export_reset_book_mlid_'. $node->type, TRUE) && isset($node->book['mlid'])) { |
| 655 |
|
$node->book['mlid'] = NULL; |
| 656 |
|
} |
| 657 |
|
|
| 658 |
|
$node->files = array(); |
| 659 |
|
|
| 660 |
|
if (variable_get('node_export_reset_'. $node->type, FALSE)) { |
| 661 |
|
$node_options = variable_get('node_options_'. $node->type, array('status', 'promote')); |
| 662 |
|
// Fill in the default values. |
| 663 |
|
foreach (array('status', 'moderate', 'promote', 'sticky', 'revision') as $key) { |
| 664 |
|
$node->$key = in_array($key, $node_options); |
| 665 |
|
} |
| 666 |
|
} |
| 667 |
|
// Let other modules do special fixing up. |
| 668 |
|
// The function signature is: hook_export_node_alter(&$node, $original_node, $method) |
| 669 |
|
// Where $method is either 'prepopulate' or 'save-edit'. |
| 670 |
|
drupal_alter('node_export_node', $node, $original_node, $mode); |
| 671 |
|
|
| 672 |
|
return $node; |
| 673 |
|
|
| 674 |
|
} |
| 675 |
|
|
| 676 |
|
/** |
| 677 |
|
* Build node code string recursively |
| 678 |
|
*/ |
| 679 |
|
function node_export_node_encode($var, $iteration = 0) { |
| 680 |
|
$tab = ''; |
| 681 |
|
for ($i = 0; $i < $iteration; $i++) { |
| 682 |
|
$tab = $tab ." "; |
| 683 |
|
} |
| 684 |
|
$iteration++; |
| 685 |
|
if (is_object($var)) { |
| 686 |
|
$var = (array)$var; |
| 687 |
|
$var['#_export_node_encode_object'] = '1'; |
| 688 |
|
} |
| 689 |
|
if (is_array($var)) { |
| 690 |
|
$empty = empty($var); |
| 691 |
|
$code = "array(". ($empty ? '' : "\n"); |
| 692 |
|
foreach ($var as $key => $value) { |
| 693 |
|
$out = $tab ." '". $key ."' => ". node_export_node_encode($value, $iteration) .",\n"; |
| 694 |
|
drupal_alter('node_export_node_encode', $out, $tab, $key, $value, $iteration); |
| 695 |
|
$code .= $out; |
| 696 |
|
} |
| 697 |
|
$code .= ($empty ? '' : $tab) .")"; |
| 698 |
|
return $code; |
| 699 |
|
} |
| 700 |
|
else { |
| 701 |
|
if (is_string($var)) { |
| 702 |
|
return "'". addslashes($var) ."'"; |
| 703 |
|
} |
| 704 |
|
elseif (is_numeric($var)) { |
| 705 |
|
return $var; |
| 706 |
|
} |
| 707 |
|
elseif (is_bool($var)) { |
| 708 |
|
return ($var ? 'TRUE' : 'FALSE'); |
| 709 |
|
} |
| 710 |
|
else { |
| 711 |
|
return 'NULL'; |
| 712 |
|
} |
| 713 |
|
} |
| 714 |
|
} |
| 715 |
|
|
| 716 |
|
/** |
| 717 |
|
* Evaluate and return decoded string. |
| 718 |
|
*/ |
| 719 |
|
function node_export_node_decode($string) { |
| 720 |
|
$array = eval('return '. $string .';'); |
| 721 |
|
$return = node_export_node_decode_objects($array); |
| 722 |
|
return $return; |
| 723 |
|
} |
| 724 |
|
|
| 725 |
|
/** |
| 726 |
|
* Recursively convert arrays back to objects. |
| 727 |
|
*/ |
| 728 |
|
function node_export_node_decode_objects($array) { |
| 729 |
|
foreach ($array as $k => $v) { |
| 730 |
|
if (is_array($v)) { |
| 731 |
|
$array[$k] = node_export_node_decode_objects($v); |
| 732 |
|
} |
| 733 |
|
if (is_string($v)) { |
| 734 |
|
$array[$k] = stripslashes($v); |
| 735 |
|
} |
| 736 |
|
} |
| 737 |
|
if ($array['#_export_node_encode_object']) { |
| 738 |
|
unset($array['#_export_node_encode_object']); |
| 739 |
|
$array = (object)$array; |
| 740 |
|
} |
| 741 |
|
return $array; |
| 742 |
|
} |
| 743 |
|
|
| 744 |
|
/** |
| 745 |
|
* Create a new menu entry with title, parent and weight exported from |
| 746 |
|
* another nodes menu. Returns NULL if the node has no menu title. |
| 747 |
|
*/ |
| 748 |
|
function node_export_get_menu($node) { |
| 749 |
|
// This will fetch the existing menu item if the node had one. |
| 750 |
|
node_invoke_nodeapi($node, 'prepare'); |
| 751 |
|
|
| 752 |
|
// Only keep the values we care about. |
| 753 |
|
if (!empty($node->menu)) { |
| 754 |
|
|
| 755 |
|
// Store a copy of the old menu |
| 756 |
|
$old_menu = $node->menu; |
| 757 |
|
|
| 758 |
|
// Now fetch the defaults for a new menu entry. |
| 759 |
|
$node = NULL; |
| 760 |
|
node_invoke_nodeapi($node, 'prepare'); |
| 761 |
|
|
| 762 |
|
// Make a list of values to attempt to copy. |
| 763 |
|
$menu_fields = array( |
| 764 |
|
'link_title', 'plid', 'menu_name', 'weight', // These should import properly always. |
| 765 |
|
'hidden', 'expanded', 'has_children', // These will only import properly on 'Save as a new node then edit' imports. |
| 766 |
|
); |
| 767 |
|
|
| 768 |
|
// Copy those fields from the old menu over the new menu defaults. |
| 769 |
|
foreach ($menu_fields as $menu_field) { |
| 770 |
|
$node->menu[$menu_field] = $old_menu[$menu_field]; |
| 771 |
|
} |
| 772 |
|
|
| 773 |
|
// Return the menu. |
| 774 |
|
return $node->menu; |
| 775 |
|
} |
| 776 |
|
|
| 777 |
} |
} |