Skip to content

Instantly share code, notes, and snippets.

@deekayen
Created December 3, 2014 23:47
Show Gist options
  • Save deekayen/85fd52c56da2836b7d3d to your computer and use it in GitHub Desktop.
Save deekayen/85fd52c56da2836b7d3d to your computer and use it in GitHub Desktop.
Rebuild node access permissions in Drupal 6 using drush.
<?php
/**
* @file
* Drush code to rebuild node access.
*/
/**
* Implementation of hook_drush_command().
*/
function dnar_drush_command() {
$items = array();
$items['node-access-rebuild'] = array(
'callback' => 'dnar_drush_node_access_rebuild',
'description' => dt('Rebuild node access perrmissions.'),
'examples' => array(
'drush node-access-rebuild' => dt('Rebuild the node permissions'),
),
'aliases' => array('dnar'),
);
return $items;
}
/**
* Implementation of hook_drush_help().
*/
function dnar_drush_help($section) {
switch ($section) {
case 'drush:node-access-rebuild':
return dt('Rebuild node access permissions.');
}
}
function dnar_drush_node_access_rebuild() {
// Try to allocate enough time to rebuild node grants
if (function_exists('set_time_limit')) {
@set_time_limit(0);
}
ini_set('memory_limit', '1800M');
// Remove orphaned nodes.
db_query("DELETE na.* FROM {node_access} AS na LEFT JOIN {node} AS n USING (nid) WHERE n.nid IS NULL
AND na.nid <> 0");
$changed = db_affected_rows();
drush_log(dt('@count orphaned node records removed from the node access table.', array('@count' => $changed)), 'ok');
// Get a list of nodes.
$good = array();
$bad = array();
// We have 2 passes; first pass is for missing node_access entries.
// Second pass is a general refresh.
$sql_commands = array(
'missing' => array(
'count' => 'SELECT COUNT(n.nid) FROM {node} AS n LEFT JOIN {node_access} AS na USING (nid) WHERE na.nid IS NULL',
'results' => 'SELECT n.nid FROM {node} AS n LEFT JOIN {node_access} AS na USING (nid) WHERE na.nid IS NULL ORDER BY n.nid DESC',
),
'full refresh' => array(
'count' => 'SELECT COUNT(*) FROM {node} AS n',
'results' => 'SELECT n.nid FROM {node} AS n ORDER BY n.nid DESC',
),
);
// Do the dirty work.
foreach ($sql_commands AS $type => $command) {
$count = db_result(db_query($command['count']));
drush_log(dt('Going to process @count nodes. Mode: @mode.', array('@count' => $count, '@mode' => $type)), 'ok');
$result = db_query($command['results']);
timer_start('rebuild');
while ($node = db_fetch_object($result)) {
// Skip nodes we already hit.
if (isset($good[$node->nid])) {
continue;
}
// Load the node.
$loaded_node = node_load($node->nid, NULL, TRUE);
// Remove old records for this node.
db_query("DELETE FROM {node_access} WHERE nid = %d", $node->nid);
// To preserve database integrity, only aquire grants if the node
// loads successfully.
if (!empty($loaded_node)) {
// Set node access.
node_access_acquire_grants($loaded_node);
$good[$node->nid] = TRUE;
// Output a * every 5 nodes.
if (count($good) % 5 == 0) {
print('*');
}
// Check if a status update is needed every 100 nodes.
if (count($good) > 500 && count($good) % 100 == 0) {
// Convert time from ms to seconds.
$running_time = timer_read('rebuild')/1000;
// Output status update every 100 seconds.
if (round($running_time, -1) % 100 == 0) {
$eta = $running_time * count($good) / $count;
print("\n");
drush_log(dt('@count of @good nodes have had their permissions rebuild. ETA: @time. Current NID: @nid.',
array(
'@count' => count($good),
'@good' => $count,
'@time' => format_interval(round($eta)) . ' ' . round($running_time, -1),
'@nid' => $node->nid,
)
), 'ok');
}
}
}
else {
$bad[$node->nid] = TRUE;
print('!');
}
}
drush_log(dt('Rebuilt permissions for @count nodes. @good where correctly rebuild, @bad failed on the node load. Here is a list of the bad nodes: @badlist',
array(
'@count' => $count,
'@good' => count($good),
'@bad' => count($bad),
'@badlist' => implode("\n", $bad),
)
), 'ok');
}
node_access_needs_rebuild(FALSE);
cache_clear_all();
drush_log(dt('Block and page caches cleared.'), 'ok');
}
name = Drush node access rebuild
description = Use Drush to rebuild node access permissions.
core = 6.x
<?php
/**
* @file
* Disable Core's Node Rebuild.
*/
/**
* Implementation of hook_menu_alter().
*/
function dnar_menu_alter(&$items) {
// Disable node access rebuilding from the web.
$items['admin/content/node-settings/rebuild']['page arguments'] = array();
$items['admin/content/node-settings/rebuild']['page callback'] = 'dnar_rebuild_message';
}
/**
* Output some interesting info.
*/
function dnar_rebuild_message() {
$output = '';
$output = t('Rebuilding the permissions on this site can only be done from drush. "%command" is the command. There are %orphaned orphaned node records in the node access table. There are %missing missing records from the node access table.', array(
'%command' => 'drush node-access-rebuild',
'%orphaned' => db_result(db_query("SELECT COUNT(*) FROM {node_access} AS na LEFT JOIN {node} AS n USING (nid) WHERE n.nid IS NULL AND na.nid <> 0")),
'%missing' => db_result(db_query("SELECT COUNT(nid) FROM {node} AS n LEFT JOIN {node_access} AS na USING (nid) WHERE na.nid IS NULL")),
));
return $output;
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment