content_type_extras.module 16 KB

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