Выпустить переопределение html.tpl.php из модуля?

8

Есть ли способ переопределить вывод страницы из добавленного модуля и создать собственный html.tpl.php, эффективно контролируя вывод из темы?

Я хочу сделать это в попытке создать уникальный опыт входа / регистрации, но может показаться, что он переопределяет только шаблон уровня страницы, а не шаблон уровня html. Я вижу, что модуль печати делает это, но так ли это?

Kevin
источник
У меня нет времени, чтобы уточнить это прямо сейчас, но я думаю, что вы могли бы использовать, hook_menu_alter()чтобы изменить delivery callbackпуть для пользователя / входа в систему к вашей собственной версии drupal_deliver_html_page(). Это должно дать вам полный контроль над тем, что визуализируется на экране, хотя это будет означать , устанавливая соответствующие заголовки сами
Clive
Да, именно туда я и отправился, но не был уверен, нужно ли вам делать всю эту работу.
Кевин
Я не уверен , что есть способ обойти это , чтобы быть честным, хорошим примером из ядра является ajax_deliver()функция, которая получает такой же , $page_callback_resultкак , drupal_html_deliver_page()но процессы по- другому. Я не уверен, что вы сможете еще более существенно прервать процесс до того, как включится движок тем
Клайв
Есть ли какая-то конкретная причина, чтобы изменить вывод html.tpl.php? Есть много функций, которые изменяют то, что выводит этот файл шаблона.
kiamlaluno
@kiamlaluno, это интересный вопрос. Я также нахожу способ прекратить рендеринг страниц Drupal до того, как включится движок тем. Цель состоит в том, чтобы отобразить страницу (какой-то веб-сервис) точно так же, как вывод в формате JSON или что-либо, предоставленное источником данных Views, когда using_views_api_modeвыключено.
Ситху

Ответы:

4

Согласно этому ответу , вы можете просто напечатать содержимое страницы в обратном вызове страницы меню, а не возвращать его.

Чтобы получить данные из базы данных Drupal и / или созданные на PHP, вам необходим обратный вызов страницы (в пользовательском модуле), который выводит данные без полной визуализации макета. Это легко сделать, напечатав содержимое страницы прямо в обратном вызове, а не возвращая его.

Я предполагаю, что модуль Print реализовал страницу для печати таким образом. Ниже приведен фрагмент кода из модуля.

function print_menu() {
  $items = array();

  $items[PRINT_PATH] = array(
    'title' => 'Printer-friendly',
    'page callback' => 'print_controller_html',
    'access arguments' => array('access print'),
    'type' => MENU_CALLBACK,
    'file' => 'print.pages.inc',
  );
  ........   
}   

/**
 * Generate an HTML version of the printer-friendly page
 *
 * @see print_controller()
 */
