Menerbitkan timpa html.tpl.php dari modul?


8

Apakah ada cara untuk mengganti output halaman dari modul yang disumbangkan dan mengeluarkan html.tpl.php Anda sendiri, secara efektif mengendalikan output dari tema?

Saya ingin melakukan ini dalam upaya untuk membuat pengalaman login / registrasi yang unik, tetapi sepertinya hanya bisa mengesampingkan templat tingkat halaman, bukan templat level html. Saya melihat bahwa modul cetak melakukan ini, tetapi apakah itu cara untuk mendekatinya?


Saya tidak punya waktu untuk menyempurnakannya sekarang, tetapi saya pikir Anda dapat menggunakan hook_menu_alter()untuk mengubah delivery callbackjalur pengguna / masuk ke versi Anda sendiri drupal_deliver_html_page(). Itu akan memberi Anda kendali mutlak atas apa yang ditampilkan di layar, meskipun itu berarti mengatur tajuk yang tepat sendiri
Clive

Ya, di situlah saya mulai menuju, tetapi tidak yakin apakah Anda perlu melakukan semua kerja keras itu.
Kevin

Saya tidak yakin ada cara putaran itu harus jujur, contoh yang baik dari inti adalah ajax_deliver()fungsi, yang mendapat sama $page_callback_resultseperti drupal_html_deliver_page()tetapi proses itu berbeda. Saya tidak yakin apakah Anda dapat menghentikan proses lebih jauh dengan cara yang berarti sebelum mesin tema terlibat
Clive

Apakah ada alasan khusus untuk mengubah output html.tpl.php? Ada banyak fungsi yang mengubah apa yang dihasilkan file template.
kiamlaluno

@kiamlaluno, Ini pertanyaan yang menarik. Saya juga menemukan cara untuk menghentikan rendering halaman Drupal sebelum mesin tema terlibat. Tujuannya adalah untuk membuat halaman (semacam layanan web) seperti halnya output JSON atau apa pun yang disediakan oleh Views Datasource ketika using_views_api_modedimatikan.
Sithu

Jawaban:


4

Menurut jawaban ini , Anda cukup mencetak konten halaman dalam panggilan balik halaman menu daripada mengembalikannya.

Untuk mendapatkan data dari database Drupal dan / atau diproduksi dalam PHP, Anda memerlukan panggilan balik halaman (dalam modul khusus) yang menampilkan data tanpa rendering tata letak lengkap. Ini mudah dilakukan dengan mencetak konten halaman langsung di callback halaman Anda alih-alih mengembalikannya.

Saya kira modul Cetak menerapkan halaman ramah-printer dengan cara ini. Berikut ini adalah cuplikan kode dari modul.

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;
    ......
}

Menurut ini, modul menggunakan templat HTML khusus print.tpl.php. Ini adalah template tingkat HTML. Modul kemudian mendapatkan HTML dengan memanggil theme('print',...)dan merendernya langsung ke browser menggunakan print $html;.

Inilah ide umum untuk tujuan Anda: 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;
} 

Templat: 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>

Saya harap ini akan menyesuaikan halaman login Anda sesuai kebutuhan.


2

Kedua @Sithu dan @Ayesh K telah menyediakan jawaban yang besar. Dalam contoh ini, saya akan menggabungkan metode @ Ayesh dan bagian dari kode @ Sithu untuk solusi yang lengkap.

hooks_menu atau hook_menu_alter fungsi keduanya memberikan delivery callback, yang menginstruksikan Drupal pada bagaimana Anda ingin kode Anda dibungkus. Secara default, Drupal menetapkan delivery callbackke drupal_deliver_html_page () , yang secara kasar memberi tahu Drupal untuk membungkus halaman Anda dengan html.tpl.phpdan page.tpl.php.

Untuk memodifikasi cara Drupal membungkus halaman Anda, salin fungsi drupal_deliver_html_page()ke modul Anda, dan modifikasi itu. Kemudian panggil fungsi baru Anda di delivery callback. Drupal kemudian akan menggunakan fungsi itu untuk membungkus halaman Anda.

Contoh

Berikut adalah modul yang berfungsi. Masukkan kode berikut ke dalam /sites/all/modules/MYMODULEdirektori Anda dan aktifkan modul.

Secara opsional, untuk mengganti jalur yang ada, gantikan hook_menudengan 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; }

Pertanyaan: apakah contoh ini berfungsi dengan sistem cache Drupal, dan apakah ini memiliki cache terpisah untuk string kueri yang berbeda?
Darvanen

Saya percaya, secara default Drupal menyimpan cache formulir dan halaman, masing-masing. Saya tidak yakin dengan proses caching lainnya.
timofey.com

Terima kasih. Saya akhirnya membuat cache khusus untuk respons halaman saya menggunakan API.
Darvanen

1

Saya pikir Anda perlu menginvestasikan waktu untuk menemukan kait yang paling tepat untuk ini. Anda dapat mencoba

  • hook_page_alter untuk mengubah "apa yang akan diberikan",

  • gunakan hook_menu_alter untuk mengubah callback pengiriman untuk login dan mendaftar router menu,

  • gunakan halaman - file user-login.tpl.php untuk mengambil alih templat halaman dari halaman login,

  • tambahkan beberapa saran template di template.php untuk menggunakan file html.tpl.php yang berbeda hanya untuk jalur login,

  • atau akhirnya, hook_theme_regitry_alter , untuk mengubah tema registry dan melakukan apa yang ingin Anda lakukan (perubahan html.tpl.php)


+1 Tempat di! hook_theme_registry_alter()mungkin tidak berfungsi karena kemungkinan besar akan mengubah templat untuk semua halaman, tetapi delivery callbackpasti akan berfungsi. Saya juga telah menjelajahi metode ini dalam jawaban saya, di sini.
timofey.com
Dengan menggunakan situs kami, Anda mengakui telah membaca dan memahami Kebijakan Cookie dan Kebijakan Privasi kami.
Licensed under cc by-sa 3.0 with attribution required.