Skip to content
Snippets Groups Projects
Commit 35191fc2 authored by Pascal Morin's avatar Pascal Morin
Browse files

Initial D8 port

parent cceebad6
No related branches found
No related tags found
No related merge requests found
cron: false
chunk: 500
node_access_rebuild_progressive.settings:
type: mapping
label: Settings
mapping:
cron:
type: boolean
chunk:
type: integer
\ No newline at end of file
<?php
/**
* Implements of hook_drush_command().
*/
function node_access_rebuild_progressive_drush_command() {
$items['node-access-rebuild-progressive'] = array(
'description' => "Fully rebuild node access.",
'callback' => 'drush_node_access_rebuild_progressive_rebuild',
);
return $items;
}
/**
* Rebuilds the node access grants table.
*/
function drush_node_access_rebuild_progressive_rebuild() {
node_access_rebuild_progressive_trigger();
$batch_def = array(
'title' => t('Node access rebuild'),
'operations' => array(
array('node_access_rebuild_progressive_process_drush', array()),
),
'file' => 'node_access_rebuild_progressive.drush.inc',
'finished' => 'node_access_rebuild_progressive_finished',
);
batch_set($batch_def);
$batch = & batch_get();
$batch['progressive'] = FALSE;
drush_backend_batch_process();
}
function node_access_rebuild_progressive_process_drush(&$context) {
if (!isset($context['sandbox']['total'])) {
$context['sandbox']['total'] = 0;
$context['sandbox']['processed'] = 0;
$context['sandbox']['nodes'] = db_query("SELECT count(nid) FROM {node}")->fetchField();
}
$pass = node_access_rebuild_progressive_process_chunk();
$context['sandbox']['total'] += $pass['total'];
$context['sandbox']['processed'] += $pass['processed'];
$numbers = array(
'@processed' => $pass['total'],
'@total' => $pass['processed'],
'@grand_processed' => $context['sandbox']['processed'],
'@grand_total' => $context['sandbox']['total'],
'@nodes' => $context['sandbox']['nodes'],
);
$context['finished'] = empty($pass['total']) ? 1 : 0;
if (!$context['finished']) {
drush_print(dt('Processed @processed of @total nodes - Total: @grand_processed/@grand_total (@nodes)', $numbers));
}
}
name: 'Node Access Rebuild Progressive'
description: 'Rebuild node access grants in chunks'
core: 8.x
type: module
<?php
/**
* @file
* Provides ability to rebuild node access silently.
*/
/**
* Implements hook_cron().
*/
function node_access_rebuild_progressive_cron() {
$config = \Drupal::config('node_access_rebuild_progressive.settings');
// Not enabled on cron, nothing to do.
if (!$config->get('cron')) {
return;
}
// Trigger the processing.
if (node_access_needs_rebuild()) {
node_access_rebuild_progressive_trigger();
}
// Process a batch of nodes if needed.
if (\Drupal::state()->get('node_access_rebuild_progressive.current') > 0) {
node_access_rebuild_progressive_process_cron();
}
}
/**
* Initiate the full rebuild.
*/
function node_access_rebuild_progressive_trigger() {
// Prevents default message/behaviour.
node_access_needs_rebuild(FALSE);
// Add default grants in the unlikely case
// no modules implement node_grants anymore.
if (!count(\Drupal::moduleHandler()->getImplementations('node_grants'))) {
node_access_rebuild_progressive_set_default();
return node_access_rebuild_progressive_finished();
}
// Clean up possible mismatches.
db_query("DELETE FROM {node_access} WHERE nid NOT IN (SELECT nid FROM {node})");
// We only need the current one, nodes created afterward would get processed
// at save time.
$highest = db_query("SELECT nid FROM {node} ORDER BY nid DESC LIMIT 0,1")->fetchField();
$count = db_query("SELECT count(nid) FROM {node}")->fetchField();
\Drupal::state()->set('node_access_rebuild_progressive.current', $highest + 1);
\Drupal::logger('node_access_rebuild_progressive')->notice('%count nodes queued for node access rebuild.', array('%count' => $count));
}
function node_access_rebuild_progressive_set_default() {
$access_control_handler = \Drupal::entityManager()->getAccessControlHandler('node');
$access_control_handler->deleteGrants();
$access_control_handler->writeDefaultGrant();
}
/**
* Processes a chunk of nodes at cron run.
*/
function node_access_rebuild_progressive_process_cron() {
$pass = node_access_rebuild_progressive_process_chunk();
if (empty($pass['total'])) {
return node_access_rebuild_progressive_finished();
}
}
/**
* Processes a chunk of nodes.
* @return array
* An array with the following keys:
* - total: the number of nodes retrieved for processing.
* - processed: the number of nodes actually processed.
*/
function node_access_rebuild_progressive_process_chunk() {
$current = \Drupal::state()->get('node_access_rebuild_progressive.current');
$chunk_size = \Drupal::config('node_access_rebuild_progressive.settings')->get('chunk');
$nids = db_query("SELECT nid FROM {node} WHERE nid < :current ORDER BY nid DESC LIMIT 0,$chunk_size", array(':current' => $current))->fetchCol();
$total = count($nids);
$processed = 0;
if ($total) {
$access_control_handler = \Drupal::entityManager()->getAccessControlHandler('node');
$node_storage = \Drupal::entityManager()->getStorage('node');
$node_storage->resetCache($nids);
$nodes = $node_storage->loadMultiple($nids);
foreach ($nodes as $node) {
// Make sure the node can be loaded properly.
if (!empty($node->id())) {
$grants = $access_control_handler->acquireGrants($node);
\Drupal::service('node.grant_storage')->write($node, $grants);
$current = $node->id();
$processed ++;
}
}
\Drupal::state()->set('node_access_rebuild_progressive.current', $current);
}
return array(
'total' => $total,
'processed' => $processed,
);
}
/**
* Cleanup after queue completion.
*/
function node_access_rebuild_progressive_finished() {
\Drupal::state()->set('node_access_rebuild_progressive.current', 0);
\Drupal::logger('node_access_rebuild_progressive')->notice('Node access rebuild finished.', []);
}
node_access_rebuild_progressive.settings:
path: 'admin/config/development/node-access-rebuild-progressive'
defaults:
_form: '\Drupal\node_access_rebuild_progressive\Form\NodeAccessRebuildProgressiveSettingsForm'
_title: 'Node access rebuild'
requirements:
_permission: 'administer site configuration'
<?php
namespace Drupal\node_access_rebuild_progressive\Form;
use Drupal\Core\Form\ConfigFormBase;
use Drupal\Core\Form\FormStateInterface;
/**
* Configure settings for our module.
*/
class NodeAccessRebuildProgressiveSettingsForm extends ConfigFormBase {
/**
* {@inheritdoc}
*/
public function getFormId() {
return 'node_access_rebuild_progressive_admin';
}
/**
* {@inheritdoc}
*/
protected function getEditableConfigNames() {
return [
'node_access_rebuild_progressive.settings',
];
}
/**
* {@inheritdoc}
*/
public function buildForm(array $form, FormStateInterface $form_state) {
$config = $this->config('node_access_rebuild_progressive.settings');
$form['cron'] = array(
'#type' => 'checkbox',
'#title' => $this->t('Enable progressive node access rebuild at cron time'),
'#description' => $this->t('It is recommended that you run cron via drush for using this feature.'),
'#default_value' => $config->get('cron'),
);
$form['chunk'] = array(
'#type' => 'textfield',
'#title' => $this->t('Number of nodes to process in each chunk'),
'#default_value' => $config->get('chunk'),
'#description' => $this->t('The number of nodes that will be processed per cron run. Make sure it can safely fit in memory, and in the cron run time if you are not running cron via drush.'),
);
return parent::buildForm($form, $form_state);
}
/**
* {@inheritdoc}
*/
public function validateForm(array &$form, FormStateInterface $form_state) {
$chunk_size = $form_state->getValue('chunk');
if (!is_numeric($chunk_size) || $chunk_size <= 0) {
$form_state->setErrorByName('chunk', $this->t('Chunk size must be a positive integer.'));
}
}
/**
* {@inheritdoc}
*/
public function submitForm(array &$form, FormStateInterface $form_state) {
\Drupal::configFactory()->getEditable('node_access_rebuild_progressive.settings')
->set('chunk', $form_state->getValue('chunk'))
->set('cron', $form_state->getValue('cron'))
->save();
parent::submitForm($form, $form_state);
}
}
0% Loading or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment