node.install 21.4 KB
Newer Older
1 2
<?php

3 4 5 6 7
/**
 * @file
 * Install, update and uninstall functions for the node module.
 */

8
/**
9
 * Implements hook_schema().
10 11 12
 */
function node_schema() {
  $schema['node'] = array(
13
    'description' => 'The base table for nodes.',
14
    'fields' => array(
15
      'nid' => array(
16
        'description' => 'The primary identifier for a node.',
17 18
        'type' => 'serial',
        'unsigned' => TRUE,
19 20
        'not null' => TRUE,
      ),
21 22 23 24 25 26
      'uuid' => array(
        'description' => 'Unique Key: Universally unique identifier for this entity.',
        'type' => 'varchar',
        'length' => 128,
        'not null' => FALSE,
      ),
27 28
      // Defaults to NULL in order to avoid a brief period of potential
      // deadlocks on the index.
29
      'vid' => array(
30
        'description' => 'The current {node_revision}.vid version identifier.',
31 32
        'type' => 'int',
        'unsigned' => TRUE,
33 34
        'not null' => FALSE,
        'default' => NULL,
35
      ),
36
      'type' => array(
37
        'description' => 'The {node_type}.type of this node.',
38 39 40
        'type' => 'varchar',
        'length' => 32,
        'not null' => TRUE,
41 42
        'default' => '',
      ),
43
      'langcode' => array(
44
        'description' => 'The {language}.langcode of this node.',
45 46 47
        'type' => 'varchar',
        'length' => 12,
        'not null' => TRUE,
48 49
        'default' => '',
      ),
50
      'title' => array(
51
        'description' => 'The title of this node, always treated as non-markup plain text.',
52 53 54
        'type' => 'varchar',
        'length' => 255,
        'not null' => TRUE,
55 56
        'default' => '',
      ),
57
      'uid' => array(
58
        'description' => 'The {users}.uid that owns this node; initially, this is the user that created it.',
59
        'type' => 'int',
60
        'unsigned' => TRUE,
61
        'not null' => TRUE,
62 63
        'default' => 0,
      ),
64
      'status' => array(
65
        'description' => 'Boolean indicating whether the node is published (visible to non-administrators).',
66 67
        'type' => 'int',
        'not null' => TRUE,
68 69
        'default' => 1,
      ),
70
      'created' => array(
71
        'description' => 'The Unix timestamp when the node was created.',
72 73
        'type' => 'int',
        'not null' => TRUE,
74 75
        'default' => 0,
      ),
76
      'changed' => array(
77
        'description' => 'The Unix timestamp when the node was most recently saved.',
78 79
        'type' => 'int',
        'not null' => TRUE,
80 81
        'default' => 0,
      ),
82
      'comment' => array(
83
        'description' => 'Whether comments are allowed on this node: 0 = no, 1 = closed (read only), 2 = open (read/write).',
84 85
        'type' => 'int',
        'not null' => TRUE,
86 87
        'default' => 0,
      ),
88
      'promote' => array(
89
        'description' => 'Boolean indicating whether the node should be displayed on the front page.',
90 91
        'type' => 'int',
        'not null' => TRUE,
92 93
        'default' => 0,
      ),
94
      'sticky' => array(
95
        'description' => 'Boolean indicating whether the node should be displayed at the top of lists in which it appears.',
96 97
        'type' => 'int',
        'not null' => TRUE,
98 99
        'default' => 0,
      ),
100
      'tnid' => array(
101
        'description' => 'The translation set id for this node, which equals the node id of the source post in each set.',
102 103 104
        'type' => 'int',
        'unsigned' => TRUE,
        'not null' => TRUE,
105 106
        'default' => 0,
      ),
107
      'translate' => array(
108
        'description' => 'A boolean indicating whether this translation page needs to be updated.',
109 110
        'type' => 'int',
        'not null' => TRUE,
111
        'default' => 0,
112
      ),
113
    ),
114 115 116
    'indexes' => array(
      'node_changed'        => array('changed'),
      'node_created'        => array('created'),
117
      'node_frontpage'      => array('promote', 'status', 'sticky', 'created'),
118 119 120 121 122 123
      'node_status_type'    => array('status', 'type', 'nid'),
      'node_title_type'     => array('title', array('type', 4)),
      'node_type'           => array(array('type', 4)),
      'uid'                 => array('uid'),
      'tnid'                => array('tnid'),
      'translate'           => array('translate'),
124
    ),
125
    'unique keys' => array(
126
      'vid' => array('vid'),
127
      'uuid' => array('uuid'),
128
    ),
129
    'foreign keys' => array(
130 131 132 133 134 135 136 137
      'node_revision' => array(
        'table' => 'node_revision',
        'columns' => array('vid' => 'vid'),
      ),
      'node_author' => array(
        'table' => 'users',
        'columns' => array('uid' => 'uid'),
      ),
138
    ),
139
    'primary key' => array('nid'),
140
  );
141 142

  $schema['node_access'] = array(
143
    'description' => 'Identifies which realm/grant pairs a user must possess in order to view, update, or delete specific nodes.',
144
    'fields' => array(
145
      'nid' => array(
146
        'description' => 'The {node}.nid this record affects.',
147 148 149
        'type' => 'int',
        'unsigned' => TRUE,
        'not null' => TRUE,
150 151
        'default' => 0,
      ),
152
      'gid' => array(
153
        'description' => "The grant ID a user must possess in the specified realm to gain this row's privileges on the node.",
154 155 156
        'type' => 'int',
        'unsigned' => TRUE,
        'not null' => TRUE,
157 158
        'default' => 0,
      ),
159
      'realm' => array(
160
        'description' => 'The realm in which the user must possess the grant ID. Each node access node can define one or more realms.',
161 162 163
        'type' => 'varchar',
        'length' => 255,
        'not null' => TRUE,
164 165
        'default' => '',
      ),
166
      'grant_view' => array(
167
        'description' => 'Boolean indicating whether a user with the realm/grant pair can view this node.',
168 169 170 171
        'type' => 'int',
        'unsigned' => TRUE,
        'not null' => TRUE,
        'default' => 0,
172 173
        'size' => 'tiny',
      ),
174
      'grant_update' => array(
175
        'description' => 'Boolean indicating whether a user with the realm/grant pair can edit this node.',
176 177 178 179
        'type' => 'int',
        'unsigned' => TRUE,
        'not null' => TRUE,
        'default' => 0,
180 181
        'size' => 'tiny',
      ),
182
      'grant_delete' => array(
183
        'description' => 'Boolean indicating whether a user with the realm/grant pair can delete this node.',
184 185 186 187
        'type' => 'int',
        'unsigned' => TRUE,
        'not null' => TRUE,
        'default' => 0,
188
        'size' => 'tiny',
189
      ),
190
    ),
191
    'primary key' => array('nid', 'gid', 'realm'),
192 193 194 195 196 197
    'foreign keys' => array(
      'affected_node' => array(
        'table' => 'node',
        'columns' => array('nid' => 'nid'),
      ),
     ),
198
  );
199

200
  $schema['node_revision'] = array(
201
    'description' => 'Stores information about each saved version of a {node}.',
202
    'fields' => array(
203
      'nid' => array(
204
        'description' => 'The {node} this version belongs to.',
205 206 207
        'type' => 'int',
        'unsigned' => TRUE,
        'not null' => TRUE,
208 209
        'default' => 0,
      ),
210
      'vid' => array(
211
        'description' => 'The primary identifier for this version.',
212 213
        'type' => 'serial',
        'unsigned' => TRUE,
214 215
        'not null' => TRUE,
      ),
216
      'uid' => array(
217
        'description' => 'The {users}.uid that created this version.',
218
        'type' => 'int',
219
        'unsigned' => TRUE,
220
        'not null' => TRUE,
221 222
        'default' => 0,
      ),
223
      'title' => array(
224
        'description' => 'The title of this version.',
225 226 227
        'type' => 'varchar',
        'length' => 255,
        'not null' => TRUE,
228 229
        'default' => '',
      ),
230
      'log' => array(
231
        'description' => 'The log entry explaining the changes in this version.',
232 233
        'type' => 'text',
        'not null' => TRUE,
234 235
        'size' => 'big',
      ),
236
      'timestamp' => array(
237
        'description' => 'A Unix timestamp indicating when this version was created.',
238 239
        'type' => 'int',
        'not null' => TRUE,
240 241
        'default' => 0,
      ),
242 243 244 245 246 247 248 249 250 251 252 253 254 255 256 257 258 259 260 261 262 263 264 265
      'status' => array(
        'description' => 'Boolean indicating whether the node (at the time of this revision) is published (visible to non-administrators).',
        'type' => 'int',
        'not null' => TRUE,
        'default' => 1,
      ),
      'comment' => array(
        'description' => 'Whether comments are allowed on this node (at the time of this revision): 0 = no, 1 = closed (read only), 2 = open (read/write).',
        'type' => 'int',
        'not null' => TRUE,
        'default' => 0,
      ),
      'promote' => array(
        'description' => 'Boolean indicating whether the node (at the time of this revision) should be displayed on the front page.',
        'type' => 'int',
        'not null' => TRUE,
        'default' => 0,
      ),
      'sticky' => array(
        'description' => 'Boolean indicating whether the node (at the time of this revision) should be displayed at the top of lists in which it appears.',
        'type' => 'int',
        'not null' => TRUE,
        'default' => 0,
      ),
266
    ),
267 268
    'indexes' => array(
      'nid' => array('nid'),
269 270
      'uid' => array('uid'),
    ),
271
    'primary key' => array('vid'),
272
    'foreign keys' => array(
273 274 275 276 277 278 279 280
      'versioned_node' => array(
        'table' => 'node',
        'columns' => array('nid' => 'nid'),
      ),
      'version_author' => array(
        'table' => 'users',
        'columns' => array('uid' => 'uid'),
      ),
281
    ),
282
  );
283 284

  $schema['node_type'] = array(
285
    'description' => 'Stores information about all defined {node} types.',
286
    'fields' => array(
287
      'type' => array(
288
        'description' => 'The machine-readable name of this type.',
289 290
        'type' => 'varchar',
        'length' => 32,
291 292
        'not null' => TRUE,
      ),
293
      'name' => array(
294
        'description' => 'The human-readable name of this type.',
295 296 297
        'type' => 'varchar',
        'length' => 255,
        'not null' => TRUE,
298
        'default' => '',
299
        'translatable' => TRUE,
300
      ),
301
      'base' => array(
302
        'description' => 'The base string used to construct callbacks corresponding to this node type.',
303 304
        'type' => 'varchar',
        'length' => 255,
305 306
        'not null' => TRUE,
      ),
307 308 309 310 311 312
      'module' => array(
        'description' => 'The module defining this node type.',
        'type' => 'varchar',
        'length' => 255,
        'not null' => TRUE,
      ),
313
      'description' => array(
314
        'description' => 'A brief description of this type.',
315 316
        'type' => 'text',
        'not null' => TRUE,
317
        'size' => 'medium',
318
        'translatable' => TRUE,
319
      ),
320
      'help' => array(
321
        'description' => 'Help information shown to the user when creating a {node} of this type.',
322 323
        'type' => 'text',
        'not null' => TRUE,
324
        'size' => 'medium',
325
        'translatable' => TRUE,
326
      ),
327
      'has_title' => array(
328
        'description' => 'Boolean indicating whether this type uses the {node}.title field.',
329 330 331
        'type' => 'int',
        'unsigned' => TRUE,
        'not null' => TRUE,
332 333
        'size' => 'tiny',
      ),
334
      'title_label' => array(
335
        'description' => 'The label displayed for the title field on the edit form.',
336 337 338
        'type' => 'varchar',
        'length' => 255,
        'not null' => TRUE,
339
        'default' => '',
340
        'translatable' => TRUE,
341
      ),
342
      'custom' => array(
343
        'description' => 'A boolean indicating whether this type is defined by a module (FALSE) or by a user via Add content type (TRUE).',
344 345 346
        'type' => 'int',
        'not null' => TRUE,
        'default' => 0,
347 348
        'size' => 'tiny',
      ),
349
      'modified' => array(
350
        'description' => 'A boolean indicating whether this type has been modified by an administrator; currently not used in any way.',
351 352 353
        'type' => 'int',
        'not null' => TRUE,
        'default' => 0,
354 355
        'size' => 'tiny',
      ),
356
      'locked' => array(
357
        'description' => 'A boolean indicating whether the administrator can change the machine name of this type.',
358 359 360
        'type' => 'int',
        'not null' => TRUE,
        'default' => 0,
361 362
        'size' => 'tiny',
      ),
363 364 365 366 367 368 369
      'disabled' => array(
        'description' => 'A boolean indicating whether the node type is disabled.',
        'type' => 'int',
        'not null' => TRUE,
        'default' => 0,
        'size' => 'tiny'
      ),
370
      'orig_type' => array(
371
        'description' => 'The original machine-readable name of this node type. This may be different from the current type name if the locked field is 0.',
372 373 374
        'type' => 'varchar',
        'length' => 255,
        'not null' => TRUE,
375
        'default' => '',
376
      ),
377
    ),
378
    'primary key' => array('type'),
379
  );
380

381

382 383
  return $schema;
}
384

