2

I have a page that is only accessible by some people. It's entry in hook_menu contains following:

$items['mymodule/mypage'] = array(
  'title' => 'Edit Product',
  'page callback' => 'mymodule_mypage',
  'access arguments' => array('view mypage'),
  'file' => 'pages/mypage.inc',
);

It works all right, it shows page when it should and throws 403 when needed. Now I need a link to it on some other page. Usually I would just use:

<div class="links">
  <?php echo l('My Page', 'mymodule/mypage'); ?>
</div>

in tpl.php file where I need it. But I don't want it to be visible for people who will get 403 if they will click it. l() does not test for permissions on it's own. And I feel reluctant about using logic in templates like this:

<?php if ( user_access('view mypage') ) : ?>
  <div class="links">
    <?php echo l('My Page', 'mymodule/mypage'); ?>
  </div>
<?php endif; ?>

I always believed than if's in templates are only to provide things like odd/even, marking visible tabs and deciding if markup should be outputted, like if(!empty($header)).

On the other hand, building this in the module and passing to the template seems like an overkill for such a simple task.

So what is the "canonical", cache-safe way to achieve this?

Additional information about what this link really is in this case:

Link is related to the page it is presented on, so block does not make sense.

Leaving it to the user to add link to the menu, so that menu system will take care about permissions, is not applicable, as it violates the "if something have to be done during install, always the same way, and requires no user input of any kind, don't leave it to the user" rule. If there is a way to automatically place it in menu in a way similar to node/%/edit links shown on node/% pages, all right. I'll be happy to accept that as an answer. But my question is general, without assumption that links share front part. In my exact case, they actually do not.

3
  • I know it's a pretty basic question, but I just realized I was using like 3 different approaches over time and never stopped to think which one is really the good and proper one, the mystical "Drupal way" of doing it.
    – Mołot
    May 13, 2014 at 15:10
  • Some would argue that calling l() or user_access() anywhere in a theme violates the separation of business logic versus presentation (or theming), and that your module should either define a block that can be placed somewhere or the end-user should put the link in a menu, which will then take care of the access check.
    – mpdonadio
    May 13, 2014 at 15:42
  • @MPD addressed what you said in an edit to my question.
    – Mołot
    May 13, 2014 at 21:34

1 Answer 1

2

You can check the access for any url-path in your module using menu_get_item():

$menu_item = menu_get_item('mymodule/mypage');
$access = $menu_item['access'];
if ($access) {
    $mylink = l('My Page', 'mymodule/mypage');
} else {
    $mylink = '';
}

Put this code e.g. in some preprocess function in your module, change $mylink variable to sg that is available in your .tpl.php, so you only need to print this variable in your tpl.php.

Your Answer

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

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