clone.pages.inc 8.4 KB

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