2

I have a Drupal 7 database that stores articles since 2013. The database is too big and I want to drop all the old articles to keep only the ones created on 2019, just for development purpose. I read Delete a node after X weeks it was created, which describes what to do on Drupal 8. Is there a similar method for Drupal 7?

2

The previous solutions offered by @berramou and @kiamlaluno♦ should serve you well. On the other hand, if you're looking for a step by step solution, it's the following:

Based on @kiamlaluno♦'s answer, here is the full solution for novices:

  1. Go to your file directory and go to /sites/all/modules. Create a folder here called delete_old_nodes
  2. Create a file in the folder you just created called: "delete_old_nodes.info" and paste this code in it:

    name = Delete old nodes
    description = Deletes nodes older than 30 days.
    package = Custom
    version = 1.0
    core = 7.x
    
  3. Create a file called "delete_old_nodes.module" and paste @kiamlaluno♦'s code into it:

    <?php
    
    function mymodule_cron() {
       $entity_query = new EntityFieldQuery();
       $entity_query->entityCondition('entity_type', 'node')
         ->entityCondition('bundle', 'article')
         ->entityCondition('created', strtotime('1 January 2019'), '<')
         ->addTag('DANGEROUS_ACCESS_CHECK_OPT_OUT')
         ->range(0, 25);
       $result = $entity_query->execute();
       if (isset($result['node'])) {
         node_delete_multiple(array_keys($result['node']));
       }
    }
    
  4. Flush cache, then navigate to modules page, yoursite.com/admin/modules, and enable your module, (by searching for "delete old nodes", click the checkbox by the modules name and click save).

  5. When you want to delete all the nodes up to 1 January 2019, run cron by going to yoursite.com/admin/reports/status/run-cron.

  6. Go back to the modules page, yoursite.com/admin/modules, and disable the module "delete old nodes".

  7. Upvote @kiamlaluno♦'s answer.

  8. Done!

3

The code I would use is similar to the following one.

$entity_query = new EntityFieldQuery();
$entity_query->entityCondition('entity_type', 'node')
  ->entityCondition('bundle', 'article')
  ->entityCondition('created', strtotime('1 January 2019'), '<')
  ->addTag('DANGEROUS_ACCESS_CHECK_OPT_OUT');
$result = $entity_query->execute();
if (isset($result['node'])) {
  node_delete_multiple(array_keys($result['node']));
}

The differences between the code I am using and the code shown in the answers for Delete a node after X weeks it was created are the following:

  • The object used to query the entity is instantiated differently and its class is different
  • The code doesn't select just the published nodes (I take you are interested in deleting all the nodes created before 2019)
  • The code is using addTag('DANGEROUS_ACCESS_CHECK_OPT_OUT') to get all the nodes, even the ones to which the currently logged-in user doesn't have access (Remember that cron tasks are executed as anonymous user, which possibly doesn't have access to many of the nodes)
  • In Drupal 7, the functions to delete nodes are node_delete() and node_delete_multiple() which require, respectively, a node ID and an array of node IDs

If I were to do the task in a hook_cron() implementation, I would use the following code.

  function mymodule_cron() {
    $entity_query = new EntityFieldQuery();
    $entity_query->entityCondition('entity_type', 'node')
      ->entityCondition('bundle', 'article')
      ->entityCondition('created', strtotime('1 January 2019'), '<')
      ->addTag('DANGEROUS_ACCESS_CHECK_OPT_OUT')
      ->range(0, 25);
    $result = $entity_query->execute();
    if (isset($result['node'])) {
      node_delete_multiple(array_keys($result['node']));
    }
  }

Older Drupal 7 versions would need to replace addTag('DANGEROUS_ACCESS_CHECK_OPT_OUT') with addMetaData('account', user_load(1)). For those versions the code would be then similar to the following one.

  function mymodule_cron() {
    $entity_query = new EntityFieldQuery();
    $entity_query->entityCondition('entity_type', 'node')
      ->entityCondition('bundle', 'article')
      ->entityCondition('created', strtotime('1 January 2019'), '<')
      ->addMetaData('account', user_load(1))
      ->range(0, 25);
    $result = $entity_query->execute();
    if (isset($result['node'])) {
      node_delete_multiple(array_keys($result['node']));
    }
  }

Using hook_cron() avoids issues in the case there are many nodes to delete. Trying to load, for example, 3000 nodes (even if the EntityFieldQuery class returns partially loaded nodes) could cause memory or timeout errors.

2

Yes you there is a similar method to do so you can use EntityFieldQuery

Here is a helper function to delete all articles older than two weeks. You can use it as drush command or in cron_hook as it described in the mentioned question.

function delete_older_articles(){
  $query = new EntityFieldQuery();
  $query->entityCondition('entity_type', 'node')
    ->entityCondition('bundle', 'article')
    ->entityCondition('created', strtotime('-2 week'), '<=')
    ->propertyCondition('status', NODE_PUBLISHED);
  $result = $query->execute();
  foreach ($result['node'] as $nid => $node) {
    node_delete($nid);
  }
}
  • how do I run it as a drush command? – Moses Liao GZ Feb 25 '19 at 2:51

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.