385 386 387 388 389 390 391 392 393 394 395 396 397 398 399 400 401
/**
 * Implements hook_install().
 */
function node_install() {
  // Populate the node access table.
  db_insert('node_access')
    ->fields(array(
      'nid' => 0,
      'gid' => 0,
      'realm' => 'all',
      'grant_view' => 1,
      'grant_update' => 0,
      'grant_delete' => 0,
    ))
    ->execute();
}

402 403
/**
 * Implements hook_uninstall().
404 405 406
 *
 * @see node_ranking()
 * @see _node_rankings()
407 408 409 410 411 412 413 414 415 416 417
 */
function node_uninstall() {
  // Delete node type variables.
  $types = db_query('SELECT type FROM {node_type}')->fetchCol();
  foreach ($types as $type) {
    db_delete('variable')
      ->condition(db_or()
        ->condition('name', 'node_preview_' . $type)
        ->condition('name', 'node_options_' . $type)
        ->condition('name', 'node_submitted_' . $type)
        ->condition('name', 'node_permissions_' . $type)
418
        ->condition('name', 'node_type_language_translation_enabled_' . $type)
419 420
      )
      ->execute();
421
    config('language.settings')->clear('node. ' . $type . '.language.default_configuration')->save();
422 423 424 425 426 427 428 429 430
  }

  // Delete node search ranking variables.
  variable_del('node_rank_relevance');
  variable_del('node_rank_sticky');
  variable_del('node_rank_promote');
  variable_del('node_rank_recent');

  // Delete remaining general module variables.
431
  state()->delete('node.node_access_needs_rebuild');
432 433
  variable_del('node_admin_theme');
  variable_del('node_recent_block_count');
434 435 436

  // Delete any stored state.
  state()->delete('node.cron_last');
437 438
}