function print_controller_html() {
  $args = func_get_args();
  $path = filter_xss(implode('/', $args));
  $cid = isset($_GET['comment']) ? (int)$_GET['comment'] : NULL;

  // Handle the query
  $query = $_GET;
  unset($query['q']);

  $print = print_controller($path, $query, $cid, PRINT_HTML_FORMAT);
  if ($print !== FALSE) {
    $node = $print['node'];
    $html = theme('print', array('print' => $print, 'type' => PRINT_HTML_FORMAT, 'node' => $node));
    drupal_add_http_header('Content-Type', 'text/html; charset=utf-8');
    drupal_send_headers();
    print $html;
    ......
}

В соответствии с этим модуль использует пользовательский шаблон HTML print.tpl.php. Это шаблон уровня HTML. Затем модуль получает HTML-код, вызывая его, theme('print',...)и отображает его непосредственно в браузере с помощью print $html;.

Вот общая идея для вашей цели: mymodule.module

/**
 * Implements hook_menu().
 */
function mymodule_menu() {
  $items = array();
  $items['mylogin'] = array(
    'title' => 'Custom Login Page',
    'page callback' => 'mymodule_custom_login_page',
    'type' => MENU_CALLBACK,
    'access callback' => TRUE,
  );

  return $items;
} 
/**
 * Implements hook_theme().
 */
function mymodule_theme() {
  return array(
    'mylogin' => array(
      'variables' => array('page' => array()),
      'template' => 'mylogin', // mylogin.tpl.php in your module folder
    ),
  );
}
/**
 * Generate a custom login page
 * @see more in print_controller_html() in print.pages.inc of the Print module 
 */
function mymodule_custom_login_page(){
    $page = _mymodule_login_page_prerequisite(); // get/prepare necessary variables, js, css for the page
    $page['form'] = drupal_render(drupal_get_form('user_login')); // get login form
    // prepare html in mylogin.tpl.php
    // See more in print.tpl.php() in the Print module  
    $html = theme('mylogin', array('page' => $page)); 

    drupal_add_http_header('Content-Type', 'text/html; charset=utf-8');
    drupal_send_headers();
    print $html; // cease Drupal page rendering and render directly to the browser
} 
/**
 * Prepare the array for the template with common details
 * @see more _print_var_generator() in print.pages.inc of the Print module
 */
function _mymodule_login_page_prerequisite(){
    global $base_url, $language; 
    $page = array();
    $page['language']   = $language->language;
    $page['head']       = drupal_get_html_head();
    $page['title']      = '';
    $page['scripts']    = drupal_get_js();
    $page['favicon']    = '';
    // if there is a custom css file for this page
    // drupal_add_css(drupal_get_path('module', 'mymodule') . '/css/mylogin.css');
    $page['css'] = drupal_get_css();
    $page['message'] = drupal_get_messages();
    $page['footer_scripts'] = drupal_get_js('footer');

    return $page;
} 

Шаблон: mylogin.tpl.php

<?php
/**
 * @file
 * Custom login page template
 *
 * @ingroup page
 */
?>
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd">
<html xmlns="http://www.w3.org/1999/xhtml" lang="<?php print $page['language']; ?>" xml:lang="<?php print $page['language']; ?>">
  <head>
    <?php print $page['head']; ?>
    <title><?php print $page['title']; ?></title>
    <?php print $page['scripts']; ?>
    <?php print $page['favicon']; ?>
    <?php print $page['css']; ?>
  </head>
  <body>
    <h3>This is custom login page.</h3>
    <?php 
    if (!empty($page['message'])):
        foreach($page['message'] as $type => $message):
        ?>
            <div class="messages <?php print $type; ?>">
                <ul>
                <?php foreach($message as $msg): ?>
                    <li><?php print $msg; ?></li>
                <?php endforeach; ?>
                </ul>
            </div>
        <?php
        endforeach;
    endif; ?>
    <div><?php print $page['form']; ?></div>
    <?php print $page['footer_scripts']; ?>
  </body>
</html>

Я надеюсь, что это настроит вашу страницу входа в систему, как вам нужно.

Ситху
источник
2

И @Sithu, и @Ayesh K дали отличные ответы. В этом примере я объединю метод @ Ayesh и части кода @ Sithu для полного решения.

Функции hooks_menu или hook_menu_alter предоставляют функции delivery callback, которые инструктируют Drupal о том, как вы хотите, чтобы ваш код был упакован. По умолчанию Drupal устанавливает delivery callbackзначение drupal_deliver_html_page () , что примерно говорит Drupal обернуть вашу страницу в html.tpl.phpи page.tpl.php.

Чтобы изменить способ, которым Drupal оборачивает вашу страницу, скопируйте функцию drupal_deliver_html_page()в свой модуль и измените ее. Затем вызовите вашу новую функцию в delivery callback. Drupal будет использовать эту функцию для переноса вашей страницы.

пример

Вот рабочий модуль. Поместите следующий код в свой /sites/all/modules/MYMODULEкаталог и включите модуль.

Необязательно, чтобы переопределить существующий путь, заменитель hook_menuс hook_menu_alter.

MYMODULE.module

<?php
function MYMODULE_menu() {
  $items['login'] = array(
    'title' => 'Login',
    'page callback' => 'MYMODULE_page',
    'delivery callback' => 'MYMODULE_deliver',
    'access callback' => TRUE,
  );
  return $items;
}

function MYMODULE_page() {
  global $user;
  if (!$user->uid) return drupal_get_form('user_login'); // Show login for guests.
  else drupal_goto('user/' . $user->uid); // Redirect members to own profile.
}

// Code taken from drupal_deliver_html_page().
function MYMODULE_deliver($page_callback_result) {
  global $language, $base_path;
  // Pass variables to the template.
  $vars = array(
    'language' => $language->language,
    'title' => 'My Custom Login',
    'favicon' => '',
    'css' => $base_path . drupal_get_path('module', 'MYMODULE') . '/MYMODULE.css',
    'messages' => theme_status_messages(array('display' => NULL)),
    'content' => drupal_render($page_callback_result),
  );
  echo theme('MYMODULE_login', array('vars' => $vars)); // Uses template defined in hook_theme().
  drupal_page_footer();
}

function MYMODULE_theme() {
  $items['MYMODULE_login'] = array(
    'template' => 'MYMODULE',
    'render element' => 'page',
  );
  return $items;
}

MYMODULE.info

name = MYMODULE
description = "Module description."
package = Custom
core = 7.x

MYMODULE.tpl.php

<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML+RDFa 1.0//EN" "http://www.w3.org/MarkUp/DTD/xhtml-rdfa-1.dtd">
<html xmlns="http://www.w3.org/1999/xhtml" xml:lang="<?php print $vars['language']; ?>" version="XHTML+RDFa 1.0">
<head>
  <meta http-equiv="Content-Type" content="text/html; charset=utf-8" />
  <title><?php print $vars['title']; ?></title>
  <?php print $vars['favicon']; ?>
  <link rel="stylesheet" type="text/css" href="<?php print $vars['css']; ?>">
</head>
<body>
  <?php echo $vars['messages']; ?>
  <div class="content">
    <?php print $vars['content']; ?>
  </div>
</body>
</html>

MYMODULE.css

.content { color: pink; }
timofey.com
источник
Вопрос: работает ли этот пример с системой кэширования Drupal, и будут ли в ней отдельные кэши для разных строк запросов?
Дарванен
Я считаю, что по умолчанию Drupal кэширует форму и страницу соответственно. Я не уверен ни в каких других процессах кэширования.
timofey.com
Спасибо. Я закончил тем, что сделал пользовательский кеш для ответов на своих страницах, используя API.
Дарванен
1

Я думаю, вам нужно потратить некоторое время на поиск наиболее подходящего крючка для этого. Ты можешь попробовать

  • hook_page_alter для изменения «что будет отображено»,

  • используйте hook_menu_alter для изменения обратного вызова доставки для входа в систему и регистрации меню маршрутизаторов,

  • используйте страницу - файл user-login.tpl.php, чтобы взять шаблон страницы на странице входа,

  • добавьте несколько предложений шаблонов в template.php, чтобы использовать другой файл html.tpl.php только для путей входа в систему,

  • или, наконец, hook_theme_regitry_alter , чтобы изменить реестр тем и сделать то, что вы хотели сделать (изменение html.tpl.php)

AyeshK
источник
+1 Спот на! hook_theme_registry_alter()может не сработать, так как это, скорее всего, изменит шаблон для всех страниц, но delivery callbackопределенно сработает. Я дополнительно исследовал этот метод в своем ответе здесь.
timofey.com