| [ Index ] |
PHP Cross Reference of Drupal 6 (yi-drupal) |
[Summary view] [Print] [Text view]
1 <?php 2 3 /** 4 * @file 5 * Page callbacks for adding, editing, deleting, and revisions management for content. 6 */ 7 8 9 /** 10 * Menu callback; presents the node editing form, or redirects to delete confirmation. 11 */ 12 function node_page_edit($node) { 13 drupal_set_title(check_plain($node->title)); 14 return drupal_get_form($node->type .'_node_form', $node); 15 } 16 17 function node_add_page() { 18 $item = menu_get_item(); 19 $content = system_admin_menu_block($item); 20 return theme('node_add_list', $content); 21 } 22 23 /** 24 * Display the list of available node types for node creation. 25 * 26 * @ingroup themeable 27 */ 28 function theme_node_add_list($content) { 29 $output = ''; 30 31 if ($content) { 32 $output = '<dl class="node-type-list">'; 33 foreach ($content as $item) { 34 $output .= '<dt>'. l($item['title'], $item['href'], $item['localized_options']) .'</dt>'; 35 $output .= '<dd>'. filter_xss_admin($item['description']) .'</dd>'; 36 } 37 $output .= '</dl>'; 38 } 39 return $output; 40 } 41 42 43 /** 44 * Present a node submission form or a set of links to such forms. 45 */ 46 function node_add($type) { 47 global $user; 48 49 $types = node_get_types(); 50 $type = isset($type) ? str_replace('-', '_', $type) : NULL; 51 // If a node type has been specified, validate its existence. 52 if (isset($types[$type]) && node_access('create', $type)) { 53 // Initialize settings: 54 $node = array('uid' => $user->uid, 'name' => (isset($user->name) ? $user->name : ''), 'type' => $type, 'language' => ''); 55 56 drupal_set_title(t('Create @name', array('@name' => $types[$type]->name))); 57 $output = drupal_get_form($type .'_node_form', $node); 58 } 59 60 return $output; 61 } 62 63 function node_form_validate($form, &$form_state) { 64 node_validate($form_state['values'], $form); 65 } 66 67 function node_object_prepare(&$node) { 68 // Set up default values, if required. 69 $node_options = variable_get('node_options_'. $node->type, array('status', 'promote')); 70 // If this is a new node, fill in the default values. 71 if (!isset($node->nid)) { 72 foreach (array('status', 'promote', 'sticky') as $key) { 73 $node->$key = in_array($key, $node_options); 74 } 75 global $user; 76 $node->uid = $user->uid; 77 $node->created = time(); 78 } 79 else { 80 $node->date = format_date($node->created, 'custom', 'Y-m-d H:i:s O'); 81 // Remove the log message from the original node object. 82 $node->log = NULL; 83 } 84 // Always use the default revision setting. 85 $node->revision = in_array('revision', $node_options); 86 87 node_invoke($node, 'prepare'); 88 node_invoke_nodeapi($node, 'prepare'); 89 } 90 91 /** 92 * Generate the node add/edit form array. 93 */ 94 function node_form(&$form_state, $node) { 95 global $user; 96 97 if (isset($form_state['node'])) { 98 $node = $form_state['node'] + (array)$node; 99 } 100 if (isset($form_state['node_preview'])) { 101 $form['#prefix'] = $form_state['node_preview']; 102 } 103 $node = (object)$node; 104 foreach (array('body', 'title', 'format') as $key) { 105 if (!isset($node->$key)) { 106 $node->$key = NULL; 107 } 108 } 109 if (!isset($form_state['node_preview'])) { 110 node_object_prepare($node); 111 } 112 else { 113 $node->build_mode = NODE_BUILD_PREVIEW; 114 } 115 116 // Set the id of the top-level form tag 117 $form['#id'] = 'node-form'; 118 119 // Basic node information. 120 // These elements are just values so they are not even sent to the client. 121 foreach (array('nid', 'vid', 'uid', 'created', 'type', 'language') as $key) { 122 $form[$key] = array( 123 '#type' => 'value', 124 '#value' => isset($node->$key) ? $node->$key : NULL, 125 ); 126 } 127 128 // Changed must be sent to the client, for later overwrite error checking. 129 $form['changed'] = array( 130 '#type' => 'hidden', 131 '#default_value' => isset($node->changed) ? $node->changed : NULL, 132 ); 133 // Get the node-specific bits. 134 if ($extra = node_invoke($node, 'form', $form_state)) { 135 $form = array_merge_recursive($form, $extra); 136 } 137 if (!isset($form['title']['#weight'])) { 138 $form['title']['#weight'] = -5; 139 } 140 141 $form['#node'] = $node; 142 143 // Add a log field if the "Create new revision" option is checked, or if the 144 // current user has the ability to check that option. 145 if (!empty($node->revision) || user_access('administer nodes')) { 146 $form['revision_information'] = array( 147 '#type' => 'fieldset', 148 '#title' => t('Revision information'), 149 '#collapsible' => TRUE, 150 // Collapsed by default when "Create new revision" is unchecked 151 '#collapsed' => !$node->revision, 152 '#weight' => 20, 153 ); 154 $form['revision_information']['revision'] = array( 155 '#access' => user_access('administer nodes'), 156 '#type' => 'checkbox', 157 '#title' => t('Create new revision'), 158 '#default_value' => $node->revision, 159 ); 160 $form['revision_information']['log'] = array( 161 '#type' => 'textarea', 162 '#title' => t('Log message'), 163 '#default_value' => (isset($node->log) ? $node->log : ''), 164 '#rows' => 2, 165 '#description' => t('An explanation of the additions or updates being made to help other authors understand your motivations.'), 166 ); 167 } 168 169 // Node author information for administrators 170 $form['author'] = array( 171 '#type' => 'fieldset', 172 '#access' => user_access('administer nodes'), 173 '#title' => t('Authoring information'), 174 '#collapsible' => TRUE, 175 '#collapsed' => TRUE, 176 '#weight' => 20, 177 ); 178 $form['author']['name'] = array( 179 '#type' => 'textfield', 180 '#title' => t('Authored by'), 181 '#maxlength' => 60, 182 '#autocomplete_path' => 'user/autocomplete', 183 '#default_value' => $node->name ? $node->name : '', 184 '#weight' => -1, 185 '#description' => t('Leave blank for %anonymous.', array('%anonymous' => variable_get('anonymous', t('Anonymous')))), 186 ); 187 $form['author']['date'] = array( 188 '#type' => 'textfield', 189 '#title' => t('Authored on'), 190 '#maxlength' => 25, 191 '#description' => t('Format: %time. Leave blank to use the time of form submission.', array('%time' => !empty($node->date) ? $node->date : format_date($node->created, 'custom', 'Y-m-d H:i:s O'))), 192 ); 193 194 if (isset($node->date)) { 195 $form['author']['date']['#default_value'] = $node->date; 196 } 197 198 // Node options for administrators 199 $form['options'] = array( 200 '#type' => 'fieldset', 201 '#access' => user_access('administer nodes'), 202 '#title' => t('Publishing options'), 203 '#collapsible' => TRUE, 204 '#collapsed' => TRUE, 205 '#weight' => 25, 206 ); 207 $form['options']['status'] = array( 208 '#type' => 'checkbox', 209 '#title' => t('Published'), 210 '#default_value' => $node->status, 211 ); 212 $form['options']['promote'] = array( 213 '#type' => 'checkbox', 214 '#title' => t('Promoted to front page'), 215 '#default_value' => $node->promote, 216 ); 217 $form['options']['sticky'] = array( 218 '#type' => 'checkbox', 219 '#title' => t('Sticky at top of lists'), 220 '#default_value' => $node->sticky, 221 ); 222 223 // These values are used when the user has no administrator access. 224 foreach (array('uid', 'created') as $key) { 225 $form[$key] = array( 226 '#type' => 'value', 227 '#value' => $node->$key, 228 ); 229 } 230 231 // Add the buttons. 232 $form['buttons'] = array(); 233 $form['buttons']['submit'] = array( 234 '#type' => 'submit', 235 '#access' => !variable_get('node_preview', 0) || (!form_get_errors() && isset($form_state['node_preview'])), 236 '#value' => t('Save'), 237 '#weight' => 5, 238 '#submit' => array('node_form_submit'), 239 ); 240 $form['buttons']['preview'] = array( 241 '#type' => 'submit', 242 '#value' => t('Preview'), 243 '#weight' => 10, 244 '#submit' => array('node_form_build_preview'), 245 ); 246 if (!empty($node->nid) && node_access('delete', $node)) { 247 $form['buttons']['delete'] = array( 248 '#type' => 'submit', 249 '#value' => t('Delete'), 250 '#weight' => 15, 251 '#submit' => array('node_form_delete_submit'), 252 ); 253 } 254 $form['#validate'][] = 'node_form_validate'; 255 $form['#theme'] = array($node->type .'_node_form', 'node_form'); 256 return $form; 257 } 258 259 /** 260 * Return a node body field, with format and teaser. 261 */ 262 function node_body_field(&$node, $label, $word_count) { 263 264 // Check if we need to restore the teaser at the beginning of the body. 265 $include = !isset($node->teaser) || ($node->teaser == substr($node->body, 0, strlen($node->teaser))); 266 267 $form = array( 268 '#after_build' => array('node_teaser_js', 'node_teaser_include_verify')); 269 270 $form['#prefix'] = '<div class="body-field-wrapper">'; 271 $form['#suffix'] = '</div>'; 272 273 $form['teaser_js'] = array( 274 '#type' => 'textarea', 275 '#rows' => 10, 276 '#teaser' => 'edit-body', 277 '#teaser_checkbox' => 'edit-teaser-include', 278 '#disabled' => TRUE, 279 ); 280 281 $form['teaser_include'] = array( 282 '#type' => 'checkbox', 283 '#title' => t('Show summary in full view'), 284 '#default_value' => $include, 285 '#prefix' => '<div class="teaser-checkbox">', 286 '#suffix' => '</div>', 287 ); 288 289 $form['body'] = array( 290 '#type' => 'textarea', 291 '#title' => check_plain($label), 292 '#default_value' => $include ? $node->body : ($node->teaser . $node->body), 293 '#rows' => 20, 294 '#required' => ($word_count > 0), 295 ); 296 297 $form['format'] = filter_form($node->format); 298 299 return $form; 300 } 301 302 /** 303 * Button sumit function: handle the 'Delete' button on the node form. 304 */ 305 function node_form_delete_submit($form, &$form_state) { 306 $destination = ''; 307 if (isset($_REQUEST['destination'])) { 308 $destination = drupal_get_destination(); 309 unset($_REQUEST['destination']); 310 } 311 $node = $form['#node']; 312 $form_state['redirect'] = array('node/'. $node->nid .'/delete', $destination); 313 } 314 315 316 function node_form_build_preview($form, &$form_state) { 317 $node = node_form_submit_build_node($form, $form_state); 318 $form_state['node_preview'] = node_preview($node); 319 } 320 321 /** 322 * Present a node submission form. 323 * 324 * @ingroup themeable 325 */ 326 function theme_node_form($form) { 327 $output = "\n<div class=\"node-form\">\n"; 328 329 // Admin form fields and submit buttons must be rendered first, because 330 // they need to go to the bottom of the form, and so should not be part of 331 // the catch-all call to drupal_render(). 332 $admin = ''; 333 if (isset($form['author'])) { 334 $admin .= " <div class=\"authored\">\n"; 335 $admin .= drupal_render($form['author']); 336 $admin .= " </div>\n"; 337 } 338 if (isset($form['options'])) { 339 $admin .= " <div class=\"options\">\n"; 340 $admin .= drupal_render($form['options']); 341 $admin .= " </div>\n"; 342 } 343 $buttons = drupal_render($form['buttons']); 344 345 // Everything else gets rendered here, and is displayed before the admin form 346 // field and the submit buttons. 347 $output .= " <div class=\"standard\">\n"; 348 $output .= drupal_render($form); 349 $output .= " </div>\n"; 350 351 if (!empty($admin)) { 352 $output .= " <div class=\"admin\">\n"; 353 $output .= $admin; 354 $output .= " </div>\n"; 355 } 356 $output .= $buttons; 357 $output .= "</div>\n"; 358 359 return $output; 360 } 361 362 /** 363 * Generate a node preview. 364 */ 365 function node_preview($node) { 366 if (node_access('create', $node) || node_access('update', $node)) { 367 // Load the user's name when needed. 368 if (isset($node->name)) { 369 // The use of isset() is mandatory in the context of user IDs, because 370 // user ID 0 denotes the anonymous user. 371 if ($user = user_load(array('name' => $node->name))) { 372 $node->uid = $user->uid; 373 $node->picture = $user->picture; 374 } 375 else { 376 $node->uid = 0; // anonymous user 377 } 378 } 379 else if ($node->uid) { 380 $user = user_load(array('uid' => $node->uid)); 381 $node->name = $user->name; 382 $node->picture = $user->picture; 383 } 384 385 $node->changed = time(); 386 387 // Extract a teaser, if it hasn't been set (e.g. by a module-provided 388 // 'teaser' form item). 389 if (!isset($node->teaser)) { 390 $node->teaser = empty($node->body) ? '' : node_teaser($node->body, $node->format); 391 // Chop off the teaser from the body if needed. 392 if (!$node->teaser_include && $node->teaser == substr($node->body, 0, strlen($node->teaser))) { 393 $node->body = substr($node->body, strlen($node->teaser)); 394 } 395 } 396 397 // Display a preview of the node. 398 // Previewing alters $node so it needs to be cloned. 399 if (!form_get_errors()) { 400 $cloned_node = drupal_clone($node); 401 $cloned_node->build_mode = NODE_BUILD_PREVIEW; 402 $output = theme('node_preview', $cloned_node); 403 } 404 drupal_set_title(t('Preview')); 405 406 return $output; 407 } 408 } 409 410 /** 411 * Display a node preview for display during node creation and editing. 412 * 413 * @param $node 414 * The node object which is being previewed. 415 * 416 * @ingroup themeable 417 */ 418 function theme_node_preview($node) { 419 $output = '<div class="preview">'; 420 421 $preview_trimmed_version = FALSE; 422 // Do we need to preview trimmed version of post as well as full version? 423 if (isset($node->teaser) && isset($node->body)) { 424 $teaser = trim($node->teaser); 425 $body = trim(str_replace('<!--break-->', '', $node->body)); 426 427 // Preview trimmed version if teaser and body will appear different; 428 // also (edge case) if both teaser and body have been specified by the user 429 // and are actually the same. 430 if ($teaser != $body || ($body && strpos($node->body, '<!--break-->') === 0)) { 431 $preview_trimmed_version = TRUE; 432 } 433 } 434 435 if ($preview_trimmed_version) { 436 drupal_set_message(t('The trimmed version of your post shows what your post looks like when promoted to the main page or when exported for syndication.<span class="no-js"> You can insert the delimiter "<!--break-->" (without the quotes) to fine-tune where your post gets split.</span>')); 437 $output .= '<h3>'. t('Preview trimmed version') .'</h3>'; 438 $output .= node_view(drupal_clone($node), 1, FALSE, 0); 439 $output .= '<h3>'. t('Preview full version') .'</h3>'; 440 $output .= node_view($node, 0, FALSE, 0); 441 } 442 else { 443 $output .= node_view($node, 0, FALSE, 0); 444 } 445 $output .= "</div>\n"; 446 447 return $output; 448 } 449 450 function node_form_submit($form, &$form_state) { 451 global $user; 452 453 $node = node_form_submit_build_node($form, $form_state); 454 $insert = empty($node->nid); 455 node_save($node); 456 $node_link = l(t('view'), 'node/'. $node->nid); 457 $watchdog_args = array('@type' => $node->type, '%title' => $node->title); 458 $t_args = array('@type' => node_get_types('name', $node), '%title' => $node->title); 459 460 if ($insert) { 461 watchdog('content', '@type: added %title.', $watchdog_args, WATCHDOG_NOTICE, $node_link); 462 drupal_set_message(t('@type %title has been created.', $t_args)); 463 } 464 else { 465 watchdog('content', '@type: updated %title.', $watchdog_args, WATCHDOG_NOTICE, $node_link); 466 drupal_set_message(t('@type %title has been updated.', $t_args)); 467 } 468 if ($node->nid) { 469 unset($form_state['rebuild']); 470 $form_state['nid'] = $node->nid; 471 $form_state['redirect'] = 'node/'. $node->nid; 472 } 473 else { 474 // In the unlikely case something went wrong on save, the node will be 475 // rebuilt and node form redisplayed the same way as in preview. 476 drupal_set_message(t('The post could not be saved.'), 'error'); 477 } 478 } 479 480 /** 481 * Build a node by processing submitted form values and prepare for a form rebuild. 482 */ 483 function node_form_submit_build_node($form, &$form_state) { 484 // Unset any button-level handlers, execute all the form-level submit 485 // functions to process the form values into an updated node. 486 unset($form_state['submit_handlers']); 487 form_execute_handlers('submit', $form, $form_state); 488 $node = node_submit($form_state['values']); 489 $form_state['node'] = (array)$node; 490 $form_state['rebuild'] = TRUE; 491 return $node; 492 } 493 494 /** 495 * Menu callback -- ask for confirmation of node deletion 496 */ 497 function node_delete_confirm(&$form_state, $node) { 498 $form['nid'] = array( 499 '#type' => 'value', 500 '#value' => $node->nid, 501 ); 502 503 return confirm_form($form, 504 t('Are you sure you want to delete %title?', array('%title' => $node->title)), 505 isset($_GET['destination']) ? $_GET['destination'] : 'node/'. $node->nid, 506 t('This action cannot be undone.'), 507 t('Delete'), 508 t('Cancel') 509 ); 510 } 511 512 /** 513 * Execute node deletion 514 */ 515 function node_delete_confirm_submit($form, &$form_state) { 516 if ($form_state['values']['confirm']) { 517 node_delete($form_state['values']['nid']); 518 } 519 520 $form_state['redirect'] = '<front>'; 521 } 522 523 /** 524 * Generate an overview table of older revisions of a node. 525 */ 526 function node_revision_overview($node) { 527 drupal_set_title(t('Revisions for %title', array('%title' => $node->title))); 528 529 $header = array(t('Revision'), array('data' => t('Operations'), 'colspan' => 2)); 530 531 $revisions = node_revision_list($node); 532 533 $rows = array(); 534 $revert_permission = FALSE; 535 if ((user_access('revert revisions') || user_access('administer nodes')) && node_access('update', $node)) { 536 $revert_permission = TRUE; 537 } 538 $delete_permission = FALSE; 539 if ((user_access('delete revisions') || user_access('administer nodes')) && node_access('delete', $node)) { 540 $delete_permission = TRUE; 541 } 542 foreach ($revisions as $revision) { 543 $row = array(); 544 $operations = array(); 545 546 if ($revision->current_vid > 0) { 547 $row[] = array('data' => t('!date by !username', array('!date' => l(format_date($revision->timestamp, 'small'), "node/$node->nid"), '!username' => theme('username', $revision))) 548 . (($revision->log != '') ? '<p class="revision-log">'. filter_xss($revision->log) .'</p>' : ''), 549 'class' => 'revision-current'); 550 $operations[] = array('data' => theme('placeholder', t('current revision')), 'class' => 'revision-current', 'colspan' => 2); 551 } 552 else { 553 $row[] = t('!date by !username', array('!date' => l(format_date($revision->timestamp, 'small'), "node/$node->nid/revisions/$revision->vid/view"), '!username' => theme('username', $revision))) 554 . (($revision->log != '') ? '<p class="revision-log">'. filter_xss($revision->log) .'</p>' : ''); 555 if ($revert_permission) { 556 $operations[] = l(t('revert'), "node/$node->nid/revisions/$revision->vid/revert"); 557 } 558 if ($delete_permission) { 559 $operations[] = l(t('delete'), "node/$node->nid/revisions/$revision->vid/delete"); 560 } 561 } 562 $rows[] = array_merge($row, $operations); 563 } 564 565 return theme('table', $header, $rows); 566 } 567 568 /** 569 * Ask for confirmation of the reversion to prevent against CSRF attacks. 570 */ 571 function node_revision_revert_confirm($form_state, $node_revision) { 572 $form['#node_revision'] = $node_revision; 573 return confirm_form($form, t('Are you sure you want to revert to the revision from %revision-date?', array('%revision-date' => format_date($node_revision->revision_timestamp))), 'node/'. $node_revision->nid .'/revisions', '', t('Revert'), t('Cancel')); 574 } 575 576 function node_revision_revert_confirm_submit($form, &$form_state) { 577 $node_revision = $form['#node_revision']; 578 $node_revision->revision = 1; 579 $node_revision->log = t('Copy of the revision from %date.', array('%date' => format_date($node_revision->revision_timestamp))); 580 if (module_exists('taxonomy')) { 581 $node_revision->taxonomy = array_keys($node_revision->taxonomy); 582 } 583 584 node_save($node_revision); 585 586 watchdog('content', '@type: reverted %title revision %revision.', array('@type' => $node_revision->type, '%title' => $node_revision->title, '%revision' => $node_revision->vid)); 587 drupal_set_message(t('@type %title has been reverted back to the revision from %revision-date.', array('@type' => node_get_types('name', $node_revision), '%title' => $node_revision->title, '%revision-date' => format_date($node_revision->revision_timestamp)))); 588 $form_state['redirect'] = 'node/'. $node_revision->nid .'/revisions'; 589 } 590 591 function node_revision_delete_confirm($form_state, $node_revision) { 592 $form['#node_revision'] = $node_revision; 593 return confirm_form($form, t('Are you sure you want to delete the revision from %revision-date?', array('%revision-date' => format_date($node_revision->revision_timestamp))), 'node/'. $node_revision->nid .'/revisions', t('This action cannot be undone.'), t('Delete'), t('Cancel')); 594 } 595 596 function node_revision_delete_confirm_submit($form, &$form_state) { 597 $node_revision = $form['#node_revision']; 598 db_query("DELETE FROM {node_revisions} WHERE nid = %d AND vid = %d", $node_revision->nid, $node_revision->vid); 599 node_invoke_nodeapi($node_revision, 'delete revision'); 600 watchdog('content', '@type: deleted %title revision %revision.', array('@type' => $node_revision->type, '%title' => $node_revision->title, '%revision' => $node_revision->vid)); 601 drupal_set_message(t('Revision from %revision-date of @type %title has been deleted.', array('%revision-date' => format_date($node_revision->revision_timestamp), '@type' => node_get_types('name', $node_revision), '%title' => $node_revision->title))); 602 $form_state['redirect'] = 'node/'. $node_revision->nid; 603 if (db_result(db_query('SELECT COUNT(vid) FROM {node_revisions} WHERE nid = %d', $node_revision->nid)) > 1) { 604 $form_state['redirect'] .= '/revisions'; 605 } 606 }
title
Description
Body
title
Description
Body
title
Description
Body
title
Body
| Generated: Mon Jul 9 18:01:44 2012 | Cross-referenced by PHPXref 0.7 |