8

I have a drupal module with a function that returns an attachment text/plain,

function mymodule_menu() {
$items = array();
$items[MY_PATH] = array(
'title' => 'some page',
'page callback' => 'myfunction',
'type' => MENU_CALLBACK,
);
}

function myfunction()
{
drupal_set_header('Content-Type: text/plain');
return "some text";
}

But it returns the page in the page.tpl.php template, however I want it untemplated, how do I over-ride the theme to make it return plain text?

Thanks,

Tom

xpereta
  • 692
  • 9
  • 21
Tom
  • 131
  • 2
  • 3

5 Answers5

9

This will return plain text

function myfunction() {
  drupal_set_header('Content-Type: text/plain');
  print "some text";
  exit(0);
}
Jeremy French
  • 11,707
  • 6
  • 46
  • 71
  • 1
    +1 - This is the way Drupal itself returns 'unthemed' content, e.g. answers to js callbacks or files (when private files are enabled). See the http://api.drupal.org/api/function/file_transfer/6 for an example of this in core. – Henrik Opel Feb 19 '10 at 08:18
  • 1
    A word of warning applies: When ending the normal Drupal request processing via exit()/die(), *hook_exit will not be invoked*, so make sure not to rely on that in these cases. – Henrik Opel Feb 19 '10 at 08:20
  • 2
    Instead of exit; generally drupal_exit(); should be used in Drupal 7: https://api.drupal.org/api/drupal/includes%21common.inc/function/drupal_exit/7 This invokes hook_exit() and more. – Phizes Jul 07 '14 at 12:16
  • This question is about Drupal 6 but, this answer would apply to Drupal 7 too if we use drupal_add_header https://api.drupal.org/api/drupal/includes!bootstrap.inc/function/drupal_add_http_header/7 instead of drupal_set_header – xpereta Mar 04 '15 at 17:21
7

Alternatively you can use the 'delivery callback' setting in your menu callback definition. Now your page callback function will be run through a custom function that just prints and exits, rather than calling drupal_deliver_html_page(), which is what outputs all the typical theme markup, etc.

function mymodule_menu() {
  $items = array();
  $items['MY_PATH'] = array(
    'title' => 'some page',
    'page callback' => 'myfunction',
    'type' => MENU_CALLBACK,
    'delivery callback' => 'mymodule_deliver_page',
  );
  return $items;
}

function mymodule_deliver_page($page_callback_result) {
  print $page_callback_result;
  exit(0);
}
chromix
  • 71
  • 1
  • 1
  • I think the 'delivery callback' is the best way to handle this in drupal 7, but instead of exit; generally drupal_exit(); should be used in Drupal 7: https://api.drupal.org/api/drupal/includes%21common.inc/function/drupal_exit/7 This invokes hook_exit() and more. – Phizes Jul 07 '14 at 12:17
2

The best and simplest solution is to just have your callback print your html and return nothing.

For example,

// Hooks menu to insert new url for drupal
function MYMODULE_menu() {
  $items = array();
  $items['member-stats.php'] = array(
    'page callback' => '_MYMODULE_menu_callback',
    'access callback' => TRUE,
  );
  return $items;
}

// Callback prints and doesn't return anything
function _MYMODULE_menu_callback() {
  print "Hello, world";
}
bdombro
  • 1,251
  • 11
  • 17
1

if you'd create a template like html--barebones.tpl.php, containing just

<?php
    drupal_set_header('Content-Type: text/plain');
    print $barebones;
?>

you could hook that template to YOURTHEME_preprocess_html(), like so:

function YOURTHEME_preprocess_html(&$variables) {
    if (array_key_exists('barebones',$_REQUEST)) {
        $variables['barebones'] = $variables['page']['foo']['bar'];
        $variables['theme_hook_suggestions'][] = 'html__barebones';
    }
}

now, if you call your page with the additional query ?barebones, like drupal/foo/bar?barebones, it will return the barebones version.

theres a tricky bit in getting your result back. var_dump($variables['page']) to see where drupal left your text. Its been tucked inside the render array surrounded by all kind of info used to render the text, which you are not using. Making me wonder if it wouldnt be more efficient to just print it and exit() inside myfunction :-)

commonpike
  • 10,499
  • 4
  • 65
  • 58
0

Your module can define template files (reference):

<?php
function mymodul_preprocess_page(&$variables) {
     foreach ($variables['template_files'] as $file) {
     $template_files[] = $file;
     if ($file == 'page-node') {
        $template_files[] = 'page-'. $variables['node']->type;  
     }
    }
   $variables['template_files'] = $template_files;
}
?>

By creating a new .tpl.php file for the page in question. E.g.

page-module.tpl.php

page-module.tpl.php would only need to be a simple page, e.g.

<?php
print $content;
?>
wiifm
  • 3,787
  • 1
  • 21
  • 23
  • Hi, thanks! The text file is not a content type, its a report generated from php/database so I'm am not sure I get what you mean. However I have just realised, that if I do print "whateever"; and not return "whatever"; drupal doesn't display the page template. I would still be interested to know how you would get drupal to apply the page-plain.tpl.php template to arbitrary content... – Tom Feb 18 '10 at 03:09