439
/**
440
 * Fetches node types directly from the database.
441
 *
442
 * @ingroup update_api
443
 */
444
function _update_7000_node_get_types() {
445 446 447 448 449 450 451
  $node_types = db_query('SELECT * FROM {node_type}')->fetchAllAssoc('type', PDO::FETCH_OBJ);

  // Create default settings for orphaned nodes.
  $all_types = db_query('SELECT DISTINCT type FROM {node}')->fetchCol();
  $extra_types = array_diff($all_types, array_keys($node_types));

  foreach ($extra_types as $type) {
452
    $type_object = new stdClass();
453 454 455 456 457 458 459 460 461 462 463
    $type_object->type = $type;
    // In Drupal 6, whether you have a body field or not is a flag in the node
    // type table. If it's enabled, nodes may or may not have an empty string
    // for the bodies. As we can't detect what this setting should be in
    // Drupal 7 without access to the Drupal 6 node type settings, we assume
    // the default, which is to enable the body field.
    $type_object->has_body = 1;
    $type_object->body_label = 'Body';
    $node_types[$type_object->type] = $type_object;
  }
  return $node_types;
464
}
465 466 467 468 469 470

/**
 * @addtogroup updates-7.x-to-8.x
 * @{
 */

471 472 473 474
/**
 * Rename node type language variable names.
 *
 * @see http://drupal.org/node/540294
475 476
 *
 * @ingroup config_upgrade
477 478 479 480
 */
