/[drupal]/drupal/modules/node/content_types.inc
ViewVC logotype

Contents of /drupal/modules/node/content_types.inc

Parent Directory Parent Directory | Revision Log Revision Log | View Revision Graph Revision Graph


Revision 1.99 - (show annotations) (download) (as text)
Tue Nov 3 05:32:07 2009 UTC (3 weeks ago) by webchick
Branch: MAIN
CVS Tags: DRUPAL-7-0-UNSTABLE-10
Changes since 1.98: +2 -1 lines
File MIME type: text/x-php
#202533 by lisarex and brunodbo: Tell people what the heck the content type 'Description' field is for.
1 <?php
2 // $Id: content_types.inc,v 1.98 2009/10/16 13:20:16 dries Exp $
3
4 /**
5 * @file
6 * Content type editing UI.
7 */
8
9 /**
10 * Displays the content type admin overview page.
11 */
12 function node_overview_types() {
13 $types = node_type_get_types();
14 $names = node_type_get_names();
15 $header = array(t('Name'), array('data' => t('Operations'), 'colspan' => '2'));
16 $rows = array();
17
18 foreach ($names as $key => $name) {
19 $type = $types[$key];
20 if (node_hook($type->type, 'form')) {
21 $type_url_str = str_replace('_', '-', $type->type);
22 $row = array(theme('node_admin_overview', array('name' => $name, 'type' => $type)));
23 // Set the edit column.
24 $row[] = array('data' => l(t('edit'), 'admin/structure/types/manage/' . $type_url_str));
25
26 // Set the delete column.
27 if ($type->custom) {
28 $row[] = array('data' => l(t('delete'), 'admin/structure/types/manage/' . $type_url_str . '/delete'));
29 }
30 else {
31 $row[] = array('data' => '');
32 }
33 $rows[] = $row;
34 }
35 }
36
37 if (empty($rows)) {
38 $rows[] = array(array('data' => t('No content types available. <a href="@link">Add content type</a>.', array('@link' => url('admin/structure/types/add'))), 'colspan' => '5', 'class' => array('message')));
39 }
40
41 $build['node_table'] = array(
42 '#theme' => 'table',
43 '#header' => $header,
44 '#rows' => $rows
45 );
46
47 return $build;
48 }
49
50 function theme_node_admin_overview($variables) {
51 $name = $variables['name'];
52 $type = $variables['type'];
53
54 $output = check_plain($name);
55 $output .= ' <small> (Machine name: ' . check_plain($type->type) . ')</small>';
56 $output .= '<div class="description">' . filter_xss_admin($type->description) . '</div>';
57 return $output;
58 }
59
60 /**
61 * Generates the node type editing form.
62 */
63 function node_type_form($form, &$form_state, $type = NULL) {
64 if (!isset($type->type)) {
65 // This is a new type. Node module managed types are custom and unlocked.
66 $type = node_type_set_defaults(array('custom' => 1, 'locked' => 0));
67 }
68
69 // Make the type object available to implementations of hook_form_alter.
70 $form['#node_type'] = $type;
71
72 $form['identity'] = array(
73 '#type' => 'fieldset',
74 '#title' => t('Identification'),
75 );
76 $form['identity']['name'] = array(
77 '#title' => t('Name'),
78 '#type' => 'textfield',
79 '#default_value' => $type->name,
80 '#description' => t('The human-readable name of this content type. This text will be displayed as part of the list on the <em>add new content</em> page. It is recommended that this name begin with a capital letter and contain only letters, numbers, and <strong>spaces</strong>. This name must be unique.'),
81 '#required' => TRUE,
82 '#size' => 30,
83 '#field_suffix' => ' <small id="edit-name-suffix">' . ($type->locked ? t('Machine name: @name', array('@name' => $type->type)) : '&nbsp') . '</small>',
84 );
85
86 if (!$type->locked) {
87 $js_settings = array(
88 'type' => 'setting',
89 'data' => array(
90 'machineReadableValue' => array(
91 'name' => array(
92 'text' => t('Machine name'),
93 'target' => 'type',
94 'searchPattern' => '[^a-z0-9]+',
95 'replaceToken' => '_',
96 ),
97 ),
98 ),
99 );
100 $form['identity']['type'] = array(
101 '#title' => t('Machine name'),
102 '#type' => 'textfield',
103 '#default_value' => $type->type,
104 '#maxlength' => 32,
105 '#required' => TRUE,
106 '#description' => t('The machine-readable name of this content type. This text will be used for constructing the URL of the <em>add new content</em> page for this content type. This name must contain only lowercase letters, numbers, and underscores. Underscores will be converted into hyphens when constructing the URL of the <em>add new content</em> page. This name must be unique.'),
107 '#attached' => array(
108 'js' => array(drupal_get_path('module', 'system') . '/system.js', $js_settings),
109 ),
110 );
111 }
112 else {
113 $form['identity']['type'] = array(
114 '#type' => 'value',
115 '#value' => $type->type,
116 );
117 }
118
119 $form['identity']['description'] = array(
120 '#title' => t('Description'),
121 '#type' => 'textarea',
122 '#default_value' => $type->description,
123 '#description' => t('Describe this content type. It will be displayed on the <em>Add new content</em> page.'),
124 );
125
126 $form['additional_settings'] = array(
127 '#type' => 'vertical_tabs',
128 );
129
130 $form['submission'] = array(
131 '#type' => 'fieldset',
132 '#title' => t('Submission form settings'),
133 '#collapsible' => TRUE,
134 '#group' => 'additional_settings',
135 );
136 $form['submission']['title_label'] = array(
137 '#title' => t('Title field label'),
138 '#type' => 'textfield',
139 '#default_value' => $type->title_label,
140 '#required' => TRUE,
141 );
142 if (!$type->has_title) {
143 // Avoid overwriting a content type that intentionally does not have a
144 // title field.
145 $form['submission']['title_label']['#attributes'] = array('disabled' => 'disabled');
146 $form['submission']['title_label']['#description'] = t('This content type does not have a title field.');
147 $form['submission']['title_label']['#required'] = FALSE;
148 }
149 $form['submission']['body_label'] = array(
150 '#title' => t('Body field label'),
151 '#type' => 'textfield',
152 '#default_value' => isset($type->body_label) ? $type->body_label : '',
153 '#description' => t('To remove the body field, remove text and leave blank.'),
154 );
155 $form['submission']['node_preview'] = array(
156 '#type' => 'radios',
157 '#title' => t('Preview before submitting'),
158 '#default_value' => variable_get('node_preview_' . $type->type, DRUPAL_OPTIONAL),
159 '#options' => array(
160 DRUPAL_DISABLED => t('Disabled'),
161 DRUPAL_OPTIONAL => t('Optional'),
162 DRUPAL_REQUIRED => t('Required'),
163 ),
164 );
165 $form['submission']['help'] = array(
166 '#type' => 'textarea',
167 '#title' => t('Explanation or submission guidelines'),
168 '#default_value' => $type->help,
169 '#description' => t('This text will be displayed at the top of the submission form for this content type.')
170 );
171 $form['workflow'] = array(
172 '#type' => 'fieldset',
173 '#title' => t('Publishing options'),
174 '#collapsible' => TRUE,
175 '#collapsed' => TRUE,
176 '#group' => 'additional_settings',
177 );
178 $form['workflow']['node_options'] = array('#type' => 'checkboxes',
179 '#title' => t('Default options'),
180 '#default_value' => variable_get('node_options_' . $type->type, array('status', 'promote')),
181 '#options' => array(
182 'status' => t('Published'),
183 'promote' => t('Promoted to front page'),
184 'sticky' => t('Sticky at top of lists'),
185 'revision' => t('Create new revision'),
186 ),
187 '#description' => t('Users with the <em>administer nodes</em> permission will be able to override these options.'),
188 );
189 $form['display'] = array(
190 '#type' => 'fieldset',
191 '#title' => t('Display settings'),
192 '#collapsible' => TRUE,
193 '#collapsed' => TRUE,
194 '#group' => 'additional_settings',
195 );
196 $form['display']['node_submitted'] = array(
197 '#type' => 'checkbox',
198 '#title' => t('Display post information'),
199 '#default_value' => variable_get('node_submitted_' . $type->type, TRUE),
200 '#description' => t('Enable the <em>submitted by Username on date</em> text.'),
201 );
202 $form['display']['teaser_length'] = array(
203 '#type' => 'select',
204 '#title' => t('Length of trimmed posts'),
205 '#default_value' => variable_get('teaser_length_' . $type->type, 600),
206 '#options' => drupal_map_assoc(array(0, 200, 400, 600, 800, 1000, 1200, 1400, 1600, 1800, 2000), '_node_characters'),
207 '#description' => t("The maximum number of characters used in the trimmed version of content.")
208 );
209 $form['old_type'] = array(
210 '#type' => 'value',
211 '#value' => $type->type,
212 );
213 $form['orig_type'] = array(
214 '#type' => 'value',
215 '#value' => isset($type->orig_type) ? $type->orig_type : '',
216 );
217 $form['base'] = array(
218 '#type' => 'value',
219 '#value' => $type->base,
220 );
221 $form['custom'] = array(
222 '#type' => 'value',
223 '#value' => $type->custom,
224 );
225 $form['modified'] = array(
226 '#type' => 'value',
227 '#value' => $type->modified,
228 );
229 $form['locked'] = array(
230 '#type' => 'value',
231 '#value' => $type->locked,
232 );
233
234 $form['submit'] = array(
235 '#type' => 'submit',
236 '#value' => t('Save content type'),
237 '#weight' => 40,
238 );
239
240 if ($type->custom) {
241 if (!empty($type->type)) {
242 $form['delete'] = array(
243 '#type' => 'submit',
244 '#value' => t('Delete content type'),
245 '#weight' => 45,
246 );
247 }
248 }
249
250 return $form;
251 }
252
253 /**
254 * Helper function for teaser length choices.
255 */
256 function _node_characters($length) {
257 return ($length == 0) ? t('Unlimited') : format_plural($length, '1 character', '@count characters');
258 }
259
260 /**
261 * Validates the content type submission form generated by node_type_form().
262 */
263 function node_type_form_validate($form, &$form_state) {
264 $type = new stdClass();
265 $type->type = trim($form_state['values']['type']);
266 $type->name = trim($form_state['values']['name']);
267
268 // Work out what the type was before the user submitted this form
269 $old_type = trim($form_state['values']['old_type']);
270
271 $types = node_type_get_names();
272
273 if (!$form_state['values']['locked']) {
274 if (isset($types[$type->type]) && $type->type != $old_type) {
275 form_set_error('type', t('The machine-readable name %type is already taken.', array('%type' => $type->type)));
276 }
277 if (!preg_match('!^[a-z0-9_]+$!', $type->type)) {
278 form_set_error('type', t('The machine-readable name must contain only lowercase letters, numbers, and underscores.'));
279 }
280 // 'theme' conflicts with theme_node_form().
281 // '0' is invalid, since elsewhere we check it using empty().
282 if (in_array($type->type, array('0', 'theme'))) {
283 form_set_error('type', t("Invalid machine-readable name. Please enter a name other than %invalid.", array('%invalid' => $type->type)));
284 }
285 }
286
287 $names = array_flip($types);
288
289 if (isset($names[$type->name]) && $names[$type->name] != $old_type) {
290 form_set_error('name', t('The human-readable name %name is already taken.', array('%name' => $type->name)));
291 }
292 }
293
294 /**
295 * Implement hook_form_submit().
296 */
297 function node_type_form_submit($form, &$form_state) {
298 $op = isset($form_state['values']['op']) ? $form_state['values']['op'] : '';
299
300 $type = node_type_set_defaults();
301
302 $type->type = trim($form_state['values']['type']);
303 $type->name = trim($form_state['values']['name']);
304 $type->orig_type = trim($form_state['values']['orig_type']);
305 $type->old_type = isset($form_state['values']['old_type']) ? $form_state['values']['old_type'] : $type->type;
306
307 $type->description = $form_state['values']['description'];
308 $type->help = $form_state['values']['help'];
309 $type->title_label = $form_state['values']['title_label'];
310 $type->body_label = $form_state['values']['body_label'];
311
312 // title_label is required in core; has_title will always be true, unless a
313 // module alters the title field.
314 $type->has_title = ($type->title_label != '');
315 $type->has_body = ($type->body_label != '');
316
317 $type->base = !empty($form_state['values']['base']) ? $form_state['values']['base'] : 'node_content';
318 $type->custom = $form_state['values']['custom'];
319 $type->modified = TRUE;
320 $type->locked = $form_state['values']['locked'];
321
322 if ($op == t('Delete content type')) {
323 $form_state['redirect'] = 'admin/structure/types/manage/' . str_replace('_', '-', $type->old_type) . '/delete';
324 return;
325 }
326
327 $variables = $form_state['values'];
328
329 // Remove everything that's been saved already - whatever's left is assumed
330 // to be a persistent variable.
331 foreach ($variables as $key => $value) {
332 if (isset($type->$key)) {
333 unset($variables[$key]);
334 }
335 }
336
337 unset($variables['form_token'], $variables['op'], $variables['submit'], $variables['delete'], $variables['reset'], $variables['form_id'], $variables['form_build_id']);
338
339 // Save or reset persistent variable values.
340 foreach ($variables as $key => $value) {
341 $variable_new = $key . '_' . $type->type;
342 $variable_old = $key . '_' . $type->old_type;
343
344 if (is_array($value)) {
345 $value = array_keys(array_filter($value));
346 }
347 variable_set($variable_new, $value);
348
349 if ($variable_new != $variable_old) {
350 variable_del($variable_old);
351 }
352 }
353
354 // Saving the content type after saving the variables allows modules to act
355 // on those variables via hook_node_type_insert().
356 $status = node_type_save($type);
357
358 node_types_rebuild();
359 menu_rebuild();
360 $t_args = array('%name' => $type->name);
361
362 if ($status == SAVED_UPDATED) {
363 drupal_set_message(t('The content type %name has been updated.', $t_args));
364 }
365 elseif ($status == SAVED_NEW) {
366 drupal_set_message(t('The content type %name has been added.', $t_args));
367 watchdog('node', 'Added content type %name.', $t_args, WATCHDOG_NOTICE, l(t('view'), 'admin/structure/types'));
368 }
369
370 $form_state['redirect'] = 'admin/structure/types';
371 return;
372 }
373
374 /**
375 * Implement hook_node_type_insert().
376 */
377 function node_node_type_insert($info) {
378 if (!empty($info->old_type) && $info->old_type != $info->type) {
379 $update_count = node_type_update_nodes($info->old_type, $info->type);
380
381 if ($update_count) {
382 drupal_set_message(format_plural($update_count, 'Changed the content type of 1 post from %old-type to %type.', 'Changed the content type of @count posts from %old-type to %type.', array('%old-type' => $info->old_type, '%type' => $info->type)));
383 }
384 }
385 }
386
387 /**
388 * Implement hook_node_type_update().
389 */
390 function node_node_type_update($info) {
391 if (!empty($info->old_type) && $info->old_type != $info->type) {
392 $update_count = node_type_update_nodes($info->old_type, $info->type);
393
394 if ($update_count) {
395 drupal_set_message(format_plural($update_count, 'Changed the content type of 1 post from %old-type to %type.', 'Changed the content type of @count posts from %old-type to %type.', array('%old-type' => $info->old_type, '%type' => $info->type)));
396 }
397 }
398 }
399
400 /**
401 * Resets all of the relevant fields of a module-defined node type to their
402 * default values.
403 *
404 * @param $type
405 * The node type to reset. The node type is passed back by reference with its
406 * resetted values. If there is no module-defined info for this node type,
407 * then nothing happens.
408 */
409 function node_type_reset($type) {
410 $info_array = module_invoke_all('node_info');
411 if (isset($info_array[$type->orig_type])) {
412 $info_array[$type->orig_type]['type'] = $type->orig_type;
413 $info = node_type_set_defaults($info_array[$type->orig_type]);
414
415 foreach ($info as $field => $value) {
416 $type->$field = $value;
417 }
418 }
419 }
420
421 /**
422 * Menu callback; delete a single content type.
423 */
424 function node_type_delete_confirm($form, &$form_state, $type) {
425 $form['type'] = array('#type' => 'value', '#value' => $type->type);
426 $form['name'] = array('#type' => 'value', '#value' => $type->name);
427
428 $message = t('Are you sure you want to delete the content type %type?', array('%type' => $type->name));
429 $caption = '';
430
431 $num_nodes = db_query("SELECT COUNT(*) FROM {node} WHERE type = :type", array(':type' => $type->type))->fetchField();
432 if ($num_nodes) {
433 $caption .= '<p>' . format_plural($num_nodes, '<strong>Warning:</strong> there is currently 1 %type post on your site. It may not be able to be displayed or edited correctly once you have removed this content type.', '<strong>Warning:</strong> there are currently @count %type posts on your site. They may not be able to be displayed or edited correctly once you have removed this content type.', array('%type' => $type->name)) . '</p>';
434 }
435
436 $caption .= '<p>' . t('This action cannot be undone.') . '</p>';
437
438 return confirm_form($form, $message, 'admin/structure/types', $caption, t('Delete'));
439 }
440
441 /**
442 * Process content type delete confirm submissions.
443 */
444 function node_type_delete_confirm_submit($form, &$form_state) {
445 node_type_delete($form_state['values']['type']);
446
447 variable_del('teaser_length_' . $form_state['values']['type']);
448 variable_del('node_preview_' . $form_state['values']['type']);
449 $t_args = array('%name' => $form_state['values']['name']);
450 drupal_set_message(t('The content type %name has been deleted.', $t_args));
451 watchdog('menu', 'Deleted content type %name.', $t_args, WATCHDOG_NOTICE);
452
453 node_types_rebuild();
454 menu_rebuild();
455
456 $form_state['redirect'] = 'admin/structure/types';
457 return;
458 }

  ViewVC Help
Powered by ViewVC 1.1.2