1

I'm working on a module. I've added a tab to each Content Type in hook_menu using something like:

$items['admin/structure/types/manage/%/stuff'] = array(
    'title' => 'Manage stuff',
    'page callback' => 'drupal_get_form',
    'page arguments' => array('stuff_content_type_stuff_form', 4),
    'access arguments' => array('administer content types'),
    'type' => MENU_LOCAL_TASK,
    'weight' => 100
);

The tab appears fine when I visit admin/structure/types/manage/article/edit, for example. However, when I view admin/structure/types to view the list of content types, I'd like to see "Manage stuff" listed as a link in the "operations" column alongside "Manage fields" and "Manage display".

Is this possible? Can someone please provide a way to do this?

1

The admin/structure/types page is created via the hook_menu() in the node module:

$items['admin/structure/types'] = array(
  'title' => 'Content types',
  'description' => 'Manage content types, including default status, front page promotion, comment settings, etc.',
  'page callback' => 'node_overview_types',
  'access arguments' => array('administer content types'),
  'file' => 'content_types.inc',
);

which shows that the page is generated by the node_overview_types function in content_types.inc:

/**
 * Displays the content type admin overview page.
 */
function node_overview_types() {
  $types = node_type_get_types();
  $names = node_type_get_names();
  $field_ui = module_exists('field_ui');
  $header = array(t('Name'), array('data' => t('Operations'), 'colspan' => $field_ui ? '4' : '2'));
  $rows = array();

  foreach ($names as $key => $name) {
    $type = $types[$key];
    if (node_hook($type->type, 'form')) {
      $type_url_str = str_replace('_', '-', $type->type);
      $row = array(theme('node_admin_overview', array('name' => $name, 'type' => $type)));
      // Set the edit column.
      $row[] = array('data' => l(t('edit'), 'admin/structure/types/manage/' . $type_url_str));

      if ($field_ui) {
        // Manage fields.
        $row[] = array('data' => l(t('manage fields'), 'admin/structure/types/manage/' . $type_url_str . '/fields'));

        // Display fields.
        $row[] = array('data' => l(t('manage display'), 'admin/structure/types/manage/' . $type_url_str . '/display'));
      }

      // Set the delete column.
      if ($type->custom) {
        $row[] = array('data' => l(t('delete'), 'admin/structure/types/manage/' . $type_url_str . '/delete'));
      }
      else {
        $row[] = array('data' => '');
      }

      $rows[] = $row;
    }
  }

  $build['node_table'] = array(
    '#theme' => 'table',
    '#header' => $header,
    '#rows' => $rows,
    '#empty' => t('No content types available. <a href="@link">Add content type</a>.', array('@link' => url('admin/structure/types/add'))),
  );

  return $build;
}

So, one way I can see to do this would be to in your module, do a hook_menu_alter() and point the page callback to a function in your module and just add to the core one's functionality, eg, something like this:

function YOURMODULE_menu_alter(&$items) {

  $items['admin/structure/types']['page callback']='YOURMODULE_node_overview_types';
  unset($items['admin/structure/types']['file']); // or point it to YOURMODULE_pages.inc if need be

}

and then basically just copy the code from node_overview_types() into YOURMODULE_node_overview_types() and then put in your functionality, eg, change the colspan to 5 or 3 and add in the l() to your menu item.

NOTE: Of course, if the node module is ever updated you'll have to keep that in mind and possibly redo this. So, yes, since a render array is returned, you could instead modify this in any number of hook alters before the page is rendered. If you want to look into this approach, Render Arrays in Drupal 7 is a good place to start.

ADDITION:

For completeness, this is one way you could use a hook_page_alter():

function YOURMODULE_page_alter(&$page) {

  if ($_GET['q']=='admin/structure/types') {

    $types = array_keys(node_type_get_types());

    $page['content']['system_main']['node_table']['#header'][1]['colspan']++;
    foreach($page['content']['system_main']['node_table']['#rows'] as $type => &$row) {
      $row[]='New menu link goes here for ' . $types[$type];
    }

  }

}

instead of the hook_menu_alter() approach above. But also, obviously, it too relies on the structure of the array returned by the node module.

  • Thanks. I ended up using a hybrid of your two suggestions after seeing just the first. I implemented hook_menu_alter, and replaced the page callback, but rather than re-implementing, I passed the original callback as a parameter to mine. From my callback, I called the original callback (node_overview_types()), modified the results (as you do in hook_page_alter), then returned that. – George Jan 24 '14 at 19:43
1

Yes, it is possible, I have a suggestion for you

dont forget clear cache after apply this,

function yourmodule_menu_alter(&$items) {

      $items['admin/structure/types']['page callback']='yourmodule_node_overview_types',
    }


function yourmodule_node_overview_types() {
  $types = node_type_get_types();
  $names = node_type_get_names();
  $field_ui = module_exists('field_ui');
  $header = array(t('Name'), array('data' => t('Operations'), 'colspan' => $field_ui ? '4' : '2'));
  $rows = array();

  foreach ($names as $key => $name) {
    $type = $types[$key];
    if (node_hook($type->type, 'form')) {
      $type_url_str = str_replace('_', '-', $type->type);
      $row = array(theme('node_admin_overview', array('name' => $name, 'type' => $type)));
      // Set the edit column.
      $row[] = array('data' => l(t('edit'), 'admin/structure/types/manage/' . $type_url_str));
      $row[] = array('data' => l(t('Manage stuff'), 'admin/structure/types/manage/%/stuff' . $type_url_str));

      if ($field_ui) {
        // Manage fields.
        $row[] = array('data' => l(t('manage fields'), 'admin/structure/types/manage/' . $type_url_str . '/fields'));

        // Display fields.
        $row[] = array('data' => l(t('manage display'), 'admin/structure/types/manage/' . $type_url_str . '/display'));
      }

      // Set the delete column.
      if ($type->custom) {
        $row[] = array('data' => l(t('delete'), 'admin/structure/types/manage/' . $type_url_str . '/delete'));
      }
      else {
        $row[] = array('data' => '');
      }

      $rows[] = $row;
    }
  }

  $build['node_table'] = array(
    '#theme' => 'table',
    '#header' => $header,
    '#rows' => $rows,
    '#empty' => t('No content types available. <a href="@link">Add content type</a>.', array('@link' => url('admin/structure/types/add'))),
  );

  return $build;
}

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

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