drupal/core/modules/node/node.admin.inc

340 lines
11 KiB
PHP

<?php
/**
* @file
* Content administration and module settings user interface.
*/
use Drupal\Core\Language\Language;
use Drupal\node\NodeInterface;
/**
* Page callback: Form constructor for the permission rebuild confirmation form.
*
* @return array
* An array as expected by drupal_render().
*
* @see node_configure_rebuild_confirm_submit()
* @see node_menu()
* @ingroup forms
*/
function node_configure_rebuild_confirm() {
return confirm_form(array(), t('Are you sure you want to rebuild the permissions on site content?'),
'admin/reports/status', 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'));
}
/**
* Form submission handler for node_configure_rebuild_confirm().
*/
function node_configure_rebuild_confirm_submit($form, &$form_state) {
node_access_rebuild(TRUE);
$form_state['redirect'] = 'admin/reports/status';
}
/**
* Updates all nodes in the passed-in array with the passed-in field values.
*
* IMPORTANT NOTE: This function is intended to work when called from a form
* submission handler. Calling it outside of the form submission process may not
* work correctly.
*
* @param array $nodes
* Array of node nids or nodes to update.
* @param array $updates
* Array of key/value pairs with node field names and the value to update that
* field to.
* @param string $langcode
* (optional) The language updates should be applied to. If none is specified
* all available languages are processed.
* @param bool $load
* (optional) TRUE if $nodes contains an array of node IDs to be loaded, FALSE
* if it contains fully loaded nodes. Defaults to FALSE.
*/
function node_mass_update(array $nodes, array $updates, $langcode = NULL, $load = FALSE) {
// We use batch processing to prevent timeout when updating a large number
// of nodes.
if (count($nodes) > 10) {
$batch = array(
'operations' => array(
array('_node_mass_update_batch_process', array($nodes, $updates, $langcode, $load))
),
'finished' => '_node_mass_update_batch_finished',
'title' => t('Processing'),
// We use a single multi-pass operation, so the default
// 'Remaining x of y operations' message will be confusing here.
'progress_message' => '',
'error_message' => t('The update has encountered an error.'),
// The operations do not live in the .module file, so we need to
// tell the batch engine which file to load before calling them.
'file' => drupal_get_path('module', 'node') . '/node.admin.inc',
);
batch_set($batch);
}
else {
if ($load) {
$nodes = entity_load_multiple('node', $nodes);
}
foreach ($nodes as $node) {
_node_mass_update_helper($node, $updates, $langcode);
}
drupal_set_message(t('The update has been performed.'));
}
}
/**
* Updates individual nodes when fewer than 10 are queued.
*
* @param \Drupal\node\NodeInterface $node
* A node to update.
* @param array $updates
* Associative array of updates.
* @param string $langcode
* (optional) The language updates should be applied to. If none is specified
* all available languages are processed.
*
* @return \Drupal\node\NodeInterface
* An updated node object.
*
* @see node_mass_update()
*/
function _node_mass_update_helper(NodeInterface $node, array $updates, $langcode = NULL) {
$langcodes = isset($langcode) ? array($langcode) : array_keys($node->getTranslationLanguages());
// For efficiency manually save the original node before applying any changes.
$node->original = clone $node;
foreach ($langcodes as $langcode) {
foreach ($updates as $name => $value) {
$node->getTranslation($langcode, FALSE)->$name = $value;
}
}
$node->save();
return $node;
}
/**
* Executes a batch operation for node_mass_update().
*
* @param array $nodes
* An array of node IDs.
* @param array $updates
* Associative array of updates.
* @param bool $load
* TRUE if $nodes contains an array of node IDs to be loaded, FALSE if it
* contains fully loaded nodes.
* @param array $context
* An array of contextual key/values.
*/
function _node_mass_update_batch_process(array $nodes, array $updates, $load, array &$context) {
if (!isset($context['sandbox']['progress'])) {
$context['sandbox']['progress'] = 0;
$context['sandbox']['max'] = count($nodes);
$context['sandbox']['nodes'] = $nodes;
}
// Process nodes by groups of 5.
$count = min(5, count($context['sandbox']['nodes']));
for ($i = 1; $i <= $count; $i++) {
// For each nid, load the node, reset the values, and save it.
$node = array_shift($context['sandbox']['nodes']);
if ($load) {
$node = entity_load('node', $node);
}
$node = _node_mass_update_helper($node, $updates);
// Store result for post-processing in the finished callback.
$context['results'][] = l($node->label(), 'node/' . $node->nid);
// Update our progress information.
$context['sandbox']['progress']++;
}
// Inform the batch engine that we are not finished,
// and provide an estimation of the completion level we reached.
if ($context['sandbox']['progress'] != $context['sandbox']['max']) {
$context['finished'] = $context['sandbox']['progress'] / $context['sandbox']['max'];
}
}
/**
* Reports the 'finished' status of batch operation for node_mass_update().
*
* @param bool $success
* A boolean indicating whether the batch mass update operation successfully
* concluded.
* @param int $results
* The number of nodes updated via the batch mode process.
* @param array $operations
* An array of function calls (not used in this function).
*/
function _node_mass_update_batch_finished($success, $results, $operations) {
if ($success) {
drupal_set_message(t('The update has been performed.'));
}
else {
drupal_set_message(t('An error occurred and processing did not complete.'), 'error');
$message = format_plural(count($results), '1 item successfully processed:', '@count items successfully processed:');
$item_list = array(
'#theme' => 'item_list',
'#items' => $results,
);
$message .= drupal_render($item_list);
drupal_set_message($message);
}
}
/**
* Returns the admin form object to node_admin_content().
*
* @ingroup forms
*/
function node_admin_nodes() {
// Enable language column and filter if multiple languages are enabled.
$multilingual = language_multilingual();
// Build the sortable table header.
$header = array(
'title' => array(
'data' => t('Title'),
'field' => 'n.title',
),
'type' => array(
'data' => t('Content type'),
'field' => 'n.type',
'class' => array(RESPONSIVE_PRIORITY_MEDIUM),
),
'author' => array(
'data' => t('Author'),
'class' => array(RESPONSIVE_PRIORITY_LOW),
),
'status' => array(
'data' => t('Status'),
'field' => 'n.status',
),
'changed' => array(
'data' => t('Updated'),
'field' => 'n.changed',
'sort' => 'desc',
'class' => array(RESPONSIVE_PRIORITY_LOW)
,)
);
if ($multilingual) {
$header['language_name'] = array('data' => t('Language'), 'field' => 'n.langcode', 'class' => array(RESPONSIVE_PRIORITY_LOW));
}
$header['operations'] = array('data' => t('Operations'));
$query = db_select('node_field_data', 'n')
->extend('Drupal\Core\Database\Query\PagerSelectExtender')
->extend('Drupal\Core\Database\Query\TableSortExtender');
if (!user_access('bypass node access')) {
// If the user is able to view their own unpublished nodes, allow them
// to see these in addition to published nodes. Check that they actually
// have some unpublished nodes to view before adding the condition.
if (user_access('view own unpublished content') && $own_unpublished = db_query('SELECT DISTINCT nid FROM {node_field_data} WHERE uid = :uid AND status = :status', array(':uid' => $GLOBALS['user']->uid, ':status' => 0))->fetchCol()) {
$query->condition(db_or()
->condition('n.status', 1)
->condition('n.nid', $own_unpublished, 'IN')
);
}
else {
// If not, restrict the query to published nodes.
$query->condition('n.status', 1);
}
}
$nids = $query
->distinct()
->fields('n', array('nid'))
->limit(50)
->orderByHeader($header)
->addTag('node_access')
->execute()
->fetchCol();
$nodes = node_load_multiple($nids);
// Prepare the list of nodes.
$languages = language_list(Language::STATE_ALL);
$destination = drupal_get_destination();
$form['nodes'] = array(
'#type' => 'table',
'#header' => $header,
'#empty' => t('No content available.'),
);
foreach ($nodes as $node) {
$l_options = $node->langcode != Language::LANGCODE_NOT_SPECIFIED && isset($languages[$node->langcode]) ? array('language' => $languages[$node->langcode]) : array();
$mark = array(
'#theme' => 'mark',
'#mark_type' => node_mark($node->nid, $node->changed),
);
$form['nodes'][$node->nid]['title'] = array(
'#type' => 'link',
'#title' => $node->label(),
'#href' => 'node/' . $node->nid,
'#options' => $l_options,
'#suffix' => ' ' . drupal_render($mark),
);
$form['nodes'][$node->nid]['type'] = array(
'#markup' => check_plain(node_get_type_label($node)),
);
$form['nodes'][$node->nid]['author'] = array(
'#theme' => 'username',
'#account' => $node,
);
$form['nodes'][$node->nid]['status'] = array(
'#markup' => $node->status ? t('published') : t('not published'),
);
$form['nodes'][$node->nid]['changed'] = array(
'#markup' => format_date($node->changed, 'short'),
);
if ($multilingual) {
$form['nodes'][$node->nid]['language_name'] = array(
'#markup' => language_name($node->langcode),
);
}
// Build a list of all the accessible operations for the current node.
$operations = array();
if (node_access('update', $node)) {
$operations['edit'] = array(
'title' => t('Edit'),
'href' => 'node/' . $node->nid . '/edit',
'query' => $destination,
);
}
if (node_access('delete', $node)) {
$operations['delete'] = array(
'title' => t('Delete'),
'href' => 'node/' . $node->nid . '/delete',
'query' => $destination,
);
}
if ($node->isTranslatable()) {
$operations['translate'] = array(
'title' => t('Translate'),
'href' => 'node/' . $node->nid . '/translations',
'query' => $destination,
);
}
$form['nodes'][$node->nid]['operations'] = array();
if (count($operations) > 1) {
// Render an unordered list of operations links.
$form['nodes'][$node->nid]['operations'] = array(
'#type' => 'operations',
'#subtype' => 'node',
'#links' => $operations,
);
}
elseif (!empty($operations)) {
// Render the first and only operation as a link.
$link = reset($operations);
$form['nodes'][$node->nid]['operations'] = array(
'#type' => 'link',
'#title' => $link['title'],
'#href' => $link['href'],
'#options' => array('query' => $link['query']),
);
}
}
$form['pager'] = array('#theme' => 'pager');
return $form;
}