function node_update_8001() {
  $types = db_query('SELECT type FROM {node_type}')->fetchCol();
  foreach ($types as $type) {
481
    $node_type_language = update_variable_get('language_content_type_' . $type);
482
    if (isset($node_type_language)) {
483
      update_variable_set('node_type_language_' . $type, $node_type_language);
484
    }
485
    update_variable_del('language_content_type_' . $type);
486 487 488
  }
}

489 490 491 492 493 494 495 496 497 498 499 500 501 502
/**
 * Rename node.language field to node.langcode.
 */
function node_update_8002() {
  $spec = array(
    'description' => 'The {language}.langcode of this node.',
    'type' => 'varchar',
    'length' => 12,
    'not null' => TRUE,
    'default' => '',
  );
  db_change_field('node', 'language', 'langcode', $spec);
}

503
/**
504 505 506 507 508
 * Rename node type language variable names.
 */
function node_update_8003() {
  $types = db_query('SELECT type FROM {node_type}')->fetchCol();
  foreach ($types as $type) {
509 510
    update_variable_set('node_type_language_default_' . $type, LANGUAGE_NOT_SPECIFIED);
    $node_type_language = update_variable_get('node_type_language_' . $type, 0);
511
    if ($node_type_language == 0) {
512
      update_variable_set('node_type_language_show_' . $type, FALSE);
513 514 515 516 517 518
    }
    if ($node_type_language == 2) {
      // Translation was enabled, so enable it again and
      // unhide the language selector. Because if language is
      // LANGUAGE_NOT_SPECIFIED and the selector hidden, translation
      // cannot be enabled.
519
      update_variable_set('node_type_language_show_' . $type, TRUE);
520
      update_variable_set('node_type_language_translation_enabled_' . $type, TRUE);
521
    }
522
    update_variable_del('node_type_language_' . $type);
523 524 525
  }
}

