Access levels - Showing different content per user role with view modes

This solution is useful If you want to have something like standard and premium users and show different content for each role. What we mean here is to show just part of the node for normal user and full node for premium users. So how do we do this? We build 2 different view modes for that node type. In one we show lets say just title and body and in other we show title, body, images, links, telephone numbers, contact etc.

After we do that we need to add some code, we need to create custom module and in my_module.module file add code that will make a switch of view mode depending on which user role is present at that particular user.

<?php

function my_module_entity_view_mode_alter(&$view_mode, Drupal\Core\Entity\EntityInterface $entity, $context) {

  if ($entity->getEntityTypeId() == 'node' && $entity->bundle() == 'news' && $view_mode == 'full') {
    $current_user = \Drupal::currentUser();
    $roles = $current_user->getRoles();
    if (!in_array("premium", $roles)) {
      $view_mode = 'trail';
    }
  }
}

So we need to use a hook here "_entity_view_mode_alter" so we can alter the view mode for those type of users, caching should play fine along with this as it adds tags per user role, so all drupal caching mechanisms should work out of the box.

We check for entity type and bundle, we check what is current (default) view mode which is "full" and then we check user role array and does it have our "premium" type in it, if not we serve them "trial" view mode which will show just some fields, not all.

This also works with views if you use "view mode" for displaying content and for search module if you add one more view mode to first IF statement so it goes like

  if ($entity->getEntityTypeId() == 'node' && $entity->bundle() == 'novi_tip' && ($view_mode == 'full' || $view_mode == 'search_result')) {