auto_nodetitle.module 7.7 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238
  1. <?php
  2. /**
  3. * @file
  4. * Allows hiding of the node title field and automatic title creation.
  5. */
  6. define('AUTO_NODETITLE_DISABLED', 0);
  7. define('AUTO_NODETITLE_ENABLED', 1);
  8. define('AUTO_NODETITLE_OPTIONAL', 2);
  9. /**
  10. * Implements hook_permission().
  11. */
  12. function auto_nodetitle_permission() {
  13. return array(
  14. 'use PHP for title patterns' => array(
  15. 'title' => t('Use PHP for title patterns'),
  16. 'description' => t('Use PHP for title patterns.'),
  17. 'restrict access' => TRUE,
  18. ),
  19. );
  20. }
  21. /**
  22. * Implements hook_form_FORM_ID_alter() for the node form.
  23. */
  24. function auto_nodetitle_form_node_form_alter(&$form, &$form_state, $form_id) {
  25. if (auto_nodetitle_get_setting($form['#node']->type) == AUTO_NODETITLE_ENABLED) {
  26. // We will autogenerate the title later, just hide the title field in the
  27. // meanwhile.
  28. $form['title']['#value'] = 'ant';
  29. $form['title']['#type'] = 'value';
  30. $form['title']['#required'] = FALSE;
  31. }
  32. elseif (auto_nodetitle_get_setting($form['#node']->type) == AUTO_NODETITLE_OPTIONAL) {
  33. $form['title']['#required'] = FALSE;
  34. }
  35. }
  36. /**
  37. * Implements hook_node_submit().
  38. *
  39. * Generate the node title as soon as the form has been submitted. That way
  40. * the node preview is shown right too.
  41. */
  42. function auto_nodetitle_node_submit($node, $form, &$form_state) {
  43. $setting = auto_nodetitle_get_setting($node->type);
  44. if ($setting == AUTO_NODETITLE_ENABLED || ($setting == AUTO_NODETITLE_OPTIONAL && empty($form_state['values']['title']))) {
  45. auto_nodetitle_set_title($node);
  46. }
  47. }
  48. /**
  49. * Implements hook_node_presave().
  50. */
  51. function auto_nodetitle_node_presave($node) {
  52. // If not yet done, generate the title now.
  53. if (auto_nodetitle_is_needed($node)) {
  54. auto_nodetitle_set_title($node);
  55. }
  56. }
  57. /**
  58. * Returns whether the auto nodetitle has to be set.
  59. */
  60. function auto_nodetitle_is_needed($node) {
  61. return empty($node->auto_nodetitle_applied) && ($setting = auto_nodetitle_get_setting($node->type)) && !($setting == AUTO_NODETITLE_OPTIONAL && !empty($node->title));
  62. }
  63. /**
  64. * Sets the automatically generated nodetitle for the node
  65. */
  66. function auto_nodetitle_set_title(&$node) {
  67. $types = node_type_get_types();
  68. $pattern = variable_get('ant_pattern_' . $node->type, '');
  69. if (trim($pattern)) {
  70. $node->changed = REQUEST_TIME;
  71. $node->title = _auto_nodetitle_patternprocessor($pattern, $node);
  72. }
  73. elseif ($node->nid) {
  74. $node->title = t('@type @node-id', array('@type' => $types[$node->type]->name, '@node-id' => $node->nid));
  75. }
  76. else {
  77. $node->title = t('@type', array('@type' => $types[$node->type]->name));
  78. }
  79. // Ensure the generated title isn't too long.
  80. $node->title = substr($node->title, 0, 255);
  81. // With that flag we ensure we don't apply the title two times to the same
  82. // node. See auto_nodetitle_is_needed().
  83. $node->auto_nodetitle_applied = TRUE;
  84. }
  85. /**
  86. * Implements hook_node_operations().
  87. */
  88. function auto_nodetitle_node_operations() {
  89. $operations = array(
  90. 'nodetitle_update' => array(
  91. 'label' => t('Update automatic nodetitles'),
  92. 'callback' => 'auto_nodetitle_operations_update',
  93. ),
  94. );
  95. return $operations;
  96. }
  97. /**
  98. * Callback function for updating node titles.
  99. */
  100. function auto_nodetitle_operations_update($nodes) {
  101. foreach ($nodes as $nid) {
  102. $node = node_load($nid);
  103. if ($node && auto_nodetitle_is_needed($node)) {
  104. $previous_title = $node->title;
  105. auto_nodetitle_set_title($node);
  106. // Only save if the title has actually changed.
  107. if ($node->title != $previous_title) {
  108. node_save($node);
  109. }
  110. }
  111. }
  112. }
  113. /**
  114. * Helper function to generate the title according to the settings.
  115. *
  116. * @return a title string
  117. */
  118. function _auto_nodetitle_patternprocessor($pattern, $node) {
  119. // Replace tokens.
  120. $output = token_replace($pattern, array('node' => $node), array('sanitize' => FALSE));
  121. // Evalute PHP.
  122. if (variable_get('ant_php_' . $node->type, 0)) {
  123. $output = auto_nodetitle_eval($output, $node);
  124. }
  125. // Strip tags.
  126. $output = preg_replace('/[\t\n\r\0\x0B]/', '', strip_tags($output));
  127. return $output;
  128. }
  129. /**
  130. * Implements hook_form_FORM_ID_alter() for the node type form.
  131. */
  132. function auto_nodetitle_form_node_type_form_alter(&$form, &$form_state) {
  133. $default_value = auto_nodetitle_get_setting($form['#node_type']->type);
  134. $form['auto_nodetitle'] = array(
  135. '#type' => 'fieldset',
  136. '#title' => t('Automatic title generation'),
  137. '#weight' => 0,
  138. '#collapsible' => TRUE,
  139. '#collapsed' => !$default_value,
  140. '#group' => 'additional_settings',
  141. '#attached' => array(
  142. 'js' => array(
  143. 'auto-nodetitle' => drupal_get_path('module', 'auto_nodetitle') . '/auto_nodetitle.js',
  144. ),
  145. ),
  146. );
  147. $form['auto_nodetitle']['ant'] = array(
  148. '#type' => 'radios',
  149. '#default_value' => $default_value,
  150. '#options' => array(
  151. t('Disabled'),
  152. t('Automatically generate the title and hide the title field'),
  153. t('Automatically generate the title if the title field is left empty'),
  154. )
  155. );
  156. $form['auto_nodetitle']['ant_pattern'] = array(
  157. '#type' => 'textarea',
  158. '#title' => t('Pattern for the title'),
  159. '#description' => t('Leave blank for using the per default generated title. Otherwise this string will be used as title. Use the syntax [token] if you want to insert a replacement pattern.'),
  160. '#default_value' => variable_get('ant_pattern_' . $form['#node_type']->type, ''),
  161. );
  162. // Don't allow editing of the pattern if PHP is used, but the users lacks
  163. // permission for PHP.
  164. if (variable_get('ant_php_' . $form['#node_type']->type, '') && !user_access('use PHP for title patterns')) {
  165. $form['auto_nodetitle']['ant_pattern']['#disabled'] = TRUE;
  166. $form['auto_nodetitle']['ant_pattern']['#description'] = t('You are not allow the configure the pattern for the title, as you lack the %permission permission.', array('%permission' => t('Use PHP for title patterns')));
  167. }
  168. // Display the list of available placeholders if token module is installed.
  169. if (module_exists('token')) {
  170. $form['auto_nodetitle']['token_help'] = array(
  171. '#theme' => 'token_tree',
  172. '#token_types' => array('node'),
  173. );
  174. }
  175. $form['auto_nodetitle']['ant_php'] = array(
  176. '#access' => user_access('use PHP for title patterns'),
  177. '#type' => 'checkbox',
  178. '#title' => t('Evaluate PHP in pattern.'),
  179. '#description' => t('Put PHP code above that returns your string, but make sure you surround code in &lt;?php and ?&gt;. Note that $node is available and can be used by your code.'),
  180. '#default_value' => variable_get('ant_php_' . $form['#node_type']->type, ''),
  181. );
  182. }
  183. /**
  184. * Gets the auto node title setting associated with the given content type.
  185. */
  186. function auto_nodetitle_get_setting($type) {
  187. return variable_get('ant_' . $type, AUTO_NODETITLE_DISABLED);
  188. }
  189. /**
  190. * Evaluates php code and passes $node to it.
  191. */
  192. function auto_nodetitle_eval($code, $node) {
  193. ob_start();
  194. print eval('?>' . $code);
  195. $output = ob_get_contents();
  196. ob_end_clean();
  197. return $output;
  198. }
  199. /**
  200. * Implements hook_node_type().
  201. */
  202. function auto_nodetitle_node_type($op, $info) {
  203. switch ($op) {
  204. case 'delete':
  205. variable_del('ant_' . $info->type);
  206. variable_del('ant_pattern_' . $info->type);
  207. variable_del('ant_php_' . $info->type);
  208. break;
  209. case 'update':
  210. if (!empty($info->old_type) && $info->old_type != $info->type) {
  211. variable_set('ant_' . $info->type, auto_nodetitle_get_setting($info->old_type));
  212. variable_set('ant_pattern_' . $info->type, variable_get('ant_pattern_' . $info->old_type, ''));
  213. variable_set('ant_php_' . $info->type, variable_get('ant_php_' . $info->old_type, ''));
  214. variable_del('ant_' . $info->old_type);
  215. variable_del('ant_pattern_' . $info->old_type);
  216. variable_del('ant_php_' . $info->old_type);
  217. }
  218. break;
  219. }
  220. }