00001 <?php
00002
00003
00012 function node_configure() {
00013
00014
00015
00016 if (db_result(db_query('SELECT COUNT(*) FROM {node_access}')) != 1 || count(module_implements('node_grants')) > 0) {
00017 $status = '<p>' . t('If the site is experiencing problems with permissions to content, you may have to rebuild the permissions cache. Possible causes for permission problems are disabling modules or configuration changes to permissions. Rebuilding will remove all privileges to posts, and replace them with permissions based on the current modules and settings.') . '</p>';
00018 $status .= '<p>' . t('Rebuilding may take some time if there is a lot of content or complex permission settings. After rebuilding has completed posts will automatically use the new permissions.') . '</p>';
00019
00020 $form['access'] = array(
00021 '#type' => 'fieldset',
00022 '#title' => t('Node access status'),
00023 );
00024 $form['access']['status'] = array('#value' => $status);
00025 $form['access']['rebuild'] = array(
00026 '#type' => 'submit',
00027 '#value' => t('Rebuild permissions'),
00028 );
00029 }
00030
00031 $form['default_nodes_main'] = array(
00032 '#type' => 'select', '#title' => t('Number of posts on main page'), '#default_value' => variable_get('default_nodes_main', 10),
00033 '#options' => drupal_map_assoc(array(1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 15, 20, 25, 30)),
00034 '#description' => t('The default maximum number of posts to display per page on overview pages such as the main page.')
00035 );
00036 $form['teaser_length'] = array(
00037 '#type' => 'select', '#title' => t('Length of trimmed posts'), '#default_value' => variable_get('teaser_length', 600),
00038 '#options' => array(
00039 0 => t('Unlimited'),
00040 200 => t('200 characters'),
00041 400 => t('400 characters'),
00042 600 => t('600 characters'),
00043 800 => t('800 characters'),
00044 1000 => t('1000 characters'),
00045 1200 => t('1200 characters'),
00046 1400 => t('1400 characters'),
00047 1600 => t('1600 characters'),
00048 1800 => t('1800 characters'),
00049 2000 => t('2000 characters'),
00050 ),
00051 '#description' => t("The maximum number of characters used in the trimmed version of a post. Drupal will use this setting to determine at which offset long posts should be trimmed. The trimmed version of a post is typically used as a teaser when displaying the post on the main page, in XML feeds, etc. To disable teasers, set to 'Unlimited' . Note that this setting will only affect new or updated content and will not affect existing teasers.")
00052 );
00053
00054 $form['node_preview'] = array(
00055 '#type' => 'radios',
00056 '#title' => t('Preview post'),
00057 '#default_value' => variable_get('node_preview', 0),
00058 '#options' => array(t('Optional'), t('Required')),
00059 '#description' => t('Must users preview posts before submitting?'),
00060 );
00061
00062 $form['#validate'] = array('node_configure_validate');
00063
00064 return system_settings_form($form);
00065 }
00066
00070 function node_configure_validate($form, &$form_state) {
00071 if ($form_state['values']['op'] == t('Rebuild permissions')) {
00072 drupal_goto('admin/content/node-settings/rebuild');
00073 }
00074 }
00075
00079 function node_configure_rebuild_confirm() {
00080 return confirm_form(array(), t('Are you sure you want to rebuild the permissions on site content?'),
00081 'admin/content/node-settings', t('This action rebuilds all permissions on site content, and may be a lengthy process. This action cannot be undone.'), t('Rebuild permissions'), t('Cancel'));
00082 }
00083
00087 function node_configure_rebuild_confirm_submit($form, &$form_state) {
00088 node_access_rebuild(TRUE);
00089 $form_state['redirect'] = 'admin/content/node-settings';
00090 return;
00091 }
00092
00096 function node_node_operations() {
00097 $operations = array(
00098 'publish' => array(
00099 'label' => t('Publish'),
00100 'callback' => 'node_mass_update',
00101 'callback arguments' => array('updates' => array('status' => 1)),
00102 ),
00103 'unpublish' => array(
00104 'label' => t('Unpublish'),
00105 'callback' => 'node_mass_update',
00106 'callback arguments' => array('updates' => array('status' => 0)),
00107 ),
00108 'promote' => array(
00109 'label' => t('Promote to front page'),
00110 'callback' => 'node_mass_update',
00111 'callback arguments' => array('updates' => array('status' => 1, 'promote' => 1)),
00112 ),
00113 'demote' => array(
00114 'label' => t('Demote from front page'),
00115 'callback' => 'node_mass_update',
00116 'callback arguments' => array('updates' => array('promote' => 0)),
00117 ),
00118 'sticky' => array(
00119 'label' => t('Make sticky'),
00120 'callback' => 'node_mass_update',
00121 'callback arguments' => array('updates' => array('status' => 1, 'sticky' => 1)),
00122 ),
00123 'unsticky' => array(
00124 'label' => t('Remove stickiness'),
00125 'callback' => 'node_mass_update',
00126 'callback arguments' => array('updates' => array('sticky' => 0)),
00127 ),
00128 'delete' => array(
00129 'label' => t('Delete'),
00130 'callback' => NULL,
00131 ),
00132 );
00133 return $operations;
00134 }
00135
00139 function node_filters() {
00140
00141 $filters['status'] = array(
00142 'title' => t('status'),
00143 'options' => array(
00144 'status-1' => t('published'),
00145 'status-0' => t('not published'),
00146 'promote-1' => t('promoted'),
00147 'promote-0' => t('not promoted'),
00148 'sticky-1' => t('sticky'),
00149 'sticky-0' => t('not sticky'),
00150 ),
00151 );
00152
00153 if (module_exists('translation')) {
00154 $filters['status']['options'] += array(
00155 'translate-0' => t('Up to date translation'),
00156 'translate-1' => t('Outdated translation'),
00157 );
00158 }
00159
00160 $filters['type'] = array('title' => t('type'), 'options' => node_get_types('names'));
00161
00162
00163 if ($taxonomy = module_invoke('taxonomy', 'form_all', 1)) {
00164 $filters['category'] = array('title' => t('category'), 'options' => $taxonomy);
00165 }
00166
00167 if ($languages = module_invoke('locale', 'language_list')) {
00168 $languages = array('' => t('Language neutral')) + $languages;
00169 $filters['language'] = array('title' => t('language'), 'options' => $languages);
00170 }
00171 return $filters;
00172 }
00173
00177 function node_build_filter_query() {
00178 $filters = node_filters();
00179
00180
00181 $where = $args = array();
00182 $join = '';
00183 foreach ($_SESSION['node_overview_filter'] as $index => $filter) {
00184 list($key, $value) = $filter;
00185 switch ($key) {
00186 case 'status':
00187
00188 list($key, $value) = explode('-', $value, 2);
00189 $where[] = 'n.' . $key . ' = %d';
00190 break;
00191 case 'category':
00192 $table = "tn$index";
00193 $where[] = "$table.tid = %d";
00194 $join .= "INNER JOIN {term_node} $table ON n.nid = $table.nid ";
00195 break;
00196 case 'type':
00197 $where[] = "n.type = '%s'";
00198 break;
00199 case 'language':
00200 $where[] = "n.language = '%s'";
00201 break;
00202 }
00203 $args[] = $value;
00204 }
00205 $where = count($where) ? 'WHERE ' . implode(' AND ', $where) : '';
00206
00207 return array('where' => $where, 'join' => $join, 'args' => $args);
00208 }
00209
00213 function node_filter_form() {
00214 $session = &$_SESSION['node_overview_filter'];
00215 $session = is_array($session) ? $session : array();
00216 $filters = node_filters();
00217
00218 $i = 0;
00219 $form['filters'] = array(
00220 '#type' => 'fieldset',
00221 '#title' => t('Show only items where'),
00222 '#theme' => 'node_filters',
00223 );
00224 $form['#submit'][] = 'node_filter_form_submit';
00225 foreach ($session as $filter) {
00226 list($type, $value) = $filter;
00227 if ($type == 'category') {
00228
00229 $value = module_invoke('taxonomy', 'get_term', $value);
00230 $value = $value->name;
00231 }
00232 else if ($type == 'language') {
00233 $value = empty($value) ? t('Language neutral') : module_invoke('locale', 'language_name', $value);
00234 }
00235 else {
00236 $value = $filters[$type]['options'][$value];
00237 }
00238 if ($i++) {
00239 $form['filters']['current'][] = array('#value' => t('<em>and</em> where <strong>%a</strong> is <strong>%b</strong>', array('%a' => $filters[$type]['title'], '%b' => $value)));
00240 }
00241 else {
00242 $form['filters']['current'][] = array('#value' => t('<strong>%a</strong> is <strong>%b</strong>', array('%a' => $filters[$type]['title'], '%b' => $value)));
00243 }
00244 if (in_array($type, array('type', 'language'))) {
00245
00246 unset($filters[$type]);
00247 }
00248 }
00249
00250 foreach ($filters as $key => $filter) {
00251 $names[$key] = $filter['title'];
00252 $form['filters']['status'][$key] = array('#type' => 'select', '#options' => $filter['options']);
00253 }
00254
00255 $form['filters']['filter'] = array('#type' => 'radios', '#options' => $names, '#default_value' => 'status');
00256 $form['filters']['buttons']['submit'] = array('#type' => 'submit', '#value' => (count($session) ? t('Refine') : t('Filter')));
00257 if (count($session)) {
00258 $form['filters']['buttons']['undo'] = array('#type' => 'submit', '#value' => t('Undo'));
00259 $form['filters']['buttons']['reset'] = array('#type' => 'submit', '#value' => t('Reset'));
00260 }
00261
00262 drupal_add_js('misc/form.js', 'core');
00263
00264 return $form;
00265 }
00266
00272 function theme_node_filter_form($form) {
00273 $output = '';
00274 $output .= '<div id="node-admin-filter">';
00275 $output .= drupal_render($form['filters']);
00276 $output .= '</div>';
00277 $output .= drupal_render($form);
00278 return $output;
00279 }
00280
00286 function theme_node_filters($form) {
00287 $output = '';
00288 $output .= '<ul class="clear-block">';
00289 if (!empty($form['current'])) {
00290 foreach (element_children($form['current']) as $key) {
00291 $output .= '<li>' . drupal_render($form['current'][$key]) . '</li>';
00292 }
00293 }
00294
00295 $output .= '<li><dl class="multiselect">' . (!empty($form['current']) ? '<dt><em>' . t('and') . '</em> ' . t('where') . '</dt>' : '') . '<dd class="a">';
00296 foreach (element_children($form['filter']) as $key) {
00297 $output .= drupal_render($form['filter'][$key]);
00298 }
00299 $output .= '</dd>';
00300
00301 $output .= '<dt>' . t('is') . '</dt><dd class="b">';
00302
00303 foreach (element_children($form['status']) as $key) {
00304 $output .= drupal_render($form['status'][$key]);
00305 }
00306 $output .= '</dd>';
00307
00308 $output .= '</dl>';
00309 $output .= '<div class="container-inline" id="node-admin-buttons">' . drupal_render($form['buttons']) . '</div>';
00310 $output .= '</li></ul>';
00311
00312 return $output;
00313 }
00314
00318 function node_filter_form_submit($form, &$form_state) {
00319 $filters = node_filters();
00320 switch ($form_state['values']['op']) {
00321 case t('Filter'):
00322 case t('Refine'):
00323 if (isset($form_state['values']['filter'])) {
00324 $filter = $form_state['values']['filter'];
00325
00326
00327 $flat_options = form_options_flatten($filters[$filter]['options']);
00328
00329 if (isset($flat_options[$form_state['values'][$filter]])) {
00330 $_SESSION['node_overview_filter'][] = array($filter, $form_state['values'][$filter]);
00331 }
00332 }
00333 break;
00334 case t('Undo'):
00335 array_pop($_SESSION['node_overview_filter']);
00336 break;
00337 case t('Reset'):
00338 $_SESSION['node_overview_filter'] = array();
00339 break;
00340 }
00341 }
00342
00357 function node_mass_update($nodes, $updates) {
00358
00359
00360 if (count($nodes) > 10) {
00361 $batch = array(
00362 'operations' => array(
00363 array('_node_mass_update_batch_process', array($nodes, $updates))
00364 ),
00365 'finished' => '_node_mass_update_batch_finished',
00366 'title' => t('Processing'),
00367
00368
00369 'progress_message' => '',
00370 'error_message' => t('The update has encountered an error.'),
00371
00372
00373 'file' => drupal_get_path('module', 'node') . '/node.admin.inc',
00374 );
00375 batch_set($batch);
00376 }
00377 else {
00378 foreach ($nodes as $nid) {
00379 _node_mass_update_helper($nid, $updates);
00380 }
00381 drupal_set_message(t('The update has been performed.'));
00382 }
00383 }
00384
00388 function _node_mass_update_helper($nid, $updates) {
00389 $node = node_load($nid, NULL, TRUE);
00390 foreach ($updates as $name => $value) {
00391 $node->$name = $value;
00392 }
00393 node_save($node);
00394 return $node;
00395 }
00396
00400 function _node_mass_update_batch_process($nodes, $updates, &$context) {
00401 if (!isset($context['sandbox']['progress'])) {
00402 $context['sandbox']['progress'] = 0;
00403 $context['sandbox']['max'] = count($nodes);
00404 $context['sandbox']['nodes'] = $nodes;
00405 }
00406
00407
00408 $count = min(5, count($context['sandbox']['nodes']));
00409 for ($i = 1; $i <= $count; $i++) {
00410
00411 $nid = array_shift($context['sandbox']['nodes']);
00412 $node = _node_mass_update_helper($nid, $updates);
00413
00414
00415 $context['results'][] = l($node->title, 'node/' . $node->nid);
00416
00417
00418 $context['sandbox']['progress']++;
00419 }
00420
00421
00422
00423 if ($context['sandbox']['progress'] != $context['sandbox']['max']) {
00424 $context['finished'] = $context['sandbox']['progress'] / $context['sandbox']['max'];
00425 }
00426 }
00427
00431 function _node_mass_update_batch_finished($success, $results, $operations) {
00432 if ($success) {
00433 drupal_set_message(t('The update has been performed.'));
00434 }
00435 else {
00436 drupal_set_message(t('An error occurred and processing did not complete.'), 'error');
00437 $message = format_plural(count($results), '1 item successfully processed:', '@count items successfully processed:');
00438 $message .= theme('item_list', $results);
00439 drupal_set_message($message);
00440 }
00441 }
00442
00446 function node_admin_content($form_state) {
00447 if (isset($form_state['values']['operation']) && $form_state['values']['operation'] == 'delete') {
00448 return node_multiple_delete_confirm($form_state, array_filter($form_state['values']['nodes']));
00449 }
00450 $form = node_filter_form();
00451
00452 $form['#theme'] = 'node_filter_form';
00453 $form['admin'] = node_admin_nodes();
00454
00455 return $form;
00456 }
00457
00461 function node_admin_nodes() {
00462
00463 $filter = node_build_filter_query();
00464
00465 $result = pager_query(db_rewrite_sql('SELECT n.*, u.name FROM {node} n ' . $filter['join'] . ' INNER JOIN {users} u ON n.uid = u.uid ' . $filter['where'] . ' ORDER BY n.changed DESC'), 50, 0, NULL, $filter['args']);
00466
00467
00468 $count = db_result(db_query("SELECT COUNT(*) FROM {node} n WHERE language != ''"));
00469 $multilanguage = (module_exists('locale') || $count);
00470
00471 $form['options'] = array(
00472 '#type' => 'fieldset',
00473 '#title' => t('Update options'),
00474 '#prefix' => '<div class="container-inline">',
00475 '#suffix' => '</div>',
00476 );
00477 $options = array();
00478 foreach (module_invoke_all('node_operations') as $operation => $array) {
00479 $options[$operation] = $array['label'];
00480 }
00481 $form['options']['operation'] = array(
00482 '#type' => 'select',
00483 '#options' => $options,
00484 '#default_value' => 'approve',
00485 );
00486 $form['options']['submit'] = array(
00487 '#type' => 'submit',
00488 '#value' => t('Update'),
00489 '#submit' => array('node_admin_nodes_submit'),
00490 );
00491
00492 $languages = language_list();
00493 $destination = drupal_get_destination();
00494 $nodes = array();
00495 while ($node = db_fetch_object($result)) {
00496 $nodes[$node->nid] = '';
00497 $options = empty($node->language) ? array() : array('language' => $languages[$node->language]);
00498 $form['title'][$node->nid] = array('#value' => l($node->title, 'node/' . $node->nid, $options) . ' ' . theme('mark', node_mark($node->nid, $node->changed)));
00499 $form['name'][$node->nid] = array('#value' => check_plain(node_get_types('name', $node)));
00500 $form['username'][$node->nid] = array('#value' => theme('username', $node));
00501 $form['status'][$node->nid] = array('#value' => ($node->status ? t('published') : t('not published')));
00502 if ($multilanguage) {
00503 $form['language'][$node->nid] = array('#value' => empty($node->language) ? t('Language neutral') : t($languages[$node->language]->name));
00504 }
00505 $form['operations'][$node->nid] = array('#value' => l(t('edit'), 'node/' . $node->nid . '/edit', array('query' => $destination)));
00506 }
00507 $form['nodes'] = array('#type' => 'checkboxes', '#options' => $nodes);
00508 $form['pager'] = array('#value' => theme('pager', NULL, 50, 0));
00509 $form['#theme'] = 'node_admin_nodes';
00510 return $form;
00511 }
00512
00519 function node_admin_nodes_validate($form, &$form_state) {
00520 $nodes = array_filter($form_state['values']['nodes']);
00521 if (count($nodes) == 0) {
00522 form_set_error('', t('No items selected.'));
00523 }
00524 }
00525
00531 function node_admin_nodes_submit($form, &$form_state) {
00532 $operations = module_invoke_all('node_operations');
00533 $operation = $operations[$form_state['values']['operation']];
00534
00535 $nodes = array_filter($form_state['values']['nodes']);
00536 if ($function = $operation['callback']) {
00537
00538 if (isset($operation['callback arguments'])) {
00539 $args = array_merge(array($nodes), $operation['callback arguments']);
00540 }
00541 else {
00542 $args = array($nodes);
00543 }
00544 call_user_func_array($function, $args);
00545
00546 cache_clear_all();
00547 }
00548 else {
00549
00550
00551 $form_state['rebuild'] = TRUE;
00552 }
00553 }
00554
00555
00561 function theme_node_admin_nodes($form) {
00562
00563
00564 $has_posts = isset($form['title']) && is_array($form['title']);
00565 $select_header = $has_posts ? theme('table_select_header_cell') : '';
00566 $header = array($select_header, t('Title'), t('Type'), t('Author'), t('Status'));
00567 if (isset($form['language'])) {
00568 $header[] = t('Language');
00569 }
00570 $header[] = t('Operations');
00571 $output = '';
00572
00573 $output .= drupal_render($form['options']);
00574 if ($has_posts) {
00575 foreach (element_children($form['title']) as $key) {
00576 $row = array();
00577 $row[] = drupal_render($form['nodes'][$key]);
00578 $row[] = drupal_render($form['title'][$key]);
00579 $row[] = drupal_render($form['name'][$key]);
00580 $row[] = drupal_render($form['username'][$key]);
00581 $row[] = drupal_render($form['status'][$key]);
00582 if (isset($form['language'])) {
00583 $row[] = drupal_render($form['language'][$key]);
00584 }
00585 $row[] = drupal_render($form['operations'][$key]);
00586 $rows[] = $row;
00587 }
00588
00589 }
00590 else {
00591 $rows[] = array(array('data' => t('No posts available.'), 'colspan' => '6'));
00592 }
00593
00594 $output .= theme('table', $header, $rows);
00595 if ($form['pager']['#value']) {
00596 $output .= drupal_render($form['pager']);
00597 }
00598
00599 $output .= drupal_render($form);
00600
00601 return $output;
00602 }
00603
00604 function node_multiple_delete_confirm(&$form_state, $nodes) {
00605
00606 $form['nodes'] = array('#prefix' => '<ul>', '#suffix' => '</ul>', '#tree' => TRUE);
00607
00608 foreach ($nodes as $nid => $value) {
00609 $title = db_result(db_query('SELECT title FROM {node} WHERE nid = %d', $nid));
00610 $form['nodes'][$nid] = array(
00611 '#type' => 'hidden',
00612 '#value' => $nid,
00613 '#prefix' => '<li>',
00614 '#suffix' => check_plain($title) . "</li>\n",
00615 );
00616 }
00617 $form['operation'] = array('#type' => 'hidden', '#value' => 'delete');
00618 $form['#submit'][] = 'node_multiple_delete_confirm_submit';
00619 return confirm_form($form,
00620 t('Are you sure you want to delete these items?'),
00621 'admin/content/node', t('This action cannot be undone.'),
00622 t('Delete all'), t('Cancel'));
00623 }
00624
00625 function node_multiple_delete_confirm_submit($form, &$form_state) {
00626 if ($form_state['values']['confirm']) {
00627 foreach ($form_state['values']['nodes'] as $nid => $value) {
00628 node_delete($nid);
00629 }
00630 drupal_set_message(t('The items have been deleted.'));
00631 }
00632 $form_state['redirect'] = 'admin/content/node';
00633 return;
00634 }
00635