Unpublish nodes programmatically

Tutorial Goal

Lesson Goal:

Implementation Method

D7

D8

hook_cron + node_save

hook_cron + Node::save()

D7 Code

First, implement a custom function that loads the set of nodes you’d like to unpublish.  The following example will load all nodes that are more than 30 days old:

function lotus_load_old_nodes() {
  $query = new EntityFieldQuery();
  $query->entityCondition('entity_type', 'node')
    ->propertyCondition('created', strtotime('-30 days'), '<');
  $result = $query->execute();
  if (!$result) {
    // Query failed. @todo implement error handling as needed
    return array();
  }
  return node_load_multiple(array_keys($result['node']));
}

Next, in an implementation of hook_cron(), call the above function and operate on the returned nodes to unpublish them as follows:

function lotus_cron() {
  $old_nodes = lotus_load_old_nodes();
  foreach ($old_nodes as $node) {
    $node->status = NODE_NOT_PUBLISHED;
    node_save($node);
  }
}

Both of these functions should be implemented in lotus.module.  Once this is complete and the Lotus module is enabled, every cron run will result in the targeted nodes being unpublished.

Both of these functions should be implemented in lotus.module.  Once this is complete and the Lotus module is enabled, every cron run will result in the targeted nodes being unpublished.

D8 Code

The strategy in D8 is similar to D7, but the specifics of the code are a bit different. Drupal 8 introduces the concept of Service classes, which capture application-wide behaviors (database access, sending emails, translating text, etc.) in PHP classes instead of global functions.  Our lookup function is a good candidate for this kind of implementation.

First, implement the service class as follows, in lotus/src/OldNodesService.php:

namespace Drupal\lotus;

use Drupal\Core\Entity\EntityTypeManager;

class OldNodesService {

  protected $entityTypeManager;

  public function __construct(EntityTypeManager $entity_type_manager) {
    $this->entityTypeManager = $entity_type_manager;
  }

  public function load() {
    $storage = $this->entityTypeManager->getStorage('node');
    $query = $storage->getQuery()
      ->condition('created', strtotime('-30 days'), '<');
    $nids = $query->execute();
    return $storage->loadMultiple($nids);
  }

}

Then, register your service and describe its dependencies (in this case, an instance of the EntityTypeManager service) in lotus/lotus.services.yml:

services:
  lotus.old_nodes:
    class: \Drupal\lotus\OldNodesService
    arguments: ["@entity_type.manager"]

Finally, implement hook_cron() much as in D7:  

function lotus_cron() {
  $old_nodes = \Drupal::service('lotus.old_nodes')->load();
  foreach ($old_nodes as $node) {
    $node->setPublished(false);
    $node->save();
  }
}

Gist Link

lotus.module: https://gist.github.com/jazzslider/e7f2d72ae32b959e245c27fe66016393

Contact supportStill need assistance? Contact Acquia Support