Search code examples
drupalmenudrupal-7hook

Drupal 7 - How to retrieve Object/ID and use inside Hook Menu?


I'm using the Entity Registration Module and added a "Cancel" tab inside

function registration_menu() ...

$items['registration/%registration/view'] = array(
    'title' => 'View',
    'page callback' => 'registration_view',
    'page arguments' => array(1),
    'access callback' => 'entity_access',
    'access arguments' => array('view', 'registration', 1),
    'type' => MENU_DEFAULT_LOCAL_TASK,
  );

$items['registration/%registration/cancel'] = array(
'title' => 'Cancel',
'page callback' => 'registration_view_cancel',
'page arguments' => array(1),
'access callback' => 'entity_access',
'access arguments' => array('view', 'registration', 1),
'type' => MENU_LOCAL_TASK,
);

which I want to hide based on the Registration State by placing that tab inside an if condition.

I couldn't figure out how to load the current "registration" object (ID is only in the URL) to read the state. I take this works different than for node types, as this is an entity type "registration".

How best can I load that object to extract the "state" value? See devel output below

.. (Object) Registration
entityType:protected (String, 12 characters ) registration
entityInfo:protected (Array, 25 elements)
idKey:protected (String, 15 characters ) registration_id
nameKey:protected (String, 15 characters ) registration_id
statusKey:protected (String, 6 characters ) status
defaultLabel:protected (Boolean) FALSE
registration_id (String, 3 characters ) 633
type (String, 9 characters ) classroom
entity_id (String, 4 characters ) 1426
entity_type (String, 4 characters ) node
anon_mail (NULL)
user_uid (String, 4 characters ) 1772
count (String, 1 characters ) 1
author_uid (String, 4 characters ) 1772
state (String, 8 characters ) complete
created (String, 10 characters ) 1591628269
updated (String, 10 characters ) 1591628269

UPDATE dpm($items);

admin/structure/registration (Array, 6 elements)
registration/%registration (Array, 6 elements)
test/registration2/%registration (Array, 6 elements)
test/registration2/%registration/view (Array, 6 elements)
registration/%registration/view (Array, 6 elements)
registration/%registration/edit (Array, 7 elements)
registration/%registration/delete (Array, 6 elements)
node/%entity_object/register (Array, 7 elements)
node/%entity_object/registrations (Array, 7 elements)
node/%entity_object/registrations/list (Array, 7 elements)
node/%entity_object/registrations/settings (Array, 8 elements)
node/%entity_object/registrations/broadcast (Array, 8 elements)
registration/%registration/devel (Array, 8 elements)
registration/%registration/devel/load (Array, 2 elements)

and the registration object (the page i'm on)

registration/%registration (Array, 6 elements)
title callback (String, 23 characters ) registration_page_title | (Callback) registration_page_title();
title arguments (Array, 1 element)
0 (Integer) 1
page callback (String, 17 characters ) registration_view | (Callback) registration_view();
page arguments (Array, 1 element)
0 (Integer) 1
access callback (String, 13 characters ) entity_access | (Callback) entity_access();
access arguments (Array, 3 elements)
0 (String, 4 characters ) view
1 (String, 12 characters ) registration
2 (Integer) 1

Solution

  • menu_alter will modify the menu based on the criteria set in the registration_cancel_visibility access callback. In this case, if the callback finds "complete" in $registration->state, it will return TRUE and the Cancel button will show, otherwise, it will remain hidden.

    There is no need to add $items['registration/%registration/cancel'] under the registration_menu.

    You'll likely want to change the page callback to direct the user to a cancel page/form.

    Add this to your registration.module:

    /**
    * Implements hook_menu_alter.
    */
    function registration_menu_alter(&$items) {
        $items['registration/%registration/cancel'] = array(
            'title' => 'Cancel',
            'page callback' => 'drupal_get_form',
            'page arguments' => array('registration_form', 1),
            // access callback to a function to check if the menu item should be visible
            'access callback' => 'registration_cancel_visibility',
            'access arguments' => array('update', 1),
            'weight' => 10,
            'type' => MENU_LOCAL_TASK,
        );
    }
    
    /**
    *
    * Check state of registration and apply visibility of cancel functionality accordingly
    */
    function registration_cancel_visibility($action, $registration) {
        // ternary operator to return TRUE or FALSE based on the value of $registration->state
        return $registration->state === "complete" ? TRUE : FALSE;
    }