clone.pages.inc 8.9 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258
  1. <?php
  2. /**
  3. * @file
  4. * Additional functions for Node_Clone module.
  5. */
  6. /**
  7. * Menu callback to configure module settings.
  8. */
  9. function clone_settings($form, &$form_state) {
  10. $form['basic'] = array(
  11. '#type' => 'fieldset',
  12. '#title' => t('General settings'),
  13. );
  14. $form['basic']['clone_method'] = array(
  15. '#type' => 'radios',
  16. '#title' => t('Method to use when cloning a node'),
  17. '#options' => array('prepopulate' => t('Pre-populate the node form fields'), 'save-edit' => t('Save as a new node then edit')),
  18. '#default_value' => variable_get('clone_method', 'prepopulate'),
  19. );
  20. $form['basic']['clone_nodes_without_confirm'] = array(
  21. '#type' => 'radios',
  22. '#title' => t('Confirmation mode when using the "Save as a new node then edit" method'),
  23. '#default_value' => (int)variable_get('clone_nodes_without_confirm', 0),
  24. '#options' => array(t('Require confirmation (recommended)'), t('Bypass confirmation')),
  25. '#description' => t('A new node may be saved immediately upon clicking the "clone" link when viewing a node, bypassing the normal confirmation form.'),
  26. '#states' => array(
  27. // Only show this field when the clone method is save-edit.
  28. 'visible' => array(
  29. ':input[name="clone_method"]' => array('value' => 'save-edit'),
  30. ),
  31. ),
  32. );
  33. $form['basic']['clone_menu_links'] = array(
  34. '#type' => 'radios',
  35. '#title' => t('Clone menu links'),
  36. '#options' => array(0 => t('No'), 1 => t('Yes')),
  37. '#default_value' => (int) variable_get('clone_menu_links', 0),
  38. '#description' => t('Should any menu link for a node also be cloned?'),
  39. );
  40. $form['basic']['clone_use_node_type_name'] = array(
  41. '#type' => 'checkbox',
  42. '#title' => t('Use node type name in clone link'),
  43. '#default_value' => (int) variable_get('clone_use_node_type_name', 0),
  44. '#description' => t('If checked, the link to clone the node will contain the node type name, for example, "Clone this article", otherwise it will read "Clone content".'),
  45. );
  46. $form['publishing'] = array(
  47. '#type' => 'fieldset',
  48. '#title' => t('Should the publishing options ( e.g. published, promoted, etc) be reset to the defaults?'),
  49. );
  50. $types = node_type_get_names();
  51. foreach ($types as $type => $name) {
  52. $form['publishing']['clone_reset_' . $type] = array(
  53. '#type' => 'checkbox',
  54. '#title' => t('@s: reset publishing options when cloned', array('@s' => $name)),
  55. '#default_value' => variable_get('clone_reset_' . $type, FALSE),
  56. );
  57. }
  58. // Need the variable default key to be something that's never a valid node type.
  59. $form['omit'] = array(
  60. '#type' => 'fieldset',
  61. '#title' => t('Content types that are not to be cloned - omitted due to incompatibility'),
  62. );
  63. $form['omit']['clone_omitted'] = array(
  64. '#type' => 'checkboxes',
  65. '#title' => t('Omitted content types'),
  66. '#default_value' => variable_get('clone_omitted', array()),
  67. '#options' => $types,
  68. '#description' => t('Select any node types which should <em>never</em> be cloned. In other words, all node types where cloning will fail.'),
  69. );
  70. return system_settings_form($form);
  71. }
  72. /**
  73. * Menu callback: prompt the user to confirm the operation
  74. */
  75. function clone_node_check($node) {
  76. $method = variable_get('clone_method', 'prepopulate');
  77. switch ($method) {
  78. case 'save-edit':
  79. if (variable_get('clone_nodes_without_confirm', FALSE)) {
  80. $new_nid = clone_node_save($node->nid);
  81. $options = array();
  82. if (!empty($_GET['node-clone-destination'])) {
  83. $options['query']['destination'] = $_GET['node-clone-destination'];
  84. }
  85. drupal_goto('node/' . $new_nid . '/edit', $options);
  86. }
  87. else {
  88. return drupal_get_form('clone_node_confirm', $node);
  89. }
  90. break;
  91. case 'prepopulate':
  92. default:
  93. return clone_node_prepopulate($node);
  94. break;
  95. }
  96. }
  97. /**
  98. * form builder: prompt the user to confirm the operation
  99. */
  100. function clone_node_confirm($form, &$form_state, $node) {
  101. $form['nid'] = array('#type' => 'value', '#value' => $node->nid);
  102. return confirm_form($form,
  103. t('Are you sure you want to clone %title?', array('%title' => $node->title)),
  104. 'node/' . $node->nid, '<p>' . t('This action will create a new node. You will then be redirected to the edit page for the new node.') . '</p>',
  105. t('Clone'), t('Cancel'));
  106. }
  107. /**
  108. * Handle confirm form submission
  109. */
  110. function clone_node_confirm_submit($form, &$form_state) {
  111. if ($form_state['values']['confirm']) {
  112. $new_nid = clone_node_save($form_state['values']['nid']);
  113. }
  114. $form_state['redirect'] = 'node/' . $new_nid . '/edit';
  115. }
  116. /**
  117. * Create a new menu link cloned from another node.
  118. *
  119. * Returns NULL if no existing link, or links are not to be cloned.
  120. */
  121. function clone_node_clone_menu_link($node) {
  122. if (variable_get('clone_menu_links', FALSE) && function_exists('menu_node_prepare')) {
  123. // This will fetch the existing menu link if the node had one.
  124. menu_node_prepare($node);
  125. if (!empty($node->menu['mlid'])) {
  126. $old_link = $node->menu;
  127. $link['link_title'] = t('Clone of !title', array('!title' => $old_link['link_title']));
  128. $link['plid'] = $old_link['plid'];
  129. $link['menu_name'] = $old_link['menu_name'];
  130. $link['weight'] = $old_link['weight'];
  131. $link['module'] = $old_link['module'];
  132. // Use the value -1 because it casts to boolean TRUE in function
  133. // menu_form_node_form_alter() in menu.module so the node form checkbox
  134. // is selected, but in function menu_link_save() no existing link will
  135. // match.
  136. $link['mlid'] = -1;
  137. $link['has_children'] = 0;
  138. $link['hidden'] = $old_link['hidden'];
  139. $link['customized'] = $old_link['customized'];
  140. $link['options'] = $old_link['options'];
  141. $link['expanded'] = $old_link['expanded'];
  142. $link['description'] = $old_link['description'];
  143. $link['language'] = isset($old_link['language']) ? $old_link['language'] : NULL;
  144. // This is needed to get the link saved in function menu_node_save() when
  145. // using the save-edit method.
  146. $link['enabled'] = TRUE;
  147. return $link;
  148. }
  149. }
  150. return NULL;
  151. }
  152. /**
  153. * Clones a node - prepopulate a node editing form
  154. */
  155. function clone_node_prepopulate($original_node) {
  156. if (isset($original_node->nid)) {
  157. if (clone_is_permitted($original_node->type)) {
  158. $node = _clone_node_prepare($original_node, TRUE);
  159. drupal_set_title($node->title);
  160. // Let other modules do special fixing up.
  161. $context = array('method' => 'prepopulate', 'original_node' => $original_node);
  162. drupal_alter('clone_node', $node, $context);
  163. // Make sure the file defining the node form is loaded.
  164. $form_state = array();
  165. $form_state['build_info']['args'] = array($node);
  166. form_load_include($form_state, 'inc', 'node', 'node.pages');
  167. return drupal_build_form($node->type . '_node_form', $form_state);
  168. }
  169. }
  170. }
  171. /**
  172. * Clones a node by directly saving it.
  173. */
  174. function clone_node_save($nid, $account = NULL) {
  175. if (is_numeric($nid)) {
  176. $original_node = node_load($nid);
  177. if (isset($original_node->nid) && clone_is_permitted($original_node->type)) {
  178. $node = _clone_node_prepare($original_node, TRUE, $account);
  179. // Let other modules do special fixing up.
  180. $context = array('method' => 'save-edit', 'original_node' => $original_node);
  181. drupal_alter('clone_node', $node, $context);
  182. node_save($node);
  183. if (module_exists('rules')) {
  184. rules_invoke_event('clone_node', $node, $original_node);
  185. }
  186. return $node->nid;
  187. }
  188. }
  189. }
  190. /**
  191. * Prepares a node to be cloned.
  192. */
  193. function _clone_node_prepare($original_node, $prefix_title = FALSE, $account = NULL) {
  194. $node = clone $original_node;
  195. if (!isset($account->uid)) {
  196. $account = $GLOBALS['user'];
  197. }
  198. $node->nid = NULL;
  199. $node->vid = NULL;
  200. $node->tnid = NULL;
  201. $node->log = NULL;
  202. // Also handle modules that attach a UUID to the node.
  203. $node->uuid = NULL;
  204. $node->vuuid = NULL;
  205. // Anyonmymous users don't have a name.
  206. // @see: drupal_anonymous_user().
  207. $node->name = isset($account->name) ? $account->name : NULL;
  208. $node->uid = $account->uid;
  209. $node->created = NULL;
  210. $node->menu = clone_node_clone_menu_link($original_node);
  211. if (isset($node->book['mlid'])) {
  212. $node->book['mlid'] = NULL;
  213. $node->book['has_children'] = 0;
  214. }
  215. $node->path = NULL;
  216. $node->files = array();
  217. if ($prefix_title) {
  218. $node->title = t('Clone of !title', array('!title' => $node->title));
  219. }
  220. // Add an extra property as a flag.
  221. $node->clone_from_original_nid = $original_node->nid;
  222. if (variable_get('clone_reset_' . $node->type, FALSE)) {
  223. $node_options = variable_get('node_options_' . $node->type, array('status', 'promote'));
  224. // Fill in the default values.
  225. foreach (array('status', 'moderate', 'promote', 'sticky', 'revision') as $key) {
  226. // Cast to int since that's how they need to be saved to the DB.
  227. $node->$key = (int) in_array($key, $node_options);
  228. }
  229. }
  230. return $node;
  231. }