2

I have a custom module that outputs some sql reports in a table with a csv button. These are SQL tables that are not accessible via views which is why I had to make this module.

Now when these links are accessible through the frontend (ie do not have 'admin' in the path ) the page and table's contents render just fine.

$items['custom_report/glp_report'] = array(
'title' => 'GLP Report',
'description' => 'Report for Guided Learning Pathways.',
'page callback' => 'op_reports_page',
'access callback' => 'op_reports_permission',
 //'theme callback' => 'op_theme',
'type' => MENU_NORMAL_ITEM,
);

rendered theme that work

When I switch this to an admin path only the table headers render but no content.

$items['admin/custom_report/glp_report'] = array(
'title' => 'GLP Report',
'description' => 'Report for Guided Learning Pathways.',
'page callback' => 'op_reports_page',
'access callback' => 'op_reports_permission',
 //'theme callback' => 'op_theme',
'type' => MENU_NORMAL_ITEM,
);

broken table on admin link

Theme_debug is on and I can see that on the frontend the bootstrap block.tpl serves the table correctly

<!-- BEGIN OUTPUT from 'sites/all/themes/bootstrap/templates/block/block.tpl.php' -->

however on the admin page it loads block/block.tpl

<!-- BEGIN OUTPUT from 'modules/block/block.tpl.php' -->

Hypothesis

Drupal Admin theme is different than the frontend theme. For whatever reason, this new theme uses a different template and that different template can't render my output.

Approach 1 Create custom template for the page

So I wanted to force a custom template hoping that would fix the module override:

Here is the page callback:

function op_reports_page() {
$page = drupal_render(drupal_get_form('op_reports_form', 'glp'));
$page .= op_reports_table('glp');

$page = array
(
'op_reports_page' => array
(
// Note - we will register theme_my_page in the next step
'#theme' => 'glp_reports',
'#contents' => $page,
),
);

return $page;
}

Here is the theme_hook:

function op_reports_theme()
{
  return array
  (
    'glp_reports' => array
    (
      'variables' => array('contents' => array()),
      'template' => 'op_theme', // don't add .tpl.php
    ),
  );
}

Template file:

<h2><?php print t('My Page'); ?></h2>
<div id="my_page_wrapper">
  <?php print render($contents); ?>
</div>
Outcome

While this renders for frontend, on the admin I get a blank content section.

Approach 2 force the theme through the hook_menu

Using the theme callback you can tell Drupal how the page should be rendered

Hook Menu:

  $items['admin/custom_report/glp_report'] = array(
    'title' => 'GLP Report',
    'description' => 'Report for Guided Learning Pathways.',
    'page callback' => 'op_reports_page',
    'access callback' => 'op_reports_permission',
    'theme callback' => 'op_theme', //name of bootstrap extended theme
    'type' => MENU_NORMAL_ITEM,
  );
Outcome

Blank page on admin page

Approach 3 hook_custom_theme

Hook_custom_theme should override any theme with the machine name theme

  function op_reports_custom_theme(){
    return 'op_theme';
  }
Outcome

Blank page on admin page

Ask

So while I appreciate getting stripes on my Drupal white belt, I would really just like to know the best way to make my custom module render output on an admin path.

0

Do not name your access callback op_reports_permission(). The conventional name is op_reports_access(). You accidentally implemented hook_permission(), and I bet you get some warnings when you drush cc all.

I think you have misdiagnosed the problem. If the table headers are rendering, but not the table body, then I think something is going wrong in generating the table. You have not shown us the contents of op_reports_form() nor op_reports_table(), and I suspect that is where the problem is.

I have created a test module for this issue at https://github.com/benjifisher/test-drupal-module. Note that I have tagged two releases: v1.0.0 is the minimal example, and v1.0.1 uses a custom theme function as in your first approach. Feel free to send a pull request!

Standard rules of debugging apply. Make the simplest example you can that reproduces the problem.

These are SQL tables that are not accessible via views which is why I had to make this module.

It may be easier to tell View how to handle these tables by implementing hook_views_data(). A little Google search turns up this blog post. (I cannot vouch for its accuracy, but it looks like what you need.)

0

All I can suggest is to look at page callbacks that already render on administrative pages (like the ones in core). There should be nothing special between a core or third-party module in this respect.

More thoughts:

  • You should not call drupal_render() in a page callback. Return the render array and let core do the rendering
  • No need for 'theme callback' in a menu definition here

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.