source: sipes/cord/modules/node/node.admin.inc @ 8a8efa8

stableversion-3.0
Last change on this file since 8a8efa8 was d7a822e, checked in by José Gregorio Puentes <jpuentes@…>, 8 años ago

se agrego el directorio del cord

  • Propiedad mode establecida a 100755
File size: 21.2 KB
Línea 
1<?php
2
3/**
4 * @file
5 * Content administration and module settings UI.
6 */
7
8/**
9 * Menu callback; presents general node configuration options.
10 */
11function node_configure() {
12  $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>';
13  $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>';
14
15  $form['access'] = array(
16    '#type' => 'fieldset',
17    '#title' => t('Node access status'),
18  );
19  $form['access']['status'] = array('#value' => $status);
20  $form['access']['rebuild'] = array(
21    '#type' => 'submit',
22    '#value' => t('Rebuild permissions'),
23    '#submit' => array('node_configure_access_submit'),
24  );
25
26  $form['default_nodes_main'] = array(
27    '#type' => 'select', '#title' => t('Number of posts on main page'), '#default_value' => variable_get('default_nodes_main', 10),
28    '#options' => drupal_map_assoc(array(1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 15, 20, 25, 30)),
29    '#description' => t('The default maximum number of posts to display per page on overview pages such as the main page.')
30  );
31  $form['teaser_length'] = array(
32    '#type' => 'select', '#title' => t('Length of trimmed posts'), '#default_value' => variable_get('teaser_length', 600),
33    '#options' => array(
34      0 => t('Unlimited'),
35      200 => t('200 characters'),
36      400 => t('400 characters'),
37      600 => t('600 characters'),
38      800 => t('800 characters'),
39      1000 => t('1000 characters'),
40      1200 => t('1200 characters'),
41      1400 => t('1400 characters'),
42      1600 => t('1600 characters'),
43      1800 => t('1800 characters'),
44      2000 => t('2000 characters'),
45    ),
46    '#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.")
47  );
48
49  $form['node_preview'] = array(
50    '#type' => 'radios',
51    '#title' => t('Preview post'),
52    '#default_value' => variable_get('node_preview', 0),
53    '#options' => array(t('Optional'), t('Required')),
54    '#description' => t('Must users preview posts before submitting?'),
55  );
56
57  return system_settings_form($form);
58}
59
60/**
61 * Form button submit callback.
62 */
63function node_configure_access_submit($form, &$form_state) {
64  $form_state['redirect'] = 'admin/content/node-settings/rebuild';
65}
66
67/**
68 * Menu callback: confirm rebuilding of permissions.
69 */
70function node_configure_rebuild_confirm() {
71  return confirm_form(array(), t('Are you sure you want to rebuild the permissions on site content?'),
72                  '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'));
73}
74
75/**
76 * Handler for wipe confirmation
77 */
78function node_configure_rebuild_confirm_submit($form, &$form_state) {
79  node_access_rebuild(TRUE);
80  $form_state['redirect'] = 'admin/content/node-settings';
81}
82
83/**
84 * Implementation of hook_node_operations().
85 */
86function node_node_operations() {
87  $operations = array(
88    'publish' => array(
89      'label' => t('Publish'),
90      'callback' => 'node_mass_update',
91      'callback arguments' => array('updates' => array('status' => 1)),
92    ),
93    'unpublish' => array(
94      'label' => t('Unpublish'),
95      'callback' => 'node_mass_update',
96      'callback arguments' => array('updates' => array('status' => 0)),
97    ),
98    'promote' => array(
99      'label' => t('Promote to front page'),
100      'callback' => 'node_mass_update',
101      'callback arguments' => array('updates' => array('status' => 1, 'promote' => 1)),
102    ),
103    'demote' => array(
104      'label' => t('Demote from front page'),
105      'callback' => 'node_mass_update',
106      'callback arguments' => array('updates' => array('promote' => 0)),
107    ),
108    'sticky' => array(
109      'label' => t('Make sticky'),
110      'callback' => 'node_mass_update',
111      'callback arguments' => array('updates' => array('status' => 1, 'sticky' => 1)),
112    ),
113    'unsticky' => array(
114      'label' => t('Remove stickiness'),
115      'callback' => 'node_mass_update',
116      'callback arguments' => array('updates' => array('sticky' => 0)),
117    ),
118    'delete' => array(
119      'label' => t('Delete'),
120      'callback' => NULL,
121    ),
122  );
123  return $operations;
124}
125
126/**
127 * List node administration filters that can be applied.
128 */
129function node_filters() {
130  // Regular filters
131  $filters['status'] = array(
132    'title' => t('status'),
133    'options' => array(
134      'status-1' => t('published'),
135      'status-0' => t('not published'),
136      'promote-1' => t('promoted'),
137      'promote-0' => t('not promoted'),
138      'sticky-1' => t('sticky'),
139      'sticky-0' => t('not sticky'),
140    ),
141  );
142  // Include translation states if we have this module enabled
143  if (module_exists('translation')) {
144    $filters['status']['options'] += array(
145      'translate-0' => t('Up to date translation'),
146      'translate-1' => t('Outdated translation'),
147    );
148  }
149
150  $filters['type'] = array('title' => t('type'), 'options' => node_get_types('names'));
151
152  // The taxonomy filter
153  if ($taxonomy = module_invoke('taxonomy', 'form_all', 1)) {
154    $filters['category'] = array('title' => t('category'), 'options' => $taxonomy);
155  }
156  // Language filter if there is a list of languages
157  if ($languages = module_invoke('locale', 'language_list')) {
158    $languages = array('' => t('Language neutral')) + $languages;
159    $filters['language'] = array('title' => t('language'), 'options' => $languages);
160  }
161  return $filters;
162}
163
164/**
165 * Build query for node administration filters based on session.
166 */
167function node_build_filter_query() {
168  $filters = node_filters();
169
170  // Build query
171  $where = $args = array();
172  $join = '';
173  foreach ($_SESSION['node_overview_filter'] as $index => $filter) {
174    list($key, $value) = $filter;
175    switch ($key) {
176      case 'status':
177        // Note: no exploitable hole as $key/$value have already been checked when submitted
178        list($key, $value) = explode('-', $value, 2);
179        $where[] = 'n.'. $key .' = %d';
180        break;
181      case 'category':
182        $table = "tn$index";
183        $where[] = "$table.tid = %d";
184        $join .= "INNER JOIN {term_node} $table ON n.vid = $table.vid ";
185        break;
186      case 'type':
187        $where[] = "n.type = '%s'";
188        break;
189      case 'language':
190        $where[] = "n.language = '%s'";
191        break;
192    }
193    $args[] = $value;
194  }
195  $where = count($where) ? 'WHERE '. implode(' AND ', $where) : '';
196
197  return array('where' => $where, 'join' => $join, 'args' => $args);
198}
199
200/**
201 * Return form for node administration filters.
202 */
203function node_filter_form() {
204  $session = &$_SESSION['node_overview_filter'];
205  $session = is_array($session) ? $session : array();
206  $filters = node_filters();
207
208  $i = 0;
209  $form['filters'] = array(
210    '#type' => 'fieldset',
211    '#title' => t('Show only items where'),
212    '#theme' => 'node_filters',
213  );
214  $form['#submit'][] = 'node_filter_form_submit';
215  foreach ($session as $filter) {
216    list($type, $value) = $filter;
217    if ($type == 'category') {
218      // Load term name from DB rather than search and parse options array.
219      $value = module_invoke('taxonomy', 'get_term', $value);
220      $value = $value->name;
221    }
222    else if ($type == 'language') {
223      $value = empty($value) ? t('Language neutral') : module_invoke('locale', 'language_name', $value);
224    }
225    else {
226      $value = $filters[$type]['options'][$value];
227    }
228    if ($i++) {
229      $form['filters']['current'][] = array('#value' => t('<em>and</em> where <strong>%a</strong> is <strong>%b</strong>', array('%a' => $filters[$type]['title'], '%b' => $value)));
230    }
231    else {
232      $form['filters']['current'][] = array('#value' => t('<strong>%a</strong> is <strong>%b</strong>', array('%a' => $filters[$type]['title'], '%b' => $value)));
233    }
234    if (in_array($type, array('type', 'language'))) {
235      // Remove the option if it is already being filtered on.
236      unset($filters[$type]);
237    }
238  }
239
240  foreach ($filters as $key => $filter) {
241    $names[$key] = $filter['title'];
242    $form['filters']['status'][$key] = array('#type' => 'select', '#options' => $filter['options']);
243  }
244
245  $form['filters']['filter'] = array('#type' => 'radios', '#options' => $names, '#default_value' => 'status');
246  $form['filters']['buttons']['submit'] = array('#type' => 'submit', '#value' => (count($session) ? t('Refine') : t('Filter')));
247  if (count($session)) {
248    $form['filters']['buttons']['undo'] = array('#type' => 'submit', '#value' => t('Undo'));
249    $form['filters']['buttons']['reset'] = array('#type' => 'submit', '#value' => t('Reset'));
250  }
251
252  drupal_add_js('misc/form.js', 'core');
253
254  return $form;
255}
256
257/**
258 * Theme node administration filter form.
259 *
260 * @ingroup themeable
261 */
262function theme_node_filter_form($form) {
263  $output = '';
264  $output .= '<div id="node-admin-filter">';
265  $output .= drupal_render($form['filters']);
266  $output .= '</div>';
267  $output .= drupal_render($form);
268  return $output;
269}
270
271/**
272 * Theme node administration filter selector.
273 *
274 * @ingroup themeable
275 */
276function theme_node_filters($form) {
277  $output = '';
278  $output .= '<ul class="clear-block">';
279  if (!empty($form['current'])) {
280    foreach (element_children($form['current']) as $key) {
281      $output .= '<li>'. drupal_render($form['current'][$key]) .'</li>';
282    }
283  }
284
285  $output .= '<li><dl class="multiselect">'. (!empty($form['current']) ? '<dt><em>'. t('and') .'</em> '. t('where') .'</dt>' : '') .'<dd class="a">';
286  foreach (element_children($form['filter']) as $key) {
287    $output .= drupal_render($form['filter'][$key]);
288  }
289  $output .= '</dd>';
290
291  $output .= '<dt>'. t('is') .'</dt><dd class="b">';
292
293  foreach (element_children($form['status']) as $key) {
294    $output .= drupal_render($form['status'][$key]);
295  }
296  $output .= '</dd>';
297
298  $output .= '</dl>';
299  $output .= '<div class="container-inline" id="node-admin-buttons">'. drupal_render($form['buttons']) .'</div>';
300  $output .= '</li></ul>';
301
302  return $output;
303}
304
305/**
306 * Process result from node administration filter form.
307 */
308function node_filter_form_submit($form, &$form_state) {
309  $filters = node_filters();
310  switch ($form_state['values']['op']) {
311    case t('Filter'):
312    case t('Refine'):
313      if (isset($form_state['values']['filter'])) {
314        $filter = $form_state['values']['filter'];
315
316        // Flatten the options array to accommodate hierarchical/nested options.
317        $flat_options = form_options_flatten($filters[$filter]['options']);
318
319        if (isset($flat_options[$form_state['values'][$filter]])) {
320          $_SESSION['node_overview_filter'][] = array($filter, $form_state['values'][$filter]);
321        }
322      }
323      break;
324    case t('Undo'):
325      array_pop($_SESSION['node_overview_filter']);
326      break;
327    case t('Reset'):
328      $_SESSION['node_overview_filter'] = array();
329      break;
330  }
331}
332
333/**
334 * Make mass update of nodes, changing all nodes in the $nodes array
335 * to update them with the field values in $updates.
336 *
337 * IMPORTANT NOTE: This function is intended to work when called
338 * from a form submit handler. Calling it outside of the form submission
339 * process may not work correctly.
340 *
341 * @param array $nodes
342 *   Array of node nids to update.
343 * @param array $updates
344 *   Array of key/value pairs with node field names and the
345 *   value to update that field to.
346 */
347function node_mass_update($nodes, $updates) {
348  // We use batch processing to prevent timeout when updating a large number
349  // of nodes.
350  if (count($nodes) > 10) {
351    $batch = array(
352      'operations' => array(
353        array('_node_mass_update_batch_process', array($nodes, $updates))
354      ),
355      'finished' => '_node_mass_update_batch_finished',
356      'title' => t('Processing'),
357      // We use a single multi-pass operation, so the default
358      // 'Remaining x of y operations' message will be confusing here.
359      'progress_message' => '',
360      'error_message' => t('The update has encountered an error.'),
361      // The operations do not live in the .module file, so we need to
362      // tell the batch engine which file to load before calling them.
363      'file' => drupal_get_path('module', 'node') .'/node.admin.inc',
364    );
365    batch_set($batch);
366  }
367  else {
368    foreach ($nodes as $nid) {
369      _node_mass_update_helper($nid, $updates);
370    }
371    drupal_set_message(t('The update has been performed.'));
372  }
373}
374
375/**
376 * Node Mass Update - helper function.
377 */
378function _node_mass_update_helper($nid, $updates) {
379  $node = node_load($nid, NULL, TRUE);
380  foreach ($updates as $name => $value) {
381    $node->$name = $value;
382  }
383  node_save($node);
384  return $node;
385}
386
387/**
388 * Node Mass Update Batch operation
389 */
390function _node_mass_update_batch_process($nodes, $updates, &$context) {
391  if (!isset($context['sandbox']['progress'])) {
392    $context['sandbox']['progress'] = 0;
393    $context['sandbox']['max'] = count($nodes);
394    $context['sandbox']['nodes'] = $nodes;
395  }
396
397  // Process nodes by groups of 5.
398  $count = min(5, count($context['sandbox']['nodes']));
399  for ($i = 1; $i <= $count; $i++) {
400    // For each nid, load the node, reset the values, and save it.
401    $nid = array_shift($context['sandbox']['nodes']);
402    $node = _node_mass_update_helper($nid, $updates);
403
404    // Store result for post-processing in the finished callback.
405    $context['results'][] = l($node->title, 'node/'. $node->nid);
406
407    // Update our progress information.
408    $context['sandbox']['progress']++;
409  }
410
411  // Inform the batch engine that we are not finished,
412  // and provide an estimation of the completion level we reached.
413  if ($context['sandbox']['progress'] != $context['sandbox']['max']) {
414    $context['finished'] = $context['sandbox']['progress'] / $context['sandbox']['max'];
415  }
416}
417
418/**
419 * Node Mass Update Batch 'finished' callback.
420 */
421function _node_mass_update_batch_finished($success, $results, $operations) {
422  if ($success) {
423    drupal_set_message(t('The update has been performed.'));
424  }
425  else {
426    drupal_set_message(t('An error occurred and processing did not complete.'), 'error');
427    $message = format_plural(count($results), '1 item successfully processed:', '@count items successfully processed:');
428    $message .= theme('item_list', $results);
429    drupal_set_message($message);
430  }
431}
432
433/**
434 * Menu callback: content administration.
435 */
436function node_admin_content($form_state) {
437  if (isset($form_state['values']['operation']) && $form_state['values']['operation'] == 'delete') {
438    return node_multiple_delete_confirm($form_state, array_filter($form_state['values']['nodes']));
439  }
440  $form = node_filter_form();
441
442  $form['#theme'] = 'node_filter_form';
443  $form['admin']  = node_admin_nodes();
444
445  return $form;
446}
447
448/**
449 * Form builder: Builds the node administration overview.
450 */
451function node_admin_nodes() {
452
453  $filter = node_build_filter_query();
454
455  $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']);
456
457  // Enable language column if locale is enabled or if we have any node with language
458  $count = db_result(db_query("SELECT COUNT(*) FROM {node} n WHERE language != ''"));
459  $multilanguage = (module_exists('locale') || $count);
460
461  $form['options'] = array(
462    '#type' => 'fieldset',
463    '#title' => t('Update options'),
464    '#prefix' => '<div class="container-inline">',
465    '#suffix' => '</div>',
466  );
467  $options = array();
468  foreach (module_invoke_all('node_operations') as $operation => $array) {
469    $options[$operation] = $array['label'];
470  }
471  $form['options']['operation'] = array(
472    '#type' => 'select',
473    '#options' => $options,
474    '#default_value' => 'approve',
475  );
476  $form['options']['submit'] = array(
477    '#type' => 'submit',
478    '#value' => t('Update'),
479    '#submit' => array('node_admin_nodes_submit'),
480  );
481
482  $languages = language_list();
483  $destination = drupal_get_destination();
484  $nodes = array();
485  while ($node = db_fetch_object($result)) {
486    $nodes[$node->nid] = '';
487    $options = empty($node->language) ? array() : array('language' => $languages[$node->language]);
488    $form['title'][$node->nid] = array('#value' => l($node->title, 'node/'. $node->nid, $options) .' '. theme('mark', node_mark($node->nid, $node->changed)));
489    $form['name'][$node->nid] =  array('#value' => check_plain(node_get_types('name', $node)));
490    $form['username'][$node->nid] = array('#value' => theme('username', $node));
491    $form['status'][$node->nid] =  array('#value' => ($node->status ? t('published') : t('not published')));
492    if ($multilanguage) {
493      $form['language'][$node->nid] = array('#value' => empty($node->language) ? t('Language neutral') : t($languages[$node->language]->name));
494    }
495    $form['operations'][$node->nid] = array('#value' => l(t('edit'), 'node/'. $node->nid .'/edit', array('query' => $destination)));
496  }
497  $form['nodes'] = array('#type' => 'checkboxes', '#options' => $nodes);
498  $form['pager'] = array('#value' => theme('pager', NULL, 50, 0));
499  $form['#theme'] = 'node_admin_nodes';
500  return $form;
501}
502
503/**
504 * Validate node_admin_nodes form submissions.
505 *
506 * Check if any nodes have been selected to perform the chosen
507 * 'Update option' on.
508 */
509function node_admin_nodes_validate($form, &$form_state) {
510  $nodes = array_filter($form_state['values']['nodes']);
511  if (count($nodes) == 0) {
512    form_set_error('', t('No items selected.'));
513  }
514}
515
516/**
517 * Process node_admin_nodes form submissions.
518 *
519 * Execute the chosen 'Update option' on the selected nodes.
520 */
521function node_admin_nodes_submit($form, &$form_state) {
522  $operations = module_invoke_all('node_operations');
523  $operation = $operations[$form_state['values']['operation']];
524  // Filter out unchecked nodes
525  $nodes = array_filter($form_state['values']['nodes']);
526  if ($function = $operation['callback']) {
527    // Add in callback arguments if present.
528    if (isset($operation['callback arguments'])) {
529      $args = array_merge(array($nodes), $operation['callback arguments']);
530    }
531    else {
532      $args = array($nodes);
533    }
534    call_user_func_array($function, $args);
535
536    cache_clear_all();
537  }
538  else {
539    // We need to rebuild the form to go to a second step.  For example, to
540    // show the confirmation form for the deletion of nodes.
541    $form_state['rebuild'] = TRUE;
542  }
543}
544
545
546/**
547 * Theme node administration overview.
548 *
549 * @ingroup themeable
550 */
551function theme_node_admin_nodes($form) {
552  // If there are rows in this form, then $form['title'] contains a list of
553  // the title form elements.
554  $has_posts = isset($form['title']) && is_array($form['title']);
555  $select_header = $has_posts ? theme('table_select_header_cell') : '';
556  $header = array($select_header, t('Title'), t('Type'), t('Author'), t('Status'));
557  if (isset($form['language'])) {
558    $header[] = t('Language');
559  }
560  $header[] = t('Operations');
561  $output = '';
562
563  $output .= drupal_render($form['options']);
564  if ($has_posts) {
565    foreach (element_children($form['title']) as $key) {
566      $row = array();
567      $row[] = drupal_render($form['nodes'][$key]);
568      $row[] = drupal_render($form['title'][$key]);
569      $row[] = drupal_render($form['name'][$key]);
570      $row[] = drupal_render($form['username'][$key]);
571      $row[] = drupal_render($form['status'][$key]);
572      if (isset($form['language'])) {
573        $row[] = drupal_render($form['language'][$key]);
574      }
575      $row[] = drupal_render($form['operations'][$key]);
576      $rows[] = $row;
577    }
578
579  }
580  else {
581    $rows[] = array(array('data' => t('No posts available.'), 'colspan' => '6'));
582  }
583
584  $output .= theme('table', $header, $rows);
585  if ($form['pager']['#value']) {
586    $output .= drupal_render($form['pager']);
587  }
588
589  $output .= drupal_render($form);
590
591  return $output;
592}
593
594function node_multiple_delete_confirm(&$form_state, $nodes) {
595
596  $form['nodes'] = array('#prefix' => '<ul>', '#suffix' => '</ul>', '#tree' => TRUE);
597  // array_filter returns only elements with TRUE values
598  foreach ($nodes as $nid => $value) {
599    $title = db_result(db_query('SELECT title FROM {node} WHERE nid = %d', $nid));
600    $form['nodes'][$nid] = array(
601      '#type' => 'hidden',
602      '#value' => $nid,
603      '#prefix' => '<li>',
604      '#suffix' => check_plain($title) ."</li>\n",
605    );
606  }
607  $form['operation'] = array('#type' => 'hidden', '#value' => 'delete');
608  $form['#submit'][] = 'node_multiple_delete_confirm_submit';
609  return confirm_form($form,
610                      t('Are you sure you want to delete these items?'),
611                      'admin/content/node', t('This action cannot be undone.'),
612                      t('Delete all'), t('Cancel'));
613}
614
615function node_multiple_delete_confirm_submit($form, &$form_state) {
616  if ($form_state['values']['confirm']) {
617    foreach ($form_state['values']['nodes'] as $nid => $value) {
618      node_delete($nid);
619    }
620    drupal_set_message(t('The items have been deleted.'));
621  }
622  $form_state['redirect'] = 'admin/content/node';
623  return;
624}
625
Nota: Vea TracBrowser para ayuda de uso del navegador del repositorio.