0

I am creating a drupal module and here in the module file i created a check on hook_toolbar() function that if there are credentials in the database it will show 4 links in dropdown otherwise it will show only 2 links. Initially with no credentials it shows 2 links but whenever i get credentials and update them in the database i have to clear cache in order to update the tray in the hook_toolbar() in order to show 4 links.

function try_toolbar() {
    $items = [];
    \Drupal::service('page_cache_kill_switch')->trigger();
    $items['TRY'] = [
        '#cache' => [
            'contexts' => ['user.permissions'],
        ],
    ];

    if (!\Drupal::currentUser()->hasPermission('Access the Commande overview page')) {
        return $items;
    }

    $credentials = db_select('config', 'n')
        ->fields('n')
        ->condition('collection', 'TRY','=')
        ->execute()
        ->fetchAssoc();
    $opValue = $credentials['data'];
    
    if($credentials) {
        $items['TRY'] += [
            '#type' => 'toolbar_item',
            '#weight' => 1,
            'tab' => [
                '#type' => 'link',
                '#title' => 'TRY',
                '#url' => \Drupal\Core\Url::fromUri("internal:/admin/try"),
                '#attributes' => [
                    'title' => 'try menu',
                    'class' => ['toolbar-icon', 'toolbar-icon-try'],
                ],
            ],
            'tray' => [
    
                'configuration' => [
                    '#type' => 'link',
                    '#title' => 'Dashboard',
                    '#url' => \Drupal\Core\Url::fromUri("internal:/admin/try_dashboard"),
    
                ],[
                    '#type' => 'link',
                    '#title' => 'Notifications',
                    '#url' => \Drupal\Core\Url::fromUri("internal:/admin/try_notifications"),
                ],[
                    '#type' => 'link',
                    '#title' => 'Settings',
                    '#url' => \Drupal\Core\Url::fromUri("internal:/admin/try_settings"),
                ],[
                    '#type' => 'link',
                    '#title' => 'Help',
                    '#url' => \Drupal\Core\Url::fromUri("internal:/admin/try_help"),
                ],
    
            ],
            '#attached' => array(
                'library' => array(
                    'try/admin',
                ),
            ),
    
        ];
        return $items;

    } else {
        $items['TRY'] += [
            '#type' => 'toolbar_item',
            '#weight' => 1,
            'tab' => [
                '#type' => 'link',
                '#title' => 'TRY',
                '#url' => \Drupal\Core\Url::fromUri("internal:/admin/try"),
                '#attributes' => [
                    'title' => 'try menu',
                    'class' => ['toolbar-icon', 'toolbar-icon-try'],
                ],
            ],

            'tray' => [
    
                'configuration' => [
                    '#type' => 'link',
                    '#title' => 'On Board',
                    '#url' => \Drupal\Core\Url::fromUri("internal:/admin/onBoard"),
    
                ],[
                    '#type' => 'link',
                    '#title' => 'Verify Credentials',
                    '#url' => \Drupal\Core\Url::fromUri("internal:/admin/try_settings/verifyCredentials"), 
                ]
    
            ],
            '#attached' => array(
                'library' => array(
                    'try/admin',
                ),
            ),
    
        ];
        return $items;
    }
}

Here i used the following code to disable the cache

\Drupal::service('page_cache_kill_switch')->trigger();

But it is not working thus forcing me to manually clear the cache.

Please tell me a way to bust the cache depending on that database result.

2
  • 3
    You set a max-age if 0, but this is subject to limitations. drupal.org/docs/drupal-apis/cache-api/cache-max-age You would do much better by creating a cache context for the credentials existence, then varying the render array cache by that context instead of resorting to max-age.
    – mona lisa
    Commented Nov 16, 2022 at 13:11
  • can you tell me where do i have to add max-age = 0. @cilefen Commented Nov 18, 2022 at 6:38

1 Answer 1

3

Setting max-age to zero, as well as using the killswitch you have in your code \Drupal::service('page_cache_kill_switch')->trigger();, are both sledgehammer solutions to a problem that Drupal is built to handle with finesse. Rather than rebuilding the menu on every page load, a cache tag is added to the render array. Then when the DB credentials for that user are cleared, that cache tag is invalidated. The next time it is requested by a user who matches the invalidated cache tage, it will be rebuilt and re-cached.

You can add a cache tag to your existing cache declaration on the render array as follows:

'#cache' => [
  'contexts' => ['user.permissions'],
  // Might be 'tag' not 'tags'. I can't remember which.
  // Tag is in the format [IDENTIFIER]:[USERID].
  'tags' => 'example_credentials:' . \Drupal::currentUser()->id(),
],

Then, when the toolbar should be rebuilt, which in your case is when the user submits their new credentials to be saved, you invalidate that cache tag:

Drupal\Core\Cache\Cache::invalidateTags()

If your menu isn't user specific, but rather role specific, permission specific, or some other metric, change the references to current user ID to some other identifier that for that role, or that permission, or whatever suits your needs. If no specificity is required at all - IE the menu items should be built for all users (to whom the cache context applies), you can remove the specific identifier altogether, and just use [IDENTIFIER], which in the above example is example_credentials.

2
  • I am not getting that where do i have to make changes in my code. Can you please guide through my code. Commented Nov 18, 2022 at 6:58
  • I only gave you the one change. You just add the tags key to your #cache render array. For the other part, it depends on how the credentials are saved to the DB - it's probably a form, so you probably want to invalidate the tags in the submit handler for that form.
    – Jaypan
    Commented Nov 18, 2022 at 14:51

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

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