526 527 528 529 530 531 532 533 534 535 536 537 538 539 540 541 542 543 544 545 546 547 548 549
/**
 * Create a UUID column for nodes.
 */
function node_update_8004() {
  $spec = array(
    'description' => 'Unique Key: Universally unique identifier for this entity.',
    'type' => 'varchar',
    'length' => 128,
    'not null' => FALSE,
  );
  $keys = array(
    'unique keys' => array(
      'uuid' => array('uuid'),
    ),
  );
  // Account for sites having the contributed UUID module installed.
  if (db_field_exists('node', 'uuid')) {
    db_change_field('node', 'uuid', 'uuid', $spec, $keys);
  }
  else {
    db_add_field('node', 'uuid', $spec, $keys);
  }
}

550 551 552 553 554 555 556 557 558 559 560 561 562 563 564 565 566 567 568 569 570 571 572 573 574 575 576 577 578 579 580 581 582 583 584 585 586 587 588 589 590 591 592 593 594 595 596 597 598 599 600 601 602 603 604 605 606
/**
 * Make *id fields unsigned.
 */
function node_update_8005() {
  db_drop_index('node', 'uid');
  db_change_field('node', 'uid', 'uid',
    array(
      'description' => 'The {users}.uid that owns this node; initially, this is the user that created it.',
      'type' => 'int',
      'unsigned' => TRUE,
      'not null' => TRUE,
      'default' => 0,
    ),
    array('indexes' => array(
      'uid' => array('uid'),
    ))
  );

  db_drop_index('node_revision', 'uid');
  db_change_field('node_revision', 'uid', 'uid',
    array(
      'description' => 'The {users}.uid that created this version.',
      'type' => 'int',
      'unsigned' => TRUE,
      'not null' => TRUE,
      'default' => 0,
    ),
    array('indexes' => array(
      'uid' => array('uid'),
    ))
  );

  db_drop_primary_key('history');
  db_drop_index('history', 'nid');
  db_change_field('history', 'uid', 'uid',
    array(
      'description' => 'The {users}.uid that read the {node} nid.',
      'type' => 'int',
      'unsigned' => TRUE,
      'not null' => TRUE,
      'default' => 0,
    )
  );
  db_change_field('history', 'nid', 'nid',
    array(
      'description' => 'The {node}.nid that was read.',
      'type' => 'int',
      'unsigned' => TRUE,
      'not null' => TRUE,
      'default' => 0,
    ),
    array('primary key' => array('uid', 'nid'), 'indexes' => array(
      'nid' => array('nid'),
    ))
  );
}

