Eine Überschreibung von html.tpl.php aus einem Modul ausgeben?

8

Gibt es eine Möglichkeit, die Ausgabe einer Seite aus einem bereitgestellten Modul zu überschreiben und Ihre eigene html.tpl.php auszugeben, um effektiv die Kontrolle über die Ausgabe des Themas zu übernehmen?

Ich möchte dies tun, um eine einzigartige Anmelde- / Registrierungserfahrung zu schaffen, kann aber nur die Vorlage auf Seitenebene überschreiben, nicht die Vorlage auf HTML-Ebene. Ich sehe, dass das Druckmodul dies tut, aber ist das der Weg, sich dem anzunähern?

Kevin
quelle
Ich habe momentan keine Zeit, es zu konkretisieren, aber ich denke, Sie könnten es verwenden hook_menu_alter(), um den delivery callbackPfad für den Benutzer / Login in Ihre eigene Version von zu ändern drupal_deliver_html_page(). Das sollte Ihnen die absolute Kontrolle darüber geben, was auf dem Bildschirm gerendert wird, obwohl dies bedeutet, dass Sie selbst die entsprechenden Überschriften festlegen
Clive
Ja, da habe ich angefangen, aber ich war mir nicht sicher, ob du all diese Beinarbeit machen müsstest.
Kevin
Ich bin mir nicht sicher, ob es einen Ausweg gibt, um ehrlich zu sein. Ein gutes Beispiel aus dem Kern ist die ajax_deliver()Funktion, die gleich wird $page_callback_result, drupal_html_deliver_page()aber anders verarbeitet wird. Ich bin mir nicht sicher, ob Sie den Prozess weiter unten auf sinnvolle Weise unterbrechen können, bevor die Theme-Engine aktiviert wird
Clive
Gibt es einen bestimmten Grund, die Ausgabe von html.tpl.php zu ändern? Es gibt viele Funktionen, die die Ausgabe dieser Vorlagendatei ändern.
Kiamlaluno
@kiamlaluno, Dies ist eine interessante Frage. Ich finde auch eine Möglichkeit, das Rendern von Drupal-Seiten zu beenden, bevor die Theme-Engine aktiviert wird. Der Zweck besteht darin, eine Seite (eine Art Webdienst) genau wie die JSON-Ausgabe oder was auch immer von Views Datasource bereitgestellt zu rendern, wenn diese deaktiviertusing_views_api_mode ist.
Sithu

Antworten:

4

Entsprechend dieser Antwort können Sie den Seiteninhalt einfach im Menüseitenrückruf drucken, anstatt ihn zurückzugeben.

Um Daten aus der Drupal-Datenbank abzurufen und / oder in PHP zu erstellen, benötigen Sie einen Seitenrückruf (in einem benutzerdefinierten Modul), der die Daten ohne das vollständige Layout-Rendering ausgibt. Dies ist einfach möglich, indem Sie den Inhalt der Seite direkt in Ihrem Seitenrückruf drucken, anstatt ihn zurückzugeben.

Ich denke , das Druckmodul die druckerfreundliche Seite auf diese Weise umgesetzt. Das Folgende ist das Code-Snippet aus dem 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;
    ......
}

Demnach verwendet das Modul die benutzerdefinierte HTML-Vorlage print.tpl.php. Es ist eine Vorlage auf HTML-Ebene. Das Modul ruft dann den HTML-Code ab, indem es ihn aufruft theme('print',...)und direkt im Browser mit rendert print $html;.

Hier ist eine allgemeine Idee für Ihren Zweck: 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;
} 

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

Ich hoffe, dies wird Ihre Anmeldeseite nach Bedarf anpassen.

Sithu
quelle
2

Sowohl @Sithu als auch @Ayesh K haben großartige Antworten geliefert. In diesem Beispiel werde ich die Methode von @ Ayesh und Teile des Codes von @ Sithu für eine vollständige Lösung kombinieren.

Die Funktionen hooks_menu oder hook_menu_alter bieten beide eine delivery callback, die Drupal anweist, wie Ihr Code verpackt werden soll. Standardmäßig setzt Drupal delivery callbackauf drupal_deliver_html_page () , wodurch Drupal grob angewiesen wird , Ihre Seite in html.tpl.phpund einzuschließenpage.tpl.php .

Um die Art und Weise zu ändern, wie Drupal Ihre Seite umschließt, kopieren Sie die Funktion drupal_deliver_html_page()in Ihr Modul und ändern Sie sie. Rufen Sie dann Ihre neue Funktion in auf delivery callback. Drupal verwendet diese Funktion dann, um Ihre Seite zu verpacken.

Beispiel

Hier ist ein Arbeitsmodul. Fügen Sie den folgenden Code in Ihr /sites/all/modules/MYMODULEVerzeichnis ein und aktivieren Sie das Modul.

Um einen vorhandenen Pfad zu überschreiben, ersetzen Sie ihn optional hook_menudurch 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
quelle
Frage: Funktioniert dieses Beispiel mit dem Caching-System von Drupal und hätte es separate Caches für verschiedene Abfragezeichenfolgen?
Darvanen
Ich glaube, Drupal speichert standardmäßig das Formular bzw. die Seite zwischen. Ich bin mir keiner anderen Caching-Prozesse sicher.
timofey.com
Vielen Dank. Am Ende habe ich mithilfe der API einen benutzerdefinierten Cache für meine Seitenantworten erstellt.
Darvanen
1

Ich denke, Sie müssen einige Zeit investieren, um den am besten geeigneten Haken dafür zu finden. Du kannst es versuchen

  • hook_page_alter, um zu ändern, "was gerendert werden soll",

  • Verwenden Sie hook_menu_alter , um den Übermittlungsrückruf für Anmelde- und Registrierungsmenürouter zu ändern.

  • Verwenden Sie eine Seite - user-login.tpl.php , um die Seitenvorlage der Anmeldeseite zu übernehmen.

  • Fügen Sie einige Vorlagenvorschläge in template.php hinzu, um eine andere html.tpl.php-Datei nur für die Anmeldepfade zu verwenden.

  • oder schließlich hook_theme_regitry_alter , um die Theme-Registrierung zu ändern und das zu tun, was Sie tun wollten (die Änderung html.tpl.php)

AyeshK
quelle
+1 genau richtig! hook_theme_registry_alter()funktioniert möglicherweise nicht, da es höchstwahrscheinlich die Vorlage für alle Seiten ändert, aber delivery callbackdefinitiv funktioniert. Ich habe diese Methode in meiner Antwort hier zusätzlich untersucht.
timofey.com