content_type_extras.module 18 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484
  1. <?php
  2. define('CONTENT_TYPE_EXTRAS_ADMIN_DEFAULTS', 'administer content type defaults');
  3. define('CONTENT_TYPE_EXTRAS_NODE_DISPLAY_PERM', 'override content type title display');
  4. /**
  5. * Implements hook_init().
  6. */
  7. function content_type_extras_init() {
  8. drupal_add_css(drupal_get_path('module', 'content_type_extras') . '/css/content_type_extras.css');
  9. }
  10. /**
  11. * Implements hook_permission().
  12. */
  13. function content_type_extras_permission() {
  14. return array(
  15. CONTENT_TYPE_EXTRAS_ADMIN_DEFAULTS => array(
  16. 'title' => t('Administer content type defaults'),
  17. 'description' => t('Set the default settings to use on content types that are not overridden.'),
  18. ),
  19. CONTENT_TYPE_EXTRAS_NODE_DISPLAY_PERM => array(
  20. 'title' => t('Override content type title display'),
  21. 'description' => t('Allow the default node title display setting to be overridden on a per-node basis.'),
  22. ),
  23. );
  24. }
  25. /**
  26. * Implements hook_preprocess_page().
  27. */
  28. function content_type_extras_preprocess_page(&$vars) {
  29. // We have to check for the front page first since it's setting take precedence
  30. // over the node type setting.
  31. if (drupal_is_front_page()) {
  32. $hide_title_front = content_type_extras_get_default('content_type_extras_title_hide_front');
  33. if ($hide_title_front) {
  34. $hide_title_css = content_type_extras_get_default('content_type_extras_title_hide_css');
  35. if ($hide_title_css) {
  36. $vars['title_prefix']['content_type_extras'] = array(
  37. '#prefix' => '<div class="element-invisible">',
  38. );
  39. $vars['title_suffix']['content_type_extras'] = array(
  40. '#suffix' => '</div>',
  41. );
  42. }
  43. else {
  44. $vars['title'] = '';
  45. }
  46. }
  47. }
  48. elseif (!empty($vars['node'])) {
  49. // Ran into an issue when using the Print module where the node type isn't set, throwing an error
  50. // so we are checking to see if the node type is set first
  51. $hide_title = isset($vars['node']->type) ? content_type_extras_get_setting('content_type_extras_title_hide', $vars['node']->type) : '';
  52. if ($hide_title) {
  53. $hide_title_css = content_type_extras_get_default('content_type_extras_title_hide_css');
  54. if ($hide_title_css) {
  55. $vars['title_prefix']['content_type_extras'] = array(
  56. '#prefix' => '<div class="element-invisible">',
  57. );
  58. $vars['title_suffix']['content_type_extras'] = array(
  59. '#suffix' => '</div>',
  60. );
  61. }
  62. else {
  63. $vars['title'] = '';
  64. }
  65. }
  66. }
  67. }
  68. /**
  69. * Implements hook_menu().
  70. */
  71. function content_type_extras_menu() {
  72. $items['admin/structure/types/defaults'] = array(
  73. 'title' => 'Default settings',
  74. 'page callback' => 'drupal_get_form',
  75. 'page arguments' => array('content_type_extras_settings'),
  76. 'access arguments' => array(CONTENT_TYPE_EXTRAS_ADMIN_DEFAULTS),
  77. 'type' => MENU_LOCAL_TASK,
  78. 'file' => 'content_type_extras.admin.inc',
  79. 'file path' => drupal_get_path('module', 'content_type_extras') . '/includes',
  80. 'weight' => 10,
  81. );
  82. return $items;
  83. }
  84. /**
  85. * Implements hook_form_alter().
  86. */
  87. function content_type_extras_form_alter(&$form, &$form_state, $form_id) {
  88. // This is a list of node form ids to omit from being processed, since they don't
  89. // play nice with content_type_extras.
  90. $exclude_node_form = content_type_extras_get_setting('content_type_extras_excluded_node_forms', '');
  91. // These forms are known to cause issues so always include them in the excluded forms.
  92. $exclude_node_form[] = 'subscriptions_ui_node_form';
  93. $exclude_node_form[] = 'field_collection_item_form';
  94. // node_type_form = Content type edit forms.
  95. if ($form_id == 'node_type_form') {
  96. module_load_include('inc', 'content_type_extras', 'includes/content_type_extras.node_type_form');
  97. content_type_extras_node_type_form($form);
  98. }
  99. // Viewing a specific node edit form
  100. elseif (strpos($form_id, '_node_form') && !in_array($form_id, $exclude_node_form)) {
  101. $type = $form['type']['#value'];
  102. // We need to check to see if auto_nodetitle module is hiding the title field - checking for $form['title']['#value'] != 'ant'
  103. // Also, for compatibility with auto_entitytitle module we check for $form['title']['#value'] != '%AutoEntityLabel%'
  104. if (user_access(CONTENT_TYPE_EXTRAS_NODE_DISPLAY_PERM) &&
  105. (isset($form['title']['#value']) &&
  106. $form['title']['#value'] != 'ant' &&
  107. $form['title']['#value'] != '%AutoEntityLabel%')) {
  108. $hide = content_type_extras_get_setting('content_type_extras_title_hide', $type);
  109. if (!empty($form['nid']['#value'])) {
  110. $hide = _content_type_extras_get_node_display($form['nid']['#value']);
  111. }
  112. $form['title_hide'] = array(
  113. '#type' => 'checkbox',
  114. '#title' => t("Exclude this node's title from display"),
  115. '#default_value' => $hide,
  116. '#weight' => 0,
  117. );
  118. if (variable_get('site_frontpage', '') . '/edit' == current_path()) {
  119. // We need to get the default settings since that is the only place that
  120. // the hide_title_front setting is stored.
  121. $defaults = content_type_extras_get_default();
  122. if (!empty($defaults['extras']['title_hide_front'])) {
  123. $form['title_hide']['#disabled'] = TRUE;
  124. $form['title_hide']['#description'] = t('<em>You cannot edit this option as it is set as the front page and the front page title is set to be hidden by the administrator.</em>');
  125. }
  126. }
  127. }
  128. $title_label = content_type_extras_get_setting('title_label', $type);
  129. if (isset($title_label) && $title_label != t('Title')) {
  130. $form['title']['#title'] = $title_label;
  131. }
  132. $form['actions']['submit']['#value'] = content_type_extras_get_setting('content_type_extras_save_button', $type);
  133. $save_and_new = content_type_extras_get_setting('content_type_extras_save_and_new', $type);
  134. if (!empty($save_and_new)) {
  135. $form['actions']['save_and_new'] = array(
  136. '#type' => 'submit',
  137. '#value' => content_type_extras_get_setting('content_type_extras_save_and_new_button', $type),
  138. '#weight' => $form['actions']['submit']['#weight'] + 1,
  139. '#submit' => array(
  140. 'node_form_submit',
  141. 'content_type_extras_node_form_new_submit',
  142. ),
  143. );
  144. }
  145. $save_and_edit = content_type_extras_get_setting('content_type_extras_save_and_edit', $type);
  146. if (!empty($save_and_edit)) {
  147. $form['actions']['save_and_edit'] = array(
  148. '#type' => 'submit',
  149. '#value' => content_type_extras_get_setting('content_type_extras_save_and_edit_button', $type),
  150. '#weight' => $form['actions']['submit']['#weight'] + 2,
  151. '#submit' => array(
  152. 'node_form_submit',
  153. 'content_type_extras_node_form_edit_submit',
  154. ),
  155. );
  156. }
  157. $preview = content_type_extras_get_setting('node_preview', $type);
  158. if (!empty($preview)) {
  159. $form['actions']['preview']['#value'] = content_type_extras_get_setting('content_type_extras_preview_button', $type);
  160. }
  161. elseif (isset($form['actions']['preview'])) {
  162. unset($form['actions']['preview']);
  163. }
  164. $cancel = content_type_extras_get_setting('content_type_extras_cancel', $type);
  165. if (!empty($cancel)) {
  166. $cancel_hide_warning = content_type_extras_get_setting('content_type_extras_cancel_hide_warning', $type);
  167. $cancel_location = content_type_extras_get_setting('content_type_extras_cancel_button_location', $type);
  168. $location_path = content_type_extras_get_setting('content_type_extras_cancel_button_location_path', $type);
  169. $form['#attached']['js'][] = drupal_get_path('module', 'content_type_extras') . '/js/content_type_extras.cancel_button.js';
  170. $form['#attached']['js'][] = array(
  171. 'data' => array('content_type_extras' => array(
  172. 'hide_warning' => $cancel_hide_warning,
  173. 'cancel_location' => $cancel_location,
  174. 'location_path' => $location_path,
  175. )),
  176. 'type' => 'setting',
  177. );
  178. $form['actions']['cancel'] = array(
  179. '#type' => 'button',
  180. '#value' => t('Cancel'),
  181. '#weight' => 100, // We want this at the end of whatever buttons are showing
  182. '#post_render' => array('content_type_extras_change_button_type'),
  183. );
  184. }
  185. // Add the form buttons to the top of the page
  186. // Based on: http://blog.urbaninsight.com/2011/09/20/editors-perspective-creating-content-drupal
  187. $top_buttons = content_type_extras_get_setting('content_type_extras_top_buttons', $type);
  188. if (!empty($top_buttons['node_edit']) && in_array('node_edit', $top_buttons)) {
  189. $form['pre_actions'] = $form['actions'];
  190. $form['pre_actions']['#weight'] = -100;
  191. }
  192. $form['#submit'][] = 'content_type_extras_node_form_submit';
  193. }
  194. // Content type field machine names can only be a maximum of 32 characters (including 'field_')
  195. // but the user can enter a name any length, getting an error message if the name is too long
  196. // That drives me crazy!! This fixes that!
  197. elseif ($form_id == 'field_ui_field_overview_form') {
  198. $type = arg(4);
  199. drupal_add_js(drupal_get_path('module', 'content_type_extras') . '/js/content_type_extras.manage_fields.js');
  200. $top_buttons = content_type_extras_get_setting('content_type_extras_top_buttons', $type);
  201. if (!empty($top_buttons['manage_fields']) || in_array('manage_fields', $top_buttons)) {
  202. $form['pre_actions'] = $form['actions'];
  203. $form['pre_actions']['#weight'] = -100;
  204. }
  205. if (isset($form['fields']['_add_new_field'])) {
  206. $form['fields']['_add_new_field']['field_name']['#maxlength'] = 26;
  207. $form['fields']['_add_new_field']['field_name']['#description'] .= t(' - <span class="characters">26</span> characters max.');
  208. }
  209. // The field_group module does the same thing, so if that is enabled, handle it the same way
  210. if (module_exists('field_group')) {
  211. $form['fields']['_add_new_group']['group_name']['#maxlength'] = 26;
  212. $form['fields']['_add_new_group']['group_name']['#description'] .= t(' - <span class="characters">26</span> characters max.');
  213. }
  214. }
  215. }
  216. /**
  217. * Form submission handler for $form_id *_node_form
  218. */
  219. function content_type_extras_node_form_submit(&$form, &$form_state) {
  220. if (!empty($form_state['values']['title_hide'])) {
  221. _content_type_extras_set_node_display($form_state['values']['nid'], $form_state['values']['title_hide']);
  222. }
  223. }
  224. /**
  225. * Form submission for $form_id *_node_form
  226. */
  227. function content_type_extras_node_form_new_submit(&$form, &$form_state) {
  228. unset($_GET['destination']);
  229. $form_state['redirect'] = 'node/add/' . str_replace('_', '-', $form_state['node']->type);
  230. }
  231. /**
  232. * Form submission for $form_id *_node_form
  233. */
  234. function content_type_extras_node_form_edit_submit(&$form, &$form_state) {
  235. $query_string = array();
  236. // Allow compatibility with content lock module.
  237. if (isset($_REQUEST['content_lock_token'])) {
  238. $query_string['content_lock_token'] = $_REQUEST['content_lock_token'];
  239. }
  240. // Allow compatibility with additional query parameters.
  241. $query_parameters = drupal_get_query_parameters();
  242. if (!empty($query_parameters)) {
  243. foreach ($query_parameters as $key => $value) {
  244. $query_string[$key] = $value;
  245. }
  246. }
  247. if (!empty($query_string)) {
  248. $form_state['redirect'] = url('node/' . $form_state['values']['nid'] . '/edit',
  249. array(
  250. 'query' => $query_string,
  251. 'absolute' => TRUE,
  252. )
  253. );
  254. }
  255. else {
  256. $form_state['redirect'] = 'node/' . $form_state['values']['nid'] . '/edit';
  257. }
  258. unset($_GET['destination']);
  259. }
  260. /**
  261. * Implements hook_node_type_delete().
  262. */
  263. function content_type_extras_node_type_delete($info) {
  264. db_delete('variable')
  265. ->condition('name', 'content_type_extras_%_' . $info->type, 'LIKE')
  266. ->execute();
  267. }
  268. /**
  269. * Function to change the type of button from 'submit' to 'button.
  270. * -- From http://drupal.org/node/133861#comment-4002698
  271. */
  272. function content_type_extras_change_button_type($markup, $element) {
  273. $markup = str_replace('type="submit', 'type="button', $markup);
  274. return $markup;
  275. }
  276. /**
  277. * Function to set values for node title display
  278. */
  279. function _content_type_extras_set_node_display($nid, $hide) {
  280. $settings = variable_get('content_type_extras_node_display', array());
  281. $settings[$nid] = $hide;
  282. variable_set('content_type_extras_node_display', $settings);
  283. }
  284. /**
  285. * Function to get values for node title display
  286. */
  287. function _content_type_extras_get_node_display($nid) {
  288. $settings = variable_get('content_type_extras_node_display', array());
  289. if (isset($settings[$nid])) {
  290. return $settings[$nid];
  291. }
  292. return FALSE;
  293. }
  294. /**
  295. * Function to get values based on node type.
  296. *
  297. * @param $setting
  298. * Retrieve a specific setting from $type.
  299. * @param $type
  300. * The type of content to get $setting from.
  301. *
  302. * @return
  303. * Returns the requested setting for the given content type.
  304. */
  305. function content_type_extras_get_setting($setting, $type) {
  306. // We have to handle title_label differently because it is stored in the node_type
  307. // table, not in variables
  308. if ($setting == 'title_label') {
  309. $result = db_query("SELECT title_label
  310. FROM {node_type}
  311. WHERE module = 'node'
  312. AND type = :type", array(':type' => $type))->fetchField();
  313. if ($result) {
  314. return $result;
  315. }
  316. }
  317. return variable_get($setting . '_' . $type, content_type_extras_get_default($setting));
  318. }
  319. /**
  320. * Function to get default setting(s), when settings for content type do not exist.
  321. *
  322. * @param $setting
  323. * Retrieve a specific default setting.
  324. *
  325. * @return
  326. * Returns the requested setting or, if NULL, returns all default settings.
  327. */
  328. function content_type_extras_get_default($setting = NULL) {
  329. // This has to be unserialized as it will crash the default settings page.
  330. $defaults = variable_get('content_type_extras_default_settings', array()) + content_type_extras_get_initial();
  331. // Return all default settings.
  332. if ($setting == NULL) {
  333. return $defaults;
  334. }
  335. // Return specific default setting.
  336. else if (isset($defaults[$setting])) {
  337. return $defaults[$setting];
  338. }
  339. }
  340. /**
  341. * Function to retrieve intial (module default) settings when no other settings exist.
  342. * This will primarily be used when the module is first installed.
  343. *
  344. * @param $setting
  345. * Retrieve a specific initial setting.
  346. *
  347. * @return
  348. * Returns the requested setting or, if NULL, returns all initial settings.
  349. */
  350. function content_type_extras_get_initial($setting = NULL) {
  351. $initial_values = array(
  352. // Values set by Drupal Core (node.module)
  353. 'title_label' => t('Title'),
  354. 'node_preview' => 1,
  355. 'node_options' => array(
  356. 'status' => 'status',
  357. 'promote' => 'promote',
  358. 'sticky' => 0,
  359. 'revision' => 0,
  360. ),
  361. 'node_submitted' => 1,
  362. // Values set by content_type_extras.module
  363. 'content_type_extras_save_button' => t('Save'),
  364. 'content_type_extras_preview_button' => t('Preview'),
  365. 'content_type_extras_save_and_new' => 0,
  366. 'content_type_extras_save_and_new_button' => t('Save and New'),
  367. 'content_type_extras_save_and_edit' => 0,
  368. 'content_type_extras_save_and_edit_button' => t('Save and Edit'),
  369. 'content_type_extras_cancel' => 0,
  370. 'content_type_extras_cancel_hide_warning' => 0,
  371. 'content_type_extras_title_hide' => 0,
  372. 'content_type_extras_title_hide_css' => 0,
  373. 'content_type_extras_title_hide_front' => 0,
  374. 'content_type_extras_top_buttons' => array(),
  375. 'content_type_extras_remove_body' => 0,
  376. 'content_type_extras_disable_token_display' => 0,
  377. 'content_type_extras_cancel_button_location' => 'previous',
  378. 'content_type_extras_cancel_button_location_path' => '',
  379. 'content_type_extras_descriptions_required' => 0,
  380. 'content_type_extras_user_permissions_select' => 'cte',
  381. 'content_type_extras_excluded_node_forms' => array(),
  382. // Values set by comment.module
  383. 'comment' => array(
  384. 'comment' => 2,
  385. 'default_mode' => 1,
  386. 'default_per_page' => 50,
  387. 'anonymous' => 0,
  388. 'subject_field' => 1,
  389. 'form_location' => 1,
  390. 'preview' => 1,
  391. ),
  392. // Values set by pathauto module
  393. 'pathauto_node' => '',
  394. // Values set by xmlsitemap.module
  395. 'xmlsitemap_settings' => array(
  396. 'status' => 1,
  397. 'priority' => '0.5',
  398. ),
  399. // Values set by scheduler.module
  400. 'scheduler_settings' => array(
  401. 'publish_enable' => 0,
  402. 'publish_touch' => 0,
  403. 'publish_require' => 0,
  404. 'publish_revision' => 0,
  405. 'unpublish_enable' => 0,
  406. 'unpublish_require' => 0,
  407. 'unpublish_revision' => 0,
  408. ),
  409. );
  410. $admin_role = variable_get('user_admin_role', '');
  411. $initial_values['user_permissions'] = array(
  412. 'create_roles' => array($admin_role => $admin_role),
  413. 'edit_roles' => array($admin_role => $admin_role),
  414. 'delete_roles' => array($admin_role => $admin_role),
  415. 'edit_own_roles' => array($admin_role => $admin_role),
  416. 'delete_own_roles' => array($admin_role => $admin_role),
  417. );
  418. if ($setting == NULL) {
  419. return $initial_values;
  420. }
  421. return $initial_values[$setting];
  422. }
  423. /**
  424. * Redirect function to content_type_extras_node_type_form_submit().
  425. *
  426. * We use this method because when other modules are enabled, like Location,
  427. * that modify node_type_form an error is thrown saying that
  428. * content_type_extras_node_type_form_submit() is not declared. This is a
  429. * workaround to keep the actual function in
  430. * content_type_extras.node_type_form.inc for organization, but keep the
  431. * submission form from throwing an error.
  432. * @TODO: I'd like to find a better way to handle this, if one exists!
  433. */
  434. function content_type_extras_node_type_form_submit_redirect(&$form, &$form_state) {
  435. include_once(drupal_get_path('module', 'content_type_extras') . '/includes/content_type_extras.node_type_form.inc');
  436. content_type_extras_node_type_form_submit($form, $form_state);
  437. }