607
/**
608
 * Generate a UUID for all nodes.
609 610 611 612 613 614 615 616 617 618 619 620 621 622
 */
function node_update_8006(&$sandbox) {
  if (!isset($sandbox['progress'])) {
    $sandbox['progress'] = 0;
    $sandbox['last'] = 0;
    $sandbox['max'] = db_query('SELECT COUNT(nid) FROM {node} WHERE uuid IS NULL')->fetchField();
  }

  $nids = db_query_range('SELECT nid FROM {node} WHERE nid > :nid AND uuid IS NULL ORDER BY nid ASC', 0, 10, array(':nid' => $sandbox['last']))->fetchCol();
  update_add_uuids($sandbox, 'node', 'nid', $nids);

  $sandbox['#finished'] = empty($sandbox['max']) ? 1 : ($sandbox['progress'] / $sandbox['max']);
}

623 624 625 626 627 628 629
/**
 * Move the language default values to config.
 */
function node_update_8007() {
  $types = db_query('SELECT type FROM {node_type}')->fetchCol();
  foreach ($types as $type) {
    $language_default = update_variable_get('node_type_language_default_' . $type, NULL);
630 631 632
    $language_show = update_variable_get('node_type_language_show_' . $type, NULL);
    if (isset($language_default) || isset($language_show)) {
      $values = array('langcode' => $language_default, 'language_show' => $language_show);
633 634 635 636 637
      config('language.settings')->set('node.' . $type . '.language.default_configuration', $values)->save();
    }
  }
}

638 639 640 641 642 643 644 645 646 647 648 649 650 651 652 653 654 655 656 657
/**
 * Rename default menu names.
 */
function node_update_8008() {
  // System menu's new block deltas are prefixed with 'menu-'.
  $map = array(
    'navigation' => 'menu-tools',
    'management' => 'menu-admin',
    'user-menu' => 'menu-account',
    'main-menu' => 'menu-main',
  );
  foreach ($map as $old => $new) {
    db_update('block_node_type')
      ->condition('module', 'system')
      ->condition('delta', $old)
      ->fields(array('delta' => $new))
      ->execute();
  }
}

658 659 660 661 662 663 664 665 666
/**
 * Coverts default_nodes_main variable to config.
 *
 * @ingroup config_upgrade
 */
function node_update_8009() {
  update_variables_to_config('node.settings', array('default_nodes_main' => 'items_per_page'));
}

667 668 669 670 671
/**
 * Moves node_access_needs_rebuild from variable to state.
 *
 * @ingroup config_upgrade
 */
webchick's avatar
webchick committed
672
function node_update_8010() {
673 674 675
  update_variables_to_state(array('node_access_needs_rebuild' => 'node.node_access_needs_rebuild'));
}

676 677 678 679 680 681 682 683 684
/**
 * Moves node cron last run time from variable to state.
 *
 * @ingroup config_upgrade
 */
function node_update_8011() {
  update_variables_to_state(array('node_cron_last' =>'node.cron_last'));
}

685 686 687 688 689 690 691 692 693
/**
 * Enable History module.
 */
function node_update_8012() {
  // Enable the history module without re-installing the schema.
  update_module_enable(array('history'));
}


694 695 696 697 698 699 700 701 702 703 704 705 706 707 708
/**
 * Renames global revision permissions to use the word 'all'.
 */
function node_update_8013() {
  $actions = array('view', 'delete', 'revert');

  foreach ($actions as $action) {
    db_update('role_permission')
      ->fields(array('permission' => $action . ' all revisions'))
      ->condition('permission', $action . ' revisions')
      ->condition('module', 'node')
      ->execute();
  }
}

709 710
/**
 * @} End of "addtogroup updates-7.x-to-8.x"
711 712
 * The next series of updates should start at 9000.
 */