Dynamic Entity Query Based on Moderation State

By mandclu, Fri, 06/30/2023 - 13:43

As part of my ongoing work on the Event Platform modules for organizing DrupalCamps and similar events, I wanted to add to the recently introduced Scheduler interface, by allowing a site builder to specify a list of workflow (content moderation) states that would be used to restrict which sessions (or other content types) to list. After, it wouldn't make sense to ask an editor to have to pick through the rejected sessions as part of the scheduling interface.

In looking for solutions to filter on content moderation state, the existing solution I was able to find adds a tag to the query:

/** @var \Drupal\node\NodeStorage $storage */
$storage = \Drupal::entityTypeManager()->getStorage('node');
$query = $storage->getQuery()
  ->condition('type', $content_types, 'IN');
$result = $query->execute();

And then, in the module file, it implements a hook to alter the query using a hard-coded definition of what state(s) to check for:

 * Implements hook_query_TAG_alter().
function event_platform_scheduler_query_moderation_state_alter(Drupal\Core\Database\Query\AlterableInterface $query) {
  $query->addJoin('LEFT', 'content_moderation_state_field_data', 'md', 'md.content_entity_revision_id = base_table.vid');
  $query->condition('md.moderation_state', 'archived', '<>');

My challenge was that I wanted the list of moderation states to be configurable, so a site builder could customize in which states content would be listed in the scheduler, particularly since they can also customize which content types are available, and they may not all use the same workflow, or content moderation at all.

It turns out, there's a relatively simple fix — add the desired moderation states to the query's metadata:

$query = $storage->getQuery()
  ->condition('type', $content_types, 'IN')
  ->addMetaData('states', $moderation_states);

Then, in the hook implementation, load these to be used in the condition:

function event_platform_scheduler_query_moderation_state_alter(AlterableInterface $query) {
  $states = $query->getMetaData('states') ?? [];
  if ($states) {
    $query->addJoin('LEFT', 'content_moderation_state_field_data', 'md', 'md.content_entity_revision_id = base_table.vid');
    $query->condition('md.moderation_state', $states, 'IN');




Restricted HTML

  • Allowed HTML tags: <a href hreflang> <em> <strong> <cite> <blockquote cite> <code> <ul type> <ol start type> <li> <dl> <dt> <dd> <h2 id> <h3 id> <h4 id> <h5 id> <h6 id>
  • Lines and paragraphs break automatically.
  • Web page addresses and email addresses turn into links automatically.