mb_content.module 17 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512
  1. <?php
  2. /**
  3. * @file
  4. * Provides additional buttons for nodes.
  5. *
  6. * Currently available buttons:
  7. * - Cancel
  8. * - Save and Continue
  9. *
  10. * Furthermore available is the Create new action.
  11. * - The action can used as tab in addition to the node View or node Edit tab.
  12. * - The action can used as action link.
  13. *
  14. * @todo
  15. * OG compatibility
  16. */
  17. /**
  18. * Implements hook_permission().
  19. */
  20. function mb_content_permission() {
  21. return array(
  22. 'access mb content' => array(
  23. 'title' => t('Use More Content Buttons'),
  24. 'description' => t('Use the buttons defined by More Buttons Content.')
  25. )
  26. );
  27. }
  28. /**
  29. * Implements hook_menu().
  30. */
  31. function mb_content_menu() {
  32. $items = array();
  33. $items['admin/config/mb/buttons/more-buttons-content'] = array(
  34. 'page callback' => 'drupal_get_form',
  35. 'page arguments' => array('mb_content_admin'),
  36. 'title' => 'Contents',
  37. 'access arguments' => array('administer site configuration'),
  38. 'description' => 'An overview of what content type uses buttons/functions of the MB Content module.',
  39. 'file' => 'mb_content.admin.inc',
  40. 'type' => MENU_LOCAL_TASK,
  41. 'weight' => 9
  42. );
  43. $items['admin/config/mb/buttons/more-buttons-content/reset'] = array(
  44. 'page callback' => 'drupal_get_form',
  45. 'page arguments' => array('mb_content_reset'),
  46. 'access arguments' => array('administer site configuration'),
  47. 'type' => MENU_CALLBACK,
  48. 'file' => 'mb_content.admin.inc'
  49. );
  50. return $items;
  51. }
  52. /**
  53. * Title callback to provide the title for the create new tab.
  54. *
  55. * @return string
  56. */
  57. function mb_content_createnew_title() {
  58. $mb_default_values = mb_default_values('mb_content');
  59. $mb_values = variable_get('mb_values', array());
  60. return isset($mb_values['tabcn']) ? $mb_values['tabcn'] : $mb_default_values['tabcn'];
  61. }
  62. /**
  63. * Implements hook_theme().
  64. */
  65. function mb_content_theme() {
  66. return array(
  67. 'mb_content_admin' => array(
  68. 'variables' => array('form' => NULL),
  69. )
  70. );
  71. }
  72. /**
  73. * Implements hook_form_alter().
  74. */
  75. function mb_content_form_alter(&$form, &$form_state, $form_id) {
  76. // Make sure the form alter changes take place only in certain forms.
  77. // Get the right node types.
  78. $node_type = '';
  79. $module = 'mb_content';
  80. // Node add/edit forms.
  81. if (isset($form['#node']->type) && isset($form['#node_edit_form'])) {
  82. $node_type = $form['#node']->type;
  83. }
  84. // Preparing the administration of MB Content; Content type edit form.
  85. elseif (isset($form['type']) && !empty($form['#type']['#value']) && isset($form['#node_edit_form'])) {
  86. $node_type = $form['#type']['#value'];
  87. }
  88. // Prepare the administration of MB Content; Content type add form.
  89. elseif (isset($form['#node']->type) && empty($form['#type']['#value']) && isset($form['#node_edit_form'])) {
  90. // Use temporary an content type as dummy to handle button management on the "Add content type" page.
  91. $node_type = 'mb_content_type_dummy';
  92. }
  93. switch ($form_id) {
  94. case 'node_type_form':
  95. // Provide the prepared MB Content button settings.
  96. // Check the specific case add content type form.
  97. if (empty($form['#node_type']->type)) {
  98. // Add content type.
  99. $type = 'mb_content_type_dummy';
  100. }
  101. else {
  102. // Edit an content type.
  103. $type = $form['#node_type']->type;
  104. }
  105. // It makes no sense to use the MB Content module with the content type panel.
  106. if ($type == 'panel') {
  107. return;
  108. }
  109. /**
  110. * The additional buttons and tab settings.
  111. */
  112. $form['node_buttons'] = array(
  113. '#type' => 'fieldset',
  114. '#title' => t('Button settings - content'),
  115. '#group' => 'additional_settings',
  116. '#collapsible' => TRUE,
  117. '#collapsed' => TRUE,
  118. '#weight' => 4,
  119. '#attached' => array(
  120. 'js' => array(drupal_get_path('module', $module) . '/' . $module . '_node_form.js')
  121. )
  122. );
  123. // Provide "Cancel" button settings.
  124. $form['node_buttons'][$module . '_cancel'] = array(
  125. '#type' => 'select',
  126. '#title' => t('Cancel button'),
  127. '#description' => t('Please select using the button or its position.'),
  128. '#options' => mb_cancel_button_positions(),
  129. '#default_value' => variable_get($module . '_cancel_' . $type, 0)
  130. );
  131. // Provide "Save and continue" button settings.
  132. $form['node_buttons'][$module . '_sac'] = array(
  133. '#type' => 'select',
  134. '#title' => t('Save and continue button'),
  135. '#description' => t('Please select using the button or its position.'),
  136. '#options' => mb_save_button_positions($module),
  137. '#default_value' => variable_get($module . '_sac_' . $type, 0)
  138. );
  139. // Provide the "Create new" tab option.
  140. $form['node_buttons'][$module . '_tabcn'] = array(
  141. '#type' => 'checkbox',
  142. '#title' => t('Create new tab'),
  143. '#description' => t('Enable an "Create new" tab in addition to the %view or %edit tab.', array('%view' => t('View'), '%edit' => t('Edit'))),
  144. '#default_value' => variable_get($module . '_tabcn_' . $type, 0)
  145. );
  146. // Use an own submit callback to save the settings
  147. // on the add/edit content type forms.
  148. $form['#submit'][] = 'mb_content_admin_form_submit';
  149. break;
  150. case 'node_type_delete_confirm':
  151. // Use an own submit callback to delete MB Content
  152. // content type system variables if content types will be deleted.
  153. $form['#submit'][] = 'mb_content_delete_confirm_submit';
  154. break;
  155. case $node_type . '_node_form':
  156. // It makes no sense to use the MB Content module with the content type panel.
  157. if ($node_type == 'panel') {
  158. return;
  159. }
  160. $mb_default_values = mb_default_values();
  161. $mb_content_values = mb_get_values('mb');
  162. $destination = drupal_get_destination();
  163. $settings = array();
  164. $settings['cancel'] = variable_get($module . '_cancel_' . $node_type, 0);
  165. $settings['sac'] = variable_get($module . '_sac_' . $node_type, 0);
  166. $settings['tabcn'] = variable_get($module . '_tabcn_' . $node_type, 0);
  167. // Insert the referer.
  168. $referer = preg_replace('/.*\/node\//', 'node/', url($_SERVER["HTTP_REFERER"]));
  169. $form['#referer'] = $referer;
  170. $form_state['cache'] = TRUE;
  171. /**
  172. * Destination parameter handling.
  173. *
  174. * Deactivate the destination parameter
  175. * and keep these parameter in order to be able to use it anyway.
  176. */
  177. if (preg_match('/\?destination/', $form['#action'])) {
  178. $form_state['storage']['#mb_redirect'] = preg_replace('/^.*\?destination\=/', '', $form['#action']);
  179. }
  180. elseif (preg_match('/\?destination/', $form['#referer'])) {
  181. $form_state['storage']['#mb_redirect'] = preg_replace('/^.*\?destination\=/', '', $form['#referer']);
  182. }
  183. $form['#action'] = preg_replace('/\?destination.*/', '', $form['#action']);
  184. if (isset($form_state['storage']['#mb_redirect'])) {
  185. $form['storage']['#mb_redirect'] = $form_state['storage']['#mb_redirect'];
  186. }
  187. elseif (isset($form['storage']['#mb_redirect'])) {
  188. $form_state['#mb_redirect'] = $form['storage']['#mb_redirect'];
  189. }
  190. // Identify the "Create new" tab action.
  191. if (preg_match('/node\/\d+/', $referer) && !isset($form_state['clicked_button']['#id'])) {
  192. $form['#tabcn_referer'] = $referer;
  193. }
  194. /**
  195. * The "Save and continue" form element.
  196. */
  197. if ($settings['sac'] > 0) {
  198. // Left of Save.
  199. if ($settings['sac'] == 1) {
  200. $weight_sac = $form['actions']['submit']['#weight'] - 0.025;
  201. }
  202. // Right of Save
  203. if ($settings['sac'] == 2) {
  204. $weight_sac = $form['actions']['submit']['#weight'] + 0.025;
  205. }
  206. // Define the "Save and continue" form element.
  207. $form['actions']['sac'] = array(
  208. '#type' => 'submit',
  209. '#value' => isset($mb_content_values['sac']) ? t('@sac-value', array('@sac-value' => t($mb_content_values['sac']))) : t($mb_default_values['sac']),
  210. '#weight' => $weight_sac,
  211. '#validate' => array('mb_content_changed_validate'),
  212. '#submit' => array('node_form_submit', 'mb_content_sac_submit')
  213. );
  214. }
  215. /**
  216. * The "Cancel" form element.
  217. */
  218. if ($settings['cancel'] > 0) {
  219. if ($settings['cancel'] == 1) {
  220. $weight_cancel = $form['actions']['submit']['#weight'] - 1;
  221. }
  222. elseif ($settings['cancel'] == 2) {
  223. $weight_cancel = 16;
  224. }
  225. // Define the "Cancel" form element.
  226. $form['actions']['cancel'] = array(
  227. '#type' => 'submit',
  228. '#value' => isset($mb_content_values['cancel']) ? t('@cancel-value', array('@cancel-value' => t($mb_content_values['cancel']))) : t($mb_default_values['cancel']),
  229. '#weight' => $weight_cancel,
  230. '#validate' => array('mb_content_cancel_validate'),
  231. '#limit_validation_errors' => array(),
  232. );
  233. }
  234. /**
  235. * Extra validation for the standard buttons.
  236. * Without this break the normal form handling.
  237. * @see mb_content_cancel_validate(), mb_content_changed_submit()
  238. * Call edit form from admin/content is no needed this callbacks.
  239. */
  240. if ($settings['sac'] > 0 || $destination['destination'] != 'admin/content') {
  241. $form['actions']['preview']['#validate'][] = 'mb_content_changed_validate';
  242. $form['actions']['submit']['#validate'][] = 'mb_content_changed_validate';
  243. $form['actions']['delete']['#validate'][] = 'mb_content_changed_validate';
  244. // Corresponding submit callbacks.
  245. $form['actions']['preview']['#submit'][] = 'mb_content_changed_submit';
  246. $form['actions']['submit']['#submit'][] = 'mb_content_changed_submit';
  247. }
  248. // OG compatibility.
  249. // Provide the group ID.
  250. // Add an new group article.
  251. // if (isset($_GET['gids_node'])) {
  252. // $gids_node = $_GET['gids_node'];
  253. // $form['#mnb']['og']['group_id'] = (int)$gids_node[0];
  254. // }
  255. // Edit an group article.
  256. // $og_context = module_invoke('og', 'get_context_by_url');
  257. // if (isset($og_context->nid)) {
  258. // $form['#mnb']['og']['group_id'] = $og_context->nid;
  259. // }
  260. break;
  261. }
  262. }
  263. /**
  264. * Implements hook_menu_local_tasks_alter().
  265. *
  266. * Alter the node local tasks to
  267. * - use an destination parameter
  268. * - provide the "Create new" tab.
  269. */
  270. function mb_content_menu_local_tasks_alter(&$data, $router_item, $root_path) {
  271. global $base_url;
  272. $destination = drupal_get_destination();
  273. $module = 'mb_content';
  274. if ($router_item['tab_root'] == 'node/%') {
  275. $node = $router_item['map'][1];
  276. $node_type_name = node_type_get_name($node);
  277. // Add Create new as local task tab.
  278. // Note: access_callback no works.
  279. if (variable_get('mb_content_tabcn_' . $node->type, 0) == 1) {
  280. // Note: The weight setting are not accepted.
  281. // Organize the proper tab weight for the new "Create new" tab to display the new tab on the right position.
  282. $holder = array();
  283. // User with node edit permission. The tabs are displayed and the Edit tab exists.
  284. if (isset($data['tabs'][0]['output'][1]) && $data['tabs'][0]['output'][1]['#link']['page_callback'] == 'node_page_edit') {
  285. $holder = array_splice($data['tabs'][0]['output'], 2);
  286. }
  287. // User without node edit permission. The tabs are displayed and the Edit tab is not exist.
  288. elseif (isset($data['tabs'][0]['output'][1]) && $data['tabs'][0]['output'][1]['#link']['page_callback'] != 'node_page_edit') {
  289. $holder = array_splice($data['tabs'][0]['output'], 1);
  290. }
  291. // Insert the new tab.
  292. $data['tabs'][0]['output'][] = array(
  293. '#theme' => 'menu_local_task',
  294. '#link' => array(
  295. 'title' => mb_content_createnew_title(),
  296. 'href' => 'node/add/' . $node->type,
  297. 'tab_root_href' => 'node/' . $node->nid,
  298. 'weight' => 2,
  299. 'localized_options' => array(
  300. 'attributes' => array(
  301. 'title' => t('Create new @content', array('@content' => t($node_type_name))),
  302. )
  303. )
  304. )
  305. );
  306. // Rebuild the tabs to display all tabs.
  307. $data['tabs'][0]['output'] = array_merge($data['tabs'][0]['output'], $holder);
  308. }
  309. // Add Create new as action link.
  310. if ($root_path == 'node/%/edit' && variable_get('mb_content_tabcn_' . $node->type, 0) == 2) {
  311. $css_node_type = str_replace('_', '-', $node->type);
  312. $item = menu_get_item('node/add/' . $node->type);
  313. $item['title'] = t('Create new @content', array('@content' => t($node_type_name)));
  314. $item['localized_options']['attributes']['class'] = array('node-action-link', 'node-action-link-' . $css_node_type);
  315. $data['actions']['output'][] = array(
  316. '#theme' => 'menu_local_action',
  317. '#link' => $item,
  318. );
  319. }
  320. }
  321. }
  322. /**
  323. * Implements hook_form_validate().
  324. *
  325. * Handle the "Cancel" validation.
  326. */
  327. function mb_content_cancel_validate($form, &$form_state) {
  328. // This is the cancel action. No validation required.
  329. mb_content_cancel_action($form, $form_state);
  330. }
  331. /**
  332. * Implements hook_form_validate().
  333. *
  334. * Skip the function node_last_changed().
  335. */
  336. function mb_content_changed_validate($form, &$form_state) {
  337. $form['changed']['#default_value'] = 0;
  338. }
  339. /**
  340. * Implements hook_form_submit().
  341. *
  342. * Handle different submit actions and make different redirects.
  343. * - "Preview"
  344. * - "Save"
  345. * - "Delete"
  346. */
  347. function mb_content_changed_submit($form, &$form_state) {
  348. $redirect = '<front>';
  349. if ($form_state['clicked_button']['#id'] == 'edit-preview') {
  350. $form_state['redirect'] = FALSE;
  351. }
  352. if ($form_state['clicked_button']['#id'] == 'edit-submit') {
  353. $redirect = 'node/' . $form_state['nid'];
  354. drupal_goto($redirect);
  355. }
  356. if ($form_state['clicked_button']['#id'] == 'edit-delete') {
  357. $form_state['redirect'] = $redirect;
  358. }
  359. }
  360. /**
  361. * The "Cancel" action.
  362. *
  363. * Handle different submit actions and make different redirects.
  364. *
  365. * @see mb_content_cancel_validate()
  366. */
  367. function mb_content_cancel_action($form, &$form_state) {
  368. // Hide the error messages.
  369. drupal_get_messages('error');
  370. $redirect = '<front>';
  371. // $options query example:
  372. // array('query' => array('destination' => 'node/' . $node->nid))
  373. $options = array();
  374. if (arg(0) === 'node' && arg(1) === 'add') {
  375. // Limitation:
  376. // Exist only one content type this redirect does not work.
  377. $redirect = 'node/add';
  378. if (isset($form['#tabcn_referer'])) {
  379. $redirect = $form['#tabcn_referer'];
  380. }
  381. }
  382. if (arg(0) === 'node' && is_numeric(arg(1)) && arg(2) === 'edit') {
  383. $redirect = 'node/' . arg(1);
  384. }
  385. if (isset($form_state['storage']['#mb_redirect'])) {
  386. $redirect = $form_state['storage']['#mb_redirect'];
  387. }
  388. elseif (isset($form['storage']['#mb_redirect'])) {
  389. $redirect = $form['storage']['#mb_redirect'];
  390. }
  391. drupal_goto($redirect, $options);
  392. }
  393. /**
  394. * Implements hook_form_submit().
  395. *
  396. * Handle the "Save and continue" action.
  397. */
  398. function mb_content_sac_submit($form, &$form_state) {
  399. $destination = drupal_get_destination();
  400. $nid = $form_state['build_info']['args'][0]->nid;
  401. $redirect = 'node/' . $nid . '/edit';
  402. $form_state['rebuild'] = TRUE;
  403. if (isset($form_state['storage']['#mb_redirect'])) {
  404. $form['storage']['#mb_redirect'] = $form_state['storage']['#mb_redirect'];
  405. }
  406. elseif (isset($form['storage']['#mb_redirect'])) {
  407. $form_state['#mb_redirect'] = $form['storage']['#mb_redirect'];
  408. }
  409. // Is meant edit nodes from content management page.
  410. if ($destination['destination'] != 'admin/content') {
  411. drupal_get_messages('error');
  412. $form_state['redirect'] = $redirect;
  413. }
  414. $form_state['redirect'] = $redirect;
  415. }
  416. /**
  417. * Implements hook_form_submit().
  418. *
  419. * Save options from "Add content type" form and administer nodetype form.
  420. */
  421. function mb_content_admin_form_submit($form, &$form_state) {
  422. // Handle button management on the "Add content type" page.
  423. // Delete the dummy content type system variable
  424. // and set the right content type system variable.
  425. foreach ($form_state['values'] as $key => $value) {
  426. if ($key == 'type') {
  427. $type = $value;
  428. }
  429. if (preg_match("/^mb_content_type_dummy/", $key)) {
  430. // Insert the right content type.
  431. $new_type = preg_replace("/mb_content_type_dummy/", $type, $key);
  432. $form_state['values'][$new_type] = $value;
  433. // Delete the dummy content type.
  434. unset($form_state['values'][$key]);
  435. }
  436. }
  437. }
  438. /**
  439. * Submit callback to delete MB Content content type system variables
  440. * if content types will be deleted.
  441. */
  442. function mb_content_delete_confirm_submit($form, &$form_state) {
  443. $module = 'mb_content';
  444. foreach ($form_state['build_info']['args'] as $type) {
  445. variable_del($module . '_cancel_' . $type->type);
  446. variable_del($module . '_sac_' . $type->type);
  447. variable_del($module . '_tabcn_' . $type->type);
  448. }
  449. }