Trying to hook into Drupal 7 from an external php file by using various variants of ...

function getDrupalHTML() {
    define('DRUPAL_ROOT', getcwd());
    require_once DRUPAL_ROOT . '/includes/bootstrap.inc';
    drupal_bootstrap(DRUPAL_BOOTSTRAP_FULL);
    ob_start();
    menu_execute_active_handler();
    $contents = ob_get_clean();
    return $contents;
}

However, it seems D7 just spits out the HTML to the browser on the menu_execute_active_handler() call.

Any ideas how to get the html output into my variable?

Thanks

Comments

Dakanji’s picture

Tracking the Drupal flow line by line and function by function reveals the culprit to be ob_flush in the drupal_page_footer function

Using the following instead of ob_flush would make the application a bit more friendly

    $data = ob_get_contents();
    ob_clean();
    print $data;
tce’s picture

Just curious, could you not just use hook_exit(), get the data then stop the script execution using drupal_exit(), that way ob_flush is never called.

<?php
/**
 * Implements hook_exit().
 */
function MODULENAME_exit($destination = NULL) { 
  $data = ob_get_contents();
  // do something with $data

  drupal_exit();
}
?>
tce’s picture

Actually, I think you can skip all that and just do the following:

<?php
function getDrupalHTML() {
    define('DRUPAL_ROOT', getcwd());
    require_once DRUPAL_ROOT . '/includes/bootstrap.inc';
    drupal_bootstrap(DRUPAL_BOOTSTRAP_FULL);
    
    // As stated in the docs: The second argument is a boolean to indicate whether the content should be sent to the browser using the appropriate delivery callback (TRUE) or whether to return the result to the caller (FALSE).
    $data_array = menu_execute_active_handler(NULL, FALSE);

    // Use drupal_deliver_html_page() to convert the array into HTML
    return drupal_deliver_html_page($data_array)
}
?>
Dakanji’s picture

Thanks but drupal_page_footer is called downstream of drupal_deliver_html_page so the expected outcome is the same.

Dakanji’s picture

For now, I have just implemented my versions of the relevant drupal functions.

Now works fine but this may be more elegant.

Dakanji’s picture

Finally solved by adding a delivery callback to my module_menu function and handling things there to bypass the problem function.

/**
 * Implements hook_menu().
 */
function MODULE-NAME_menu() 
{
	$items = array();
	$items['MODULE-NAME'] = array(
		'page callback'		=>	'MODULE-NAME_output',
		'access arguments'	=>	array('access content'),
		'delivery callback'	=>	'MODULE-NAME_deliver_html_page',
		'type'			=>	MENU_CALLBACK
	);
	
	return $items;
}

/**
 * Page callback: Display MODULE-NAME HTML Output
 *
 * @see MODULE-NAME_menu()
 */
function MODULE-NAME_output() 
{
	return 'Some Output HTML';
}

/**
 * Delivery callback: Render MODULE-NAME Page
 *
 * @see MODULE-NAME_menu()
 */
function MODULE-NAME_deliver_html_page($page_callback_result) {
	/* Adapted from "drupal_deliver_html_page" */
	// Menu status constants are integers; page content is a string or array.
	if (is_int($page_callback_result)) 
	{
		// Integers mean an error page is required! 
		// Send to the default Drupal function and exit.
		// Note use of exit instead of drupal_exit (not needed here).
		drupal_deliver_html_page($page_callback_result);
		exit;
	}
	elseif (isset($page_callback_result)) 
	{
		/* Print anything besides a menu constant if not NULL or undefined. */
		// Send the correct charset HTTP header if code running
		// for this page request has not already set the content type header.
		if (is_null(drupal_get_http_header('Content-Type'))) 
		{
			drupal_add_http_header('Content-Type', 'text/html; charset=utf-8');
		}
		// Send appropriate HTTP-Header for browsers and search engines.
		global $language;
		drupal_add_http_header('Content-Language', $language->language);
		// Render page
		print drupal_render_page($page_callback_result);
	}
	/* Adapted from "drupal_page_footer" */
	// Perform end-of-request tasks.
	global $user;
	module_invoke_all('exit');
	// Commit the user session, if needed.
	drupal_session_commit();
	if (variable_get('cache', 0) && ($cache = drupal_page_set_cache())) 
	{
		drupal_serve_page_from_cache($cache);
	}
	else 
	{
		$data = ob_get_contents();
		ob_clean();
		print $data;
	}
	_registry_check_code(REGISTRY_WRITE_LOOKUP_CACHE);
	drupal_cache_system_paths();
	module_implements_write_cache();
	system_run_automated_cron();
}