Commit bf24773d authored by Dries's avatar Dries

- Patch #1677304 by socketwench, Niklas Fiekas: Remove drupal_deliver_page(),...

- Patch #1677304 by socketwench, Niklas Fiekas: Remove drupal_deliver_page(), ajax_deliver(), drupal_deliver_html_page().
parent 69700764
......@@ -47,9 +47,7 @@
* function named by #ajax['callback'], which returns the form element that
* has been updated and needs to be returned to the browser, or
* alternatively, an array of custom Ajax commands.
* - The page delivery callback for 'system/ajax', ajax_deliver(), renders the
* element returned by #ajax['callback'], and returns the JSON string
* created by ajax_render() to the browser.
* - The array is serialized using ajax_render() and sent to the browser.
* - The browser unserializes the returned JSON string into an array of
* command objects and executes each command, resulting in the old page
* content within and including the HTML element specified by
......@@ -419,72 +417,6 @@ function ajax_base_page_theme() {
}
}
/**
* Packages and sends the result of a page callback as an Ajax response.
*
* This function is the equivalent of drupal_deliver_html_page(), but for Ajax
* requests. Like that function, it:
* - Adds needed HTTP headers.
* - Prints rendered output.
* - Performs end-of-request tasks.
*
* @param $page_callback_result
* The result of a page callback. Can be one of:
* - NULL: to indicate no content.
* - An integer menu status constant: to indicate an error condition.
* - A string of HTML content.
* - A renderable array of content.
*
* @see drupal_deliver_html_page()
*/
function ajax_deliver($page_callback_result) {
// Browsers do not allow JavaScript to read the contents of a user's local
// files. To work around that, the jQuery Form plugin submits forms containing
// a file input element to an IFRAME, instead of using XHR. Browsers do not
// normally expect JSON strings as content within an IFRAME, so the response
// must be customized accordingly.
// @see http://malsup.com/jquery/form/#file-upload
// @see Drupal.ajax.prototype.beforeSend()
$iframe_upload = !empty($_POST['ajax_iframe_upload']);
// Emit a Content-Type HTTP header if none has been added by the page callback
// or by a wrapping delivery callback.
if (is_null(drupal_get_http_header('Content-Type'))) {
if (!$iframe_upload) {
// Standard JSON can be returned to a browser's XHR object, and to
// non-browser user agents.
// @see http://www.ietf.org/rfc/rfc4627.txt?number=4627
drupal_add_http_header('Content-Type', 'application/json; charset=utf-8');
}
else {
// Browser IFRAMEs expect HTML. With most other content types, Internet
// Explorer presents the user with a download prompt.
drupal_add_http_header('Content-Type', 'text/html; charset=utf-8');
}
}
// Print the response.
$commands = ajax_prepare_response($page_callback_result);
$json = ajax_render($commands);
if (!$iframe_upload) {
// Standard JSON can be returned to a browser's XHR object, and to
// non-browser user agents.
print $json;
}
else {
// Browser IFRAMEs expect HTML. Browser extensions, such as Linkification
// and Skype's Browser Highlighter, convert URLs, phone numbers, etc. into
// links. This corrupts the JSON response. Protect the integrity of the
// JSON data by making it the value of a textarea.
// @see http://malsup.com/jquery/form/#file-upload
// @see http://drupal.org/node/1009382
print '<textarea>' . $json . '</textarea>';
}
// Perform end-of-request tasks.
ajax_footer();
}
/**
* Converts the return value of a page callback into an Ajax commands array.
*
......
......@@ -2550,10 +2550,10 @@ function drupal_maintenance_theme() {
* If fast 404 pages are enabled, and this is a matching page then print a
* simple 404 page and exit.
*
* This function is called from drupal_deliver_html_page() at the time when a
* a normal 404 page is generated, but it can also optionally be called directly
* from settings.php to prevent a Drupal bootstrap on these pages. See
* documentation in settings.php for the benefits and drawbacks of using this.
* This function is called when a normal 404 page is generated, but it can also
* optionally be called directly from settings.php to prevent a Drupal
* bootstrap on these pages. See documentation in settings.php for the benefits
* and drawbacks of using this.
*
* Paths to dynamically-generated content, such as image styles, should also be
* accounted for in this function.
......
......@@ -2368,200 +2368,6 @@ function l($text, $path, array $options = array()) {
return '<a href="' . check_plain(url($path, $options)) . '"' . drupal_attributes($options['attributes']) . '>' . ($options['html'] ? $text : check_plain($text)) . '</a>';
}
/**
* Delivers a page callback result to the browser in the appropriate format.
*
* This function is most commonly called by menu_execute_active_handler().
*
* When a user requests a page, index.php calls menu_execute_active_handler(),
* which calls the 'page callback' function registered in hook_menu(). The page
* callback function can return one of:
* - NULL: to indicate no content.
* - An integer menu status constant: to indicate an error condition.
* - A string of HTML content.
* - A renderable array of content.
* Returning a renderable array rather than a string of HTML is preferred,
* because that provides modules with more flexibility in customizing the final
* result.
*
* When the page callback returns its constructed content to
* menu_execute_active_handler(), this function gets called. The purpose of
* this function is to determine the most appropriate 'delivery callback'
* function to route the content to. The delivery callback function then
* sends the content to the browser in the needed format. The default delivery
* callback is drupal_deliver_html_page(), which delivers the content as an HTML
* page, complete with blocks in addition to the content. This default can be
* overridden on a per menu router item basis by setting 'delivery callback' in
* hook_menu() or hook_menu_alter(), and can also be overridden on a per request
* basis in hook_page_delivery_callback_alter().
*
* For example, the same page callback function can be used for an HTML
* version of the page and an Ajax version of the page. The page callback
* function just needs to decide what content is to be returned and the
* delivery callback function will send it as an HTML page or an Ajax
* response, as appropriate.
*
* In order for page callbacks to be reusable in different delivery formats,
* they should not issue any "print" or "echo" statements, but instead just
* return content.
*
* Also note that this function does not perform access checks. The delivery
* callback function specified in hook_menu(), hook_menu_alter(), or
* hook_page_delivery_callback_alter() will be called even if the router item
* access checks fail. This is intentional (it is needed for JSON and other
* purposes), but it has security implications. Do not call this function
* directly unless you understand the security implications, and be careful in
* writing delivery callbacks, so that they do not violate security. See
* drupal_deliver_html_page() for an example of a delivery callback that
* respects security.
*
* @param $page_callback_result
* The result of a page callback. Can be one of:
* - NULL: to indicate no content.
* - An integer menu status constant: to indicate an error condition.
* - A string of HTML content.
* - A renderable array of content.
* @param $default_delivery_callback
* (Optional) If given, it is the name of a delivery function most likely
* to be appropriate for the page request as determined by the calling
* function (e.g., menu_execute_active_handler()). If not given, it is
* determined from the menu router information of the current page.
*
* @see menu_execute_active_handler()
* @see hook_menu()
* @see hook_menu_alter()
* @see hook_page_delivery_callback_alter()
*/
function drupal_deliver_page($page_callback_result, $default_delivery_callback = NULL) {
if (!isset($default_delivery_callback) && ($router_item = menu_get_item())) {
$default_delivery_callback = $router_item['delivery_callback'];
}
$delivery_callback = !empty($default_delivery_callback) ? $default_delivery_callback : 'drupal_deliver_html_page';
// Give modules a chance to alter the delivery callback used, based on
// request-time context (e.g., HTTP request headers).
drupal_alter('page_delivery_callback', $delivery_callback);
if (function_exists($delivery_callback)) {
$delivery_callback($page_callback_result);
}
else {
// If a delivery callback is specified, but doesn't exist as a function,
// something is wrong, but don't print anything, since it's not known
// what format the response needs to be in.
watchdog('delivery callback not found', 'callback %callback not found: %path.', array('%callback' => $delivery_callback, '%path' => current_path()), WATCHDOG_ERROR);
}
}
/**
* Packages and sends the result of a page callback to the browser as HTML.
*
* @param $page_callback_result
* The result of a page callback. Can be one of:
* - NULL: to indicate no content.
* - An integer menu status constant: to indicate an error condition.
* - A string of HTML content.
* - A renderable array of content.
*
* @see drupal_deliver_page()
*/
function drupal_deliver_html_page($page_callback_result) {
// Emit the correct charset HTTP header, but not if the page callback
// result is NULL, since that likely indicates that it printed something
// in which case, no further headers may be sent, and not if code running
// for this page request has already set the content type header.
if (isset($page_callback_result) && is_null(drupal_get_http_header('Content-Type'))) {
drupal_add_http_header('Content-Type', 'text/html; charset=utf-8');
}
// Send X-UA-Compatible HTTP header to force IE to use the most recent
// rendering engine or use Chrome's frame rendering engine if available.
if (is_null(drupal_get_http_header('X-UA-Compatible'))) {
drupal_add_http_header('X-UA-Compatible', 'IE=edge,chrome=1');
}
drupal_add_http_header('Content-Language', drupal_container()->get(LANGUAGE_TYPE_INTERFACE)->langcode);
// Menu status constants are integers; page content is a string or array.
if (is_int($page_callback_result)) {
$site_config = config('system.site');
// @todo: Break these up into separate functions?
switch ($page_callback_result) {
case MENU_NOT_FOUND:
// Print a 404 page.
drupal_add_http_header('Status', '404 Not Found');
watchdog('page not found', check_plain(current_path()), NULL, WATCHDOG_WARNING);
// Check for and return a fast 404 page if configured.
drupal_fast_404();
// Keep old path for reference, and to allow forms to redirect to it.
if (!isset($_GET['destination'])) {
$_GET['destination'] = current_path();
}
$path = drupal_get_normal_path($site_config->get('page.404'));
if ($path && $path != current_path()) {
// Custom 404 handler. Set the active item in case there are tabs to
// display, or other dependencies on the path.
menu_set_active_item($path);
$return = menu_execute_active_handler($path, FALSE);
}
if (empty($return) || $return == MENU_NOT_FOUND || $return == MENU_ACCESS_DENIED) {
// Standard 404 handler.
drupal_set_title(t('Page not found'));
$return = t('The requested page "@path" could not be found.', array('@path' => request_uri()));
}
drupal_set_page_content($return);
$page = element_info('page');
print drupal_render_page($page);
break;
case MENU_ACCESS_DENIED:
// Print a 403 page.
drupal_add_http_header('Status', '403 Forbidden');
watchdog('access denied', check_plain(current_path()), NULL, WATCHDOG_WARNING);
// Keep old path for reference, and to allow forms to redirect to it.
if (!isset($_GET['destination'])) {
$_GET['destination'] = current_path();
}
$path = drupal_get_normal_path($site_config->get('page.403'));
if ($path && $path != current_path()) {
// Custom 403 handler. Set the active item in case there are tabs to
// display or other dependencies on the path.
menu_set_active_item($path);
$return = menu_execute_active_handler($path, FALSE);
}
if (empty($return) || $return == MENU_NOT_FOUND || $return == MENU_ACCESS_DENIED) {
// Standard 403 handler.
drupal_set_title(t('Access denied'));
$return = t('You are not authorized to access this page.');
}
print drupal_render_page($return);
break;
case MENU_SITE_OFFLINE:
// Print a 503 page.
drupal_maintenance_theme();
drupal_add_http_header('Status', '503 Service unavailable');
drupal_set_title(t('Site under maintenance'));
print theme('maintenance_page', array('content' => filter_xss_admin(variable_get('maintenance_mode_message',
t('@site is currently under maintenance. We should be back shortly. Thank you for your patience.', array('@site' => $site_config->get('name')))))));
break;
}
}
elseif (isset($page_callback_result)) {
// Print anything besides a menu constant, assuming it's not NULL or
// undefined.
print drupal_render_page($page_callback_result);
}
}
/**
* Performs end-of-request tasks.
*
......
......@@ -1368,7 +1368,6 @@ function _menu_build_tree($menu_name, array $parameters = array()) {
'access_arguments',
'page_callback',
'page_arguments',
'delivery_callback',
'tab_parent',
'tab_root',
'title',
......@@ -3609,10 +3608,6 @@ function _menu_router_build($callbacks) {
}
}
}
// Same for delivery callbacks.
if (!isset($item['delivery callback']) && isset($parent['delivery callback'])) {
$item['delivery callback'] = $parent['delivery callback'];
}
// Same for theme callbacks.
if (!isset($item['theme callback']) && isset($parent['theme callback'])) {
$item['theme callback'] = $parent['theme callback'];
......@@ -3654,7 +3649,6 @@ function _menu_router_build($callbacks) {
'access callback' => '',
'page arguments' => array(),
'page callback' => '',
'delivery callback' => '',
'title arguments' => array(),
'title callback' => 't',
'theme arguments' => array(),
......@@ -3703,7 +3697,6 @@ function _menu_router_save($menu, $masks) {
'access_arguments',
'page_callback',
'page_arguments',
'delivery_callback',
'fit',
'number_parts',
'context',
......@@ -3735,7 +3728,6 @@ function _menu_router_save($menu, $masks) {
'access_arguments' => serialize($item['access arguments']),
'page_callback' => $item['page callback'],
'page_arguments' => serialize($item['page arguments']),
'delivery_callback' => $item['delivery callback'],
'fit' => $item['_fit'],
'number_parts' => $item['_number_parts'],
'context' => $item['context'],
......
......@@ -1418,7 +1418,7 @@ function book_menu_subtree_data($link) {
$query->join('menu_router', 'm', 'm.path = ml.router_path');
$query->join('book', 'b', 'ml.mlid = b.mlid');
$query->fields('b');
$query->fields('m', array('load_functions', 'to_arg_functions', 'access_callback', 'access_arguments', 'page_callback', 'page_arguments', 'delivery_callback', 'title', 'title_callback', 'title_arguments', 'type'));
$query->fields('m', array('load_functions', 'to_arg_functions', 'access_callback', 'access_arguments', 'page_callback', 'page_arguments', 'title', 'title_callback', 'title_arguments', 'type'));
$query->fields('ml');
$query->condition('menu_name', $link['menu_name']);
for ($i = 1; $i <= MENU_MAX_DEPTH && $link["p$i"]; ++$i) {
......
......@@ -42,7 +42,6 @@ function file_menu() {
$items['file/ajax'] = array(
'page callback' => 'file_ajax_upload',
'delivery callback' => 'ajax_deliver',
'access arguments' => array('access content'),
'theme callback' => 'ajax_base_page_theme',
'type' => MENU_CALLBACK,
......
......@@ -52,7 +52,7 @@ function menu_overview_form($form, &$form_state, $menu) {
global $menu_admin;
$form['#attached']['css'] = array(drupal_get_path('module', 'menu') . '/menu.admin.css');
$sql = "
SELECT m.load_functions, m.to_arg_functions, m.access_callback, m.access_arguments, m.page_callback, m.page_arguments, m.delivery_callback, m.title, m.title_callback, m.title_arguments, m.type, m.description, m.description_callback, m.description_arguments, ml.*
SELECT m.load_functions, m.to_arg_functions, m.access_callback, m.access_arguments, m.page_callback, m.page_arguments, m.title, m.title_callback, m.title_arguments, m.type, m.description, m.description_callback, m.description_arguments, ml.*
FROM {menu_links} ml LEFT JOIN {menu_router} m ON m.path = ml.router_path
WHERE ml.menu_name = :menu
ORDER BY p1 ASC, p2 ASC, p3 ASC, p4 ASC, p5 ASC, p6 ASC, p7 ASC, p8 ASC, p9 ASC";
......
......@@ -24,14 +24,14 @@ function setUp() {
/**
* Assert that a command with the required properties exists within the array of Ajax commands returned by the server.
*
* The Ajax framework, via the ajax_deliver() and ajax_render() functions,
* returns an array of commands. This array sometimes includes commands
* automatically provided by the framework in addition to commands returned by
* a particular page callback. During testing, we're usually interested that a
* particular command is present, and don't care whether other commands
* precede or follow the one we're interested in. Additionally, the command
* we're interested in may include additional data that we're not interested
* in. Therefore, this function simply asserts that one of the commands in
* The Ajax framework, via the ajax_render() function, returns an array of
* commands. This array sometimes includes commands automatically provided by
* the framework in addition to commands returned by a particular page
* callback. During testing, we're usually interested that a particular
* command is present, and don't care whether other commands precede or
* follow the one we're interested in. Additionally, the command we're
* interested in may include additional data that we're not interested in.
* Therefore, this function simply asserts that one of the commands in
* $haystack contains all of the keys and values in $needle. Furthermore, if
* $needle contains a 'settings' key with an array value, we simply assert
* that all keys and values within that array are present in the command we're
......
......@@ -703,12 +703,6 @@ function hook_menu_get_item_alter(&$router_item, $path, $original_map) {
* instead.
* - "page arguments": An array of arguments to pass to the page callback
* function, with path component substitution as described above.
* - "delivery callback": The function to call to package the result of the
* page callback function and send it to the browser. Defaults to
* drupal_deliver_html_page() unless a value is inherited from a parent menu
* item. Note that this function is called even if the access checks fail,
* so any custom delivery callback function should take that into account.
* See drupal_deliver_html_page() for an example.
* - "access callback": A function returning TRUE if the user has access
* rights to this menu item, and FALSE if not. It can also be a boolean
* constant instead of a function, and you can also use numeric values
......@@ -3643,51 +3637,6 @@ function hook_date_formats_alter(&$formats) {
}
}
/**
* Alters the delivery callback used to send the result of the page callback to the browser.
*
* Called by drupal_deliver_page() to allow modules to alter how the
* page is delivered to the browser.
*
* This hook is intended for altering the delivery callback based on
* information unrelated to the path of the page accessed. For example,
* it can be used to set the delivery callback based on a HTTP request
* header (as shown in the code sample). To specify a delivery callback
* based on path information, use hook_menu() or hook_menu_alter().
*
* This hook can also be used as an API function that can be used to explicitly
* set the delivery callback from some other function. For example, for a module
* named MODULE:
* @code
* function MODULE_page_delivery_callback_alter(&$callback, $set = FALSE) {
* static $stored_callback;
* if ($set) {
* $stored_callback = $callback;
* }
* elseif (isset($stored_callback)) {
* $callback = $stored_callback;
* }
* }
* function SOMEWHERE_ELSE() {
* $desired_delivery_callback = 'foo';
* MODULE_page_delivery_callback_alter($desired_delivery_callback, TRUE);
* }
* @endcode
*
* @param $callback
* The name of a function.
*
* @see drupal_deliver_page()
*/
function hook_page_delivery_callback_alter(&$callback) {
// jQuery sets a HTTP_X_REQUESTED_WITH header of 'XMLHttpRequest'.
// If a page would normally be delivered as an html page, and it is called
// from jQuery, deliver it instead as an Ajax response.
if (isset($_SERVER['HTTP_X_REQUESTED_WITH']) && $_SERVER['HTTP_X_REQUESTED_WITH'] == 'XMLHttpRequest' && $callback == 'drupal_deliver_html_page') {
$callback = 'ajax_deliver';
}
}
/**
* Alters theme operation links.
*
......@@ -4117,8 +4066,7 @@ function hook_countries_alter(&$countries) {
* Supported values are MENU_SITE_OFFLINE, MENU_ACCESS_DENIED,
* MENU_NOT_FOUND and MENU_SITE_ONLINE. Any other value than
* MENU_SITE_ONLINE will skip the default menu handling system and be passed
* for delivery to drupal_deliver_page() with a NULL
* $default_delivery_callback.
* for delivery directly.
* @param $path
* Contains the system path that is going to be loaded. This is read only,
* use hook_url_inbound_alter() to change the path.
......
......@@ -1060,13 +1060,6 @@ function system_schema() {
'type' => 'blob',
'not null' => FALSE,
),
'delivery_callback' => array(
'description' => 'The name of the function that sends the result of the page_callback function to the browser.',
'type' => 'varchar',
'length' => 255,
'not null' => TRUE,
'default' => '',
),
'fit' => array(
'description' => 'A numeric representation of how specific the path is.',
'type' => 'int',
......
......@@ -611,7 +611,6 @@ function system_menu() {
$items['system/ajax'] = array(
'title' => 'AHAH callback',
'page callback' => 'ajax_form_callback',
'delivery callback' => 'ajax_deliver',
'access callback' => TRUE,
'theme callback' => 'ajax_base_page_theme',
'type' => MENU_CALLBACK,
......
......@@ -12,14 +12,12 @@ function ajax_test_menu() {
$items['ajax-test/render'] = array(
'title' => 'ajax_render',
'page callback' => 'ajax_test_render',
'delivery callback' => 'ajax_deliver',
'access callback' => TRUE,
'type' => MENU_CALLBACK,
);
$items['ajax-test/render-error'] = array(
'title' => 'ajax_render_error',
'page callback' => 'ajax_test_error',
'delivery callback' => 'ajax_deliver',
'access callback' => TRUE,
'type' => MENU_CALLBACK,
);
......@@ -40,7 +38,7 @@ function ajax_test_system_theme_info() {
}
/**
* Menu callback; Return an element suitable for use by ajax_deliver().
* Page callback: Returns an element suitable for use by ajax_render().
*
* Additionally ensures that ajax_render() incorporates JavaScript settings
* generated during the page request by invoking drupal_add_js() with a dummy
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment