10 handverlesene Drupal snippets
Ein kleines wiederverwendbares Code-Stück
Kleines Programmierbeispiel
Mini-Modul
Text
/**
* Implements hook_user_login().
*/
function MY_MODULE_user_login(&$edit, $account) {
// Don't redirect on password reset.
$current_menu_item = menu_get_item();
if ($current_menu_item['path'] == 'user/reset/%/%/%') {
return;
}
// Redirect user to "node/35" after the login.
$_GET['destination'] = 'node/35';
}
Snippet online: http://dropbucket.org/node/746
It depends.
Nimm dir nur den Teil raus den du benötigst
Exakt anpassbar an die jeweiligen Anforderungen
“Everything in code”
Am Ende schlankere Drupal Instanz mit weniger Modulen.
Drupal core, Contrib Module, “Examples” Modul
Problem
[term:root] funktioniert nur wenn der Term nicht selbst der Root-Term ist.
Lösung
Neues Token [term:root-or-current] selbst implementieren.
(oder konkret: Ein "besseres" [term:root] token implementieren.
/**
* Implements hook_token_info().
*/
function MY_MODULE_token_info() {
$info['tokens']['term']['root-or-current'] = array(
'type' => 'text',
'name' => t('Root or current term'),
'description' => t('Root of term or current term if it is already the root'),
);
return $info;
}
/**
* Implements hook_tokens().
*/
function MY_MODULE_tokens($type, $tokens, array $data = array(), array $options = array()) {
$sanitize = !empty($options['sanitize']);
$replacements = array();
// Our token acts on "term" entities
if ($type == 'term' && !empty($data['term'])) {
$term = $data['term'];
foreach ($tokens as $name => $original) {
switch ($name) {
// The name matches our token!
case 'root-or-current':
$parents = taxonomy_get_parents_all($term->tid);
$root_term = end($parents);
$replacements[$original] = $sanitize ?
check_plain($root_term->name) : $root_term->name;
break;
}
}
}
return $replacements;
}
Problem
Zusätzlich zu "Full content" und "Teaser" will ich einen weiteren "View Mode" verwenden.
Lösung
hook_entity_info_alter implementieren
/**
* Implements hook_entity_info_alter().
*/
function YOUR_MODULE_NAME_entity_info_alter(&$entity_info) {
$entity_info['node']['view modes']['custom_teaser'] = array(
'label' => t('Custom teaser'),
// should custom settings for this view mode enabled by default
'custom settings' => FALSE,
);
}
/**
* Implements hook_preprocess_node().
*/
function YOUR_MODULE_NAME_preprocess_node(&$variables) {
if ($variables['view_mode'] == 'custom_teaser') {
// eg. "node--article--custom-teaser.tpl.php" will be used if available.
$variables['theme_hook_suggestions'][] = 'node__' . $variables['type'] . '__custom_teaser';
}
}
Problem
Ich will ein neues Datums Format verwenden (Beispiel: Datum soll im Format "1. Dezember" ausgegeben werden.)
Lösung
/**
* Implements hook_date_format_types().
*/
function hook_date_format_types() {
return array(
'my_format' => t('My format'),
);
}
Drupal Beischeid geben, dass wir einen neuen Format-Type wollen.
/**
* Implements hook_date_formats().
*/
function hook_date_formats() {
$formats = array();
$formats[] = array(
'type' => 'my_format',
'format' => 'j. F', // eg "1. Dezember", http://php.net/manual/de/function.date.php
'locales' => array(),
);
return $formats;
}
Neuen Format-String definieren.
// in hook_install die variable setzen
variable_set('date_format_my_format', 'j. F');
// oder in der settings.php hardcoden
$conf['date_format_my_format'] = 'j. F';
// oder in einem Feature exportieren
Beides verbinden durch setzen einer Variable.
Problem
Bei "Access denied" soll auf die Login Seite weitergeleitet werden
Lösung
Eigenes menu-item implementieren, das bei Bedarf weiterleitet.
/**
* Implements hook_menu().
*/
function MYMODULE_menu() {
$items = array();
// custom access denied menu item (redirects to login)
$items['access-denied'] = array(
'page callback' => 'MYMODULE_access_denied',
'access callback' => TRUE,
);
return $items;
}
function MYMODULE_access_denied() {
global $user;
if ($user->uid) {
return MENU_ACCESS_DENIED;
}
// The code in drupal_get_destination() doesn't preserve any query string
// on 403 pages, so reproduce the part we want here.
$path = $_GET['destination'];
$query = drupal_http_build_query(
drupal_get_query_parameters(NULL, array('q', 'destination'))
);
if ($query != '') {
$path .= '?' . $query;
}
$destination = array('destination' => $path);
$url = url('user/login', array('query' => $destination, 'absolute' => TRUE));
header('Location: ' . $url , TRUE, 302);
drupal_exit();
}
// Tell Drupal to use the new menu-item as a 403 page.
// For example like this:
$conf['site_403'] = 'access-denied';
Problem
Bei jeden Node sollen zusätzliche Daten dargestellt werden (ohne dafür ein Feld anzulegen)
Lösung
5 hooks und 1 callback
/**
* Getter to return the phone number.
*/
function MY_MODULE_phone($node) {
return '089 / 12345' . $node->nid;
}
/**
* Implements hook_node_load().
*/
function MY_MODULE_node_load($nodes, $types) {
if (!in_array('article', $types)) {
return;
}
foreach ($nodes as $node) {
// add the project number to each node
$node->phone = MY_MODULE_phone($node);
}
}
Add the property to the node object on load.
/**
* Implements hook_field_extra_fields().
*/
function MY_MODULE_field_extra_fields() {
$extra = array();
$extra['node']['article']['display']['phone'] = array(
'label' => t('Phone number'),
'description' => t('Phone number'),
'weight' => 10,
);
return $extra;
}
Make it available in the display settings of the node type.
/**
* Implements hook_node_view
*/
function MY_MODULE_node_view($node, $view_mode, $langcode) {
if ($node->type != 'article') {
return;
}
$node->content['phone'] = array(
'#type' => 'item',
'#title' => t('Phone number: '),
'#markup' => $node->phone,
);
}
Add it to the content array when the node is viewed.
/**
* Implements hook_entity_property_info_alter().
*
* Note: This hook is provided by Entity API.
*/
function MY_MODULE_entity_property_info_alter(&$info) {
$info['node']['bundles']['article']['properties']['phone'] = array(
'type' => 'text',
'label' => t('Phone number'),
'sanitized' => TRUE,
'getter callback' => 'MY_MODULE_phone',
);
}
BONUS: Make it available for Entity API (Rules / Search API).
/**
* Implements hook_views_data_alter().
*
* Note: This hook is provided by Views.
*/
function MY_MODULE_views_data_alter(&$data){
// Entity API seems to add a handler, but at a different place.
$data['node']['phone'] = $data['entity_node']['phone'];
}
BONUS: Make it available for Views.
Problem
Daten sollen vor dem Indizieren verändert werden, zB bestimmte Nodes sollen nicht indiziert werden.
Lösung
1 hook und 1 Plugin
/**
* Implements hook_search_api_alter_callback_info().
*/
function MYMODULE_search_api_alter_callback_info() {
$callbacks['callback_nid_filter'] = array(
'name' => t('NID filter'),
'description' => t('Exclude NIDs from being indexed.'),
'class' => 'SearchApiAlterNIDFilter',
'weight' => 100,
);
return $callbacks;
}
Definiere das neue Callback.
class SearchApiAlterNIDFilter extends SearchApiAbstractAlterCallback {
public function supportsIndex(SearchApiIndex $index) {
return $index->getEntityType() === 'node';
}
// Implement alterItems
public function alterItems(array &$items) {
$nids = array(41,52,102);
foreach($nids as $nid) {
if (isset($items[$nid])) {
unset($items[$nid]);
}
}
}
}
(version with config form on dropbucket.org)
files[] = includes/callback_nid_filter.inc
In MYMODULE.info
Problem
Menschen sollen ihre eigenen Kommentare löschen dürfen.
Lösung
Custom access callback für comment/%/delete
/**
* Implements hook_menu_alter().
*/
function MY_MODULE_menu_alter(&$items) {
$items['comment/%/delete']['access callback'] = 'MY_MODULE_comment_delete_access';
$items['comment/%/delete']['access arguments'] = array(1);
}
Change the access callback for the "delete comment" menu item.
function MY_MODULE_comment_delete_access($cid) {
global $user;
if (!user_is_logged_in()) {
return FALSE;
}
// Allow admin to delete any comments.
if (user_access('administer comments')){
return TRUE;
}
// Load the comment.
$comment = comment_load($cid);
// If user is comment author ..
if ($comment->uid == $user->uid) {
// .. check if comment mode for this node type is flat.
$node = node_load($comment->nid);
$comment_mode = variable_get('comment_default_mode_' . $node->type, COMMENT_MODE_THREADED);
if ($comment_mode == COMMENT_MODE_FLAT) {
// Comment mode is flat and user is author of the comment.
return TRUE;
}
}
return FALSE;
}
The new access callback for the "delete comment" menu item.
Kontakt: jenner@formundcode.de