Skip to content

Instantly share code, notes, and snippets.

@Paulmicha
Last active July 8, 2019 15:37
Show Gist options
  • Star 1 You must be signed in to star a gist
  • Fork 1 You must be signed in to fork a gist
  • Save Paulmicha/5047447 to your computer and use it in GitHub Desktop.
Save Paulmicha/5047447 to your computer and use it in GitHub Desktop.
Drupal 7 API Notes

#Drupal 7 API snippets @author Paulmicha

<?php
/**
* Drupal 7 API snippet - Programmatically render blocks
*
* sources :
* http://www.only10types.com/2012/05/drupal-7-render-block-in-template-file.html
* http://drupal.stackexchange.com/questions/5775/programmatically-printing-a-block
* https://www.drupal.org/node/957038
*/
// ex : module_invoke('system', 'block_view', 'navigation');
$block = module_invoke('MODULE_NAME', 'block_view', 'BLOCK_ID');
$html = drupal_render($block);
// @see https://www.drupal.org/node/957038
// @see http://www.only10types.com/2012/05/drupal-7-render-block-in-template-file.html
$block = block_load($module, $block_id);
$block_content = _block_render_blocks(array($block));
$build = _block_get_renderable_array($block_content);
$block_rendered = drupal_render($build);
// One-liner example :
$html_output = drupal_render(_block_get_renderable_array(_block_render_blocks(array(block_load('block', '1')))));
// Custom blocks
$block = block_custom_block_get(1);
$content = $block['body'];
<?php
/**
* Drupal 7 API snippet - DB Queries
*
* Contents :
* 1. Basics
* 2. Joins
*
* Sources :
* https://drupal.org/node/310075
* https://drupal.org/node/1848348
* http://www.lullabot.com/blog/articles/simplify-your-code-drupal-7s-database-api
*/
/*
Performance note :
https://www.lullabot.com/blog/article/simplify-your-code-drupal-7s-database-api#comment-4530
As catch notes, the Select builder adds a LOT of overhead. You should not use it unless you need one of the things it offers: Dynamic query structure, hook_query_alter, certain db-unportable features that don't have a simpler version (random ordering, for instance), etc.
For the run of the mill SQL query, db_query() is several times faster than db_select(). If you need a limit query, db_query_range() is still there.
You must use the query builders for non-Select queries, because those are much harder to make portable due to stupidity in many older databases. (Oracle is worst, but Postgres is dumb in places, too.) The actual code you'd have to write for those is vastly different, so the query builders are a necessity. SELECT queries are far more standardized. db_query() is still your friend in many many cases.
Really, db_select() doesn't insulate you from as many db portability issues as you think. It doesn't do anything for SQL functions that differ between databases, doesn't help with date handling, etc. Its primary advantage is what Eaton talks about in this article: When your query structure may change depending on various conditions, it's now dead-simple to do so.
If your query will never change, don't waste the CPU cycles on it. Just write proper ANSI SQL in the first place and it will be sufficiently portable.
*/
//------------------------------------------------------------------------------------------------------------------------------------
// 1. Basics
// Let's say we want to create a dynamic query which is roughly equivalent to the following static query:
$result = db_query( "SELECT uid, name, status, created, access FROM {users} u WHERE uid <> 0 LIMIT 50 OFFSET 0" );
// The dynamic equivalent begins as follows:
// Create an object of type SelectQuery
$query = db_select( 'users', 'u' );
// Add extra detail to this query object: a condition, fields and a range
$query->condition( 'u.uid', 0, '<>' );
$query->fields( 'u', array( 'uid', 'name', 'status', 'created', 'access' ));
$query->range( 0, 50 );
// Shorthand (chaining) :
$query = db_select( 'users', 'u' )
->condition( 'u.uid', 0, '<>' )
->fields( 'u', array( 'uid', 'name', 'status', 'created', 'access' ))
->range( 0, 50 );
// Once the query is built, call the execute() method to compile and run the query.
$result = $query->execute();
foreach ( $result as $record )
{
// Do something with each $record
}
// Fetch :
$result_assoc_arr = $query->execute()->fetchAssoc();
// Fetch subset :
$result_assoc_arr = $query->range( 0, 1 )->execute()->fetchAssoc()
//------------------------------------------------------------------------------------------------------------------------------------
// 2. Joins
// To join against another table, use the join(), innerJoin(), leftJoin(), or rightJoin() methods, like so:
$query = db_select( 'node', 'n' );
$table_alias = $query->join( 'users', 'u', 'n.uid = u.uid AND u.uid = :uid', array( ':uid' => 5 ));
// The above directive will add an INNER JOIN (the default join type) against the "user" table, which will get an alias of "u".
// The join will be ON the condition " n.uid = u.uid AND u.uid = :uid", where :uid has a value of 5.
// Note the use of a prepared statement fragment. That allows for the addition of variable join statements in a secure fashion.
// The return value of a join method is the alias of the table that was assigned.
// If an alias is specified it will be used except in the rare case that alias is
// Note that in place of a literal such as 'user' for the table name, all of the join methods will accept a select query as their first argument.
// Example:
$query = db_select( 'node', 'n' );
$myselect = db_select( 'mytable' )
->fields( 'mytable' )
->condition( 'myfield', 'myvalue' );
$alias = $query->join( $myselect, 'myalias', 'n.nid = myalias.nid' );
// Joins cannot be chained, so they have to be called separately (see Chaining). If you are chaining multiple functions together do it like this:
$query = db_select( 'node', 'n' );
$query->join( 'field_data_body', 'b', 'n.nid = b.entity_id' );
$query
->fields( 'n', array( 'nid', 'title' ))
->condition( 'n.type', 'page' )
->condition( 'n.status', '1' )
->orderBy( 'n.created', 'DESC' )
->addTag( 'node_access' );
?>
<?php
/**
* Drupal 7 API snippet - Assets management snippets
*/
// Add inline JS in footer
drupal_add_js( $js_str, array( 'type' => 'inline', 'scope' => 'footer', 'weight' => 0 ));
// Add inline CSS
drupal_add_css( $css_str, array( 'type' => 'inline' ));
?>
<?php
/**
* Drupal 7 API snippet - Entity Metadata Wrappers
*
* Sources :
* https://www.drupal.org/documentation/entity-metadata-wrappers
* http://www.pixelite.co.nz/article/how-use-entity-metadata-wrappers-drupal-7
* http://www.mediacurrent.com/blog/entity-metadata-wrapper
*/
//------------------------------------------------------------
// Init
// Unnecessary node load
$node = node_load($nid);
$wrapper = entity_metadata_wrapper('node', $node);
// More efficient (if the object isn't handed to you)
$wrapper = entity_metadata_wrapper('node', $nid);
//------------------------------------------------------------
// Fetch
// Any value
$node_wrapper->field_foobar->value();
$first_name = $wrapper->field_tags[0]->name->value();
// Unified way of getting $node->title, $user->name, ...
$wrapper->label();
// Unified way of getting $node->nid, $user->uid, ...
$wrapper->getIdentifier();
// Unified way of getting $node->type, ...
$wrapper->getBundle();
// Meta
$mail_info = $wrapper->author->mail->info();
// Other examples
$wrapper->body->raw();
$wrapper->title->value(array('sanitize' => TRUE));
$wrapper->body->value->value(array('decode' => TRUE));
//------------------------------------------------------------
// Iterate with "auto" Chaining
foreach ($wrapper->field_taxonomy_terms->getIterator() as $delta => $term_wrapper)
{
// $term_wrapper may now be accessed as a taxonomy term wrapper.
$label = $term_wrapper->label->value();
}
//------------------------------------------------------------
// Create / Update / Delete
// Set
$wrapper->author->mail = 'sepp@example.com';
// Set several values at once
$nids_to_set = array(42, 23);
$w_containing_node->field_entity_reference_field->set($nids_to_set);
// Appending
$w_containing_node->field_entity_reference_field[] = 42;
$w_containing_node->field_entity_reference_field[] = 23;
// Remove value
$wrapper->field_foobar = NULL;
// or just 1 vlue of a multi-valued field :
unset($wrapper->field_data[$delta]);
// Field Collection : setHostEntity()
$collection = entity_create('field_collection_item', array('field_name' => 'field_facilities_requested'));
$collection->setHostEntity('node', $node);
// Save changes to entity
$wrapper->save();
// Delete entity
$wrapper->delete();
//------------------------------------------------------------
// Error handling
try {
$node_wrapper = entity_metadata_wrapper('node', $node);
$price = $node_wrapper->field_product->field_price->value();
}
catch (EntityMetadataWrapperException $exc) {
watchdog(
'MODULE_NAME',
'See ' . __FUNCTION__ . '() <pre>' . $exc->getTraceAsString() . '</pre>',
NULL, WATCHDOG_ERROR
);
}
<?php
/**
* Drupal 7 helper functions for Entity Reference fields
*
* @evol 2013/06/28 15:18:39 - rewrite those for handling any entities
*
* @author Paulmicha
*/
/**
* Get nodes referring to a given nid through a given entity reference field
*/
function get_referencing_content( $nid, $field_entity_ref )
{
$return = array();
$safe_field_name = preg_replace( '`[^a-z_]`', '', $field_entity_ref );
if ( !empty( $nid ) && !empty( $safe_field_name ))
{
$query = "SELECT node.title AS node_title, node.nid AS nid, node.created AS node_created
FROM {node} node
LEFT JOIN {field_data_$safe_field_name} field_data_$safe_field_name ON node.nid = field_data_$safe_field_name.entity_id AND ( field_data_$safe_field_name.entity_type = 'node' AND field_data_$safe_field_name.deleted = '0' )
INNER JOIN {node} node_field_data_$safe_field_name ON field_data_$safe_field_name.". $safe_field_name ."_target_id = node_field_data_$safe_field_name.nid
WHERE node_field_data_$safe_field_name.nid = :nid
ORDER BY node_created DESC";
$result = db_query( $query, array( ':nid' => $nid ));
foreach( $result as $record )
$return[ $record->nid ] = $record->node_title;
}
return $return;
}
/**
* Get nodes referring to a given nid through a given entity reference field, filtered by node type
*/
function get_referencing_content_by_type( $nid, $field_entity_ref, $type )
{
$return = array();
$safe_field_name = preg_replace( '`[^a-z_]`', '', $field_entity_ref );
if ( !empty( $nid ) && !empty( $safe_field_name ))
{
$query = "SELECT node.title AS node_title, node.nid AS nid, node.created AS node_created
FROM {node} node
LEFT JOIN {field_data_$safe_field_name} field_data_$safe_field_name ON node.nid = field_data_$safe_field_name.entity_id AND ( field_data_$safe_field_name.entity_type = 'node' AND field_data_$safe_field_name.deleted = '0' )
INNER JOIN {node} node_field_data_$safe_field_name ON field_data_$safe_field_name.". $safe_field_name ."_target_id = node_field_data_$safe_field_name.nid
WHERE node_field_data_$safe_field_name.nid = :nid
AND node.type = :node_type
ORDER BY node_created DESC";
$result = db_query( $query, array( ':nid' => $nid, ':node_type' => $type ));
foreach( $result as $record )
$return[ $record->nid ] = $record->node_title;
}
return $return;
}
<?php
/**
* Drupal 7 API snippet - Field Formatters
* (How to add a custom formatter)
*/
/**
* Implement hook_field_formatter_info()
* Declare custom formatter
*/
function MY_MODULE_field_formatter_info()
{
return array(
'my_formatter_name' => array(
'label' => "My formatter label",
'field types' => array( 'file' ),
),
);
}
/**
* Implement hook_field_formatter_prepare_view()
* (optional) preprocess-like stuff
*
* Official doc :
* Allow formatters to load information for field values being displayed.
* This should be used when a formatter needs to load additional information
* from the database in order to render a field, for example a reference
* field which displays properties of the referenced entities such as name or type.
*
* @see https://api.drupal.org/api/drupal/modules!field!field.api.php/function/hook_field_formatter_prepare_view/7
*/
function MY_MODULE_field_formatter_prepare_view( $entity_type, $entities, $field, $instances, $langcode, &$items, $displays )
{
/*
Parameters documentation :
$entity_type: The type of $entity.
$entities: Array of entities being displayed, keyed by entity ID.
$field: The field structure for the operation.
$instances: Array of instance structures for $field for each entity, keyed by entity ID.
$langcode: The language the field values are to be shown in. If no language is provided the current language is used.
$items: Array of field values for the entities, keyed by entity ID.
$displays: Array of display settings to use for each entity, keyed by entity ID.
*/
// Basic Ex.
if ( !empty( $entities ))
foreach( $entities as $eid => $entity )
if ( !empty( $displays[ $eid ][ 'type' ]))
switch( $displays[ $eid ][ 'type' ])
{
case 'my_formatter_name' :
//...
break;
}
}
/**
* Implement hook_field_formatter_view()
*
* Produce the actual renderable array for the $items, as an array of child elements
* keyed by numeric indexes starting from 0
*
* @see https://api.drupal.org/api/drupal/modules!field!field.api.php/function/hook_field_formatter_view/7
*/
function MY_MODULE_field_formatter_view( $entity_type, $entity, $field, $instance, $langcode, $items, $display )
{
switch( $display[ 'type' ])
{
case 'my_formatter_name' :
// Basic Ex.
$renderable_element_0 = array();
$renderable_element_0['#markup'] = '<p>hello world</p>';
$render_array = array();
$render_array[] = $renderable_element_0;
return $render_array;
default :
return array();
}
}
<?php
/**
* Drupal 7 API snippet - Rendering fields the proper way
*
* Source :
* http://www.computerminds.co.uk/articles/rendering-drupal-7-fields-right-way
*/
// Shortcut - Term entity ex.
$term = taxonomy_term_load( $tid );
$field_images_items = field_get_items( 'taxonomy_term', $term, 'field_images' );
$field_sub_title_item = @reset( field_get_items( 'taxonomy_term', $term, 'field_sub_title' ));
// Shortcut - Node entity ex.
$node = menu_get_object();
$field_images_items = field_get_items( 'node', $node, 'field_images' );
$field_sub_title_item = @reset( field_get_items( 'node', $node, 'field_sub_title' ));
// 1. When you want to render a single field value
$field = field_get_items( 'node', $node, 'field_name' );
$output = field_view_value( 'node', $node, 'field_name', $field[ $delta ]);
// 2. Get sanitised rendered field in the current language in render-array form
$field = field_view_field( 'node', $node, 'field_name' );
// Shortcut
$field = @reset( field_get_items( 'user', $account, 'field_name' ));
// $field will be an array with the following keys : #theme, #weight, #title, #access, #label_display, #view_mode, #language, #field_name, #field_type, #field_translatable, #entity_type, #bundle, #object, #items, #formatter, 0
// where #items will have the values
// ex: $field[ '#items' ][ 0 ][ 'whatever_field_data' ]
// Note : http://stackoverflow.com/questions/11694770/print-drupal-field-view-field-value-only
// field_view_value() takes a $display argument that you can use to hide the label:
$display = array( 'label' => 'hidden' );
$view = field_view_field( 'node', $node, 'field_description', $display );
print drupal_render( $view );
// If you just want to extract the raw value of the field you can use field_get_items() instead:
$items = field_get_items( 'node', $node, 'field_description' );
$first_item = array_shift( $items );
$description = $first_item[ 'value' ];
// The column name ($first_item[ 'whatever' ]) will depend on the type of field you're using. For text fields it will be value. Remember to sanitise the input with check_plain() before you output it as Drupal's convention is to store the raw input data and sanitise it upon output.
?>
<?php
/**
* Drupal 7 API snippet - Programmatically creating files
* @todo 2013/04/23 15:29:45 - write sole file entity creation + document stream wrapper / remite file
*
* source : http://stackoverflow.com/questions/5129559/attaching-files-to-nodes-programmatically-in-drupal-7
* source : http://eosrei.net/articles/2012/11/programmatically-creating-nodes-using-entity-wrapper
*/
// Init node
$e = entity_create( 'node', array( 'type' => 'image' ));
$entity = entity_metadata_wrapper( 'node', $e );
$entity->uid = $user->uid;
$entity->title = 'Test node';
// Prepare image
$filepath = drupal_realpath( 'misc/druplicon.png' );
$file = (object) array(
'uid' => 1,
'uri' => $filepath,
'filemime' => file_get_mimetype( $filepath ),
'status' => 1,
);
$file = file_copy( $file, 'public://' );
$entity->field_image[ LANGUAGE_NONE ][ 0 ] = (array) $file;
// Save node with image
$entity->save();
<?php
/**
* Drupal 7 API snippet - File entity
*/
// Find the image style corresponding to a certain 'view_mode'
// For example, the one configured in :
// admin/structure/file-types/manage/image/file-display/preview
// @see file_entity_file_display_form() in module 'file_entity' -> file_entity.admin.inc
$file_type = 'image';
$view_mode = 'teaser';
$formatters = file_info_formatter_types();
foreach ( $formatters as $name => $formatter ) {
if ( isset( $formatter[ 'file types' ]) && !in_array( $file_type, $formatter[ 'file types' ])) {
unset( $formatters[ $name ]);
}
}
$current_displays = file_displays_load( $file_type, $view_mode, TRUE );
foreach ( $current_displays as $name => $display ) {
$current_displays[ $name ] = (array) $display;
}
// The style is in :
$my_image_style = $current_displays[ 'file_image' ][ 'settings' ][ 'image_style' ];
// debug
//dsm( '$formatters' );
//dsm( $formatters );
//dsm( '$current_displays' );
//dsm( $current_displays );
images/[current-date:custom:Y]/[current-date:custom:m]
images/[current-date:custom:Y]/[current-date:custom:m]/[current-date:custom:d]
documents/[current-date:custom:Y]/[current-date:custom:m]
videos/[current-date:custom:Y]/[current-date:custom:m]
videos-thumbnails/[current-date:custom:Y]/[current-date:custom:m]
Extensions images :
png gif jpg jpeg
Extensions common media :
aif art avi bmp gif ico jpg mov mp3 mp4 mpg oga ogv png psd ra ram rgb tif
Extensions media :
jpg jpeg gif png ico txt rtf doc docx xls xlsx pdf ppt pptx pps ppsx odt ods odp mp3 mov mp4 m4a m4v mpeg avi ogg oga ogv wmv
Extensions common documents :
pdf txt rtf md doc docx xls xlsx ppt pptx
Extensions MS Office :
xdoc dot xlb xlt
Extensions OpenOffice/StarOffice documents :
sxc stc sxd std sxi sti sxm sxw sxg stw
Extensions OpenDocument format documents :
odt ods odp odg odc odf odb odi odm ott ots otp otg otc otf oti oth
Extensions Apple :
pages key numbers
Extensions PostScript :
ps eps
<?php
/**
* Drupal 7 API snippet - Gotchas : PostGreSQL
* Tested on Debian 6 "Squeeze", Drupal 7.22
*/
//------------------------------------------------------------------------------------------------------------------------------------------------
// Hardcoded MySQL function in path.inc
// @see http://drupal.org/node/1791366
// Symptom :
// PDOException: SQLSTATE[42883]: Undefined function: 7 ERROR: function substring_index(character varying, unknown, integer) does not exist
// LINE 1: SELECT DISTINCT SUBSTRING_INDEX(source, '/', 1) AS path FROM...
// HINT: No function matches the given name and argument types. You might need to add explicit type casts.: SELECT DISTINCT SUBSTRING_INDEX(source, '/', 1) AS path FROM {url_alias};
// in drupal_path_alias_whitelist_rebuild() (line 380 of includes/path.inc).
// Solution :
// hack includes/path.inc @ line 380
// -> replace :
$result = db_query("SELECT DISTINCT SUBSTRING_INDEX(source, '/', 1) AS path FROM {url_alias}");
// -> with :
$result = db_query("SELECT DISTINCT my_schema_name.SUBSTRING_INDEX(source, '/', 1) AS path FROM {url_alias}");
<?php
/**
* Drupal 7 API snippet - Programmatically render images, with or without "style" (d7 version of imagecache):
*
* Source : http://www.drupalfoo.com/drupal-7-programatically-display-image-field-img-tag-fid
*/
// Different scenario, same code.
$langcode = LANGUAGE_NONE; // for demo
$photo_node = node_load( $item[ 'target_id' ]);
if ( !empty( $photo_node->field_image[ $langcode ][ 0 ][ 'fid' ]))
{
$file = file_load( $photo_node->field_image[ $langcode ][ 0 ][ 'fid' ]);
// This is how to get absolute URLs if needed :
$raw_image_url = file_create_url( $file->uri );
$medium_image_url = image_style_url( 'medium', $file->uri );
// Normal theming
$options = array( 'path' => $file->uri );
if ( !empty( $file->field_file_image_alt_text[ $langcode ][ 0 ][ 'safe_value' ]))
$options[ 'alt' ] = $file->field_file_image_alt_text[ $langcode ][ 0 ][ 'safe_value' ];
if ( !empty( $file->field_file_image_title_text[ $langcode ][ 0 ][ 'safe_value' ]))
$options[ 'title' ] = $file->field_file_image_title_text[ $langcode ][ 0 ][ 'safe_value' ];
if ( !empty( $file->image_dimensions[ 'width' ]) && is_numeric( $file->image_dimensions[ 'width' ]))
$options[ 'width' ] = $file->image_dimensions[ 'width' ];
if ( !empty( $file->image_dimensions[ 'height' ]) && is_numeric( $file->image_dimensions[ 'height' ]))
$options[ 'height' ] = $file->image_dimensions[ 'height' ];
// Raw image
$rendered_image_html = theme( 'image', $options );
// Image style
$options[ 'style_name' ] = 'medium';
$rendered_image_html = theme( 'image_style', $options );
}
// Using file entity (file type = image)
//$entity = @reset( entity_load( 'file', array( $entity_id )));
// Equivalent :
$entity = file_load( $fid );
if ( !empty( $entity->uri ))
{
$lang = LANGUAGE_NONE;
$options = array( 'path' => $entity->uri );
if ( !empty( $entity->field_file_image_alt_text[ $lang ][ 0 ][ 'safe_value' ]))
$options[ 'alt' ] = $entity->field_file_image_alt_text[ $lang ][ 0 ][ 'safe_value' ];
if ( !empty( $entity->field_file_image_title_text[ $lang ][ 0 ][ 'safe_value' ]))
$options[ 'title' ] = $entity->field_file_image_title_text[ $lang ][ 0 ][ 'safe_value' ];
if ( !empty( $entity->image_dimensions[ 'width' ]) && is_numeric( $entity->image_dimensions[ 'width' ]))
$options[ 'width' ] = $entity->image_dimensions[ 'width' ];
if ( !empty( $entity->image_dimensions[ 'height' ]) && is_numeric( $entity->image_dimensions[ 'height' ]))
$options[ 'height' ] = $entity->image_dimensions[ 'height' ];
// Raw image :
print theme( 'image', $options );
// If we wanted to use an image style :
$options[ 'style_name' ] = 'my_image_style';
print theme( 'image_style', $options );
}
// Raw DB fetch example
// @see http://www.drupalfoo.com/drupal-7-programatically-display-image-field-img-tag-fid
$out = '';
$img = db_query( "SELECT a.title, b.field_image_fid AS fid, b.field_image_width AS width, b.field_image_height AS height FROM node a LEFT OUTER JOIN field_data_field_image b ON a.nid = b.entity_id WHERE a.type = 'mynodetype' AND a.status = 1 ORDER BY RAND() LIMIT 1" )->fetchObject();
if ( $img )
{
// for displaying the original image
$out = theme( 'image', array( 'path' => file_load( $img->fid )->uri, 'width' => $img->width, 'height' => $img->height, 'alt' => t( $img->title )));
// for displaying a styled image
$out = theme( 'image_style', array( 'path' => file_load( $img->fid )->uri, 'alt' => t( $img->title ), 'style_name' => 'my_image_style' ));
}
print $out;
<?php
/**
* Drupal 7 API snippet - Menu (routing) related snippets
*
* @see hook_menu()
* @see hook_menu_alter()
* @see hook_menu_link_alter()
* @see page_example
* @see page_example_menu()
*/
// @see https://api.drupal.org/api/drupal/includes!bootstrap.inc/function/request_uri/7
$GLOBALS['base_url'] => http://example.com/drupal
base_path() => /drupal/
request_uri() => /drupal/documentation?page=1
request_path() => documentation
current_path() => node/26419
<?php
/**
* Drupal 7 API snippet - Programmatically render menus
*
* sources :
* http://drupal.org/node/1812252
*/
$html = drupal_render( menu_tree_output( menu_tree_all_data( 'your-menu-name' )));
<?php
/**
* Drupal 7 API snippet - Programmatically creating nodes using Entity Wrapper
*
* source : http://eosrei.net/articles/2012/11/programmatically-creating-nodes-using-entity-wrapper
*/
// Create an Entity
$e = entity_create( 'node', array( 'type' => 'image' ));
// Create a Entity Wrapper of that new Entity
$entity = entity_metadata_wrapper( 'node', $e );
// Specify the author
$entity->uid = $user->uid;
$entity->title = 'Test node';
// Add field data
$entity->field_text_field = 'Field value text';
// Save the node.
$entity->save();
//------------------------------------------------------------------------
// The Old Fashioned way
// Create a new node
$node = new stdClass();
// Set the content type
$node->type = 'image';
// Add default values
node_object_prepare( $node );
// Set the language
$node->language = LANGUAGE_NONE;
// Specify the author
$node->uid = $user->uid;
// Create textfield formatted data array
$data = array(
array(
'value' => 'Field value text',
'format' => 'plain_text',
)
);
$field_name = 'field_text_field';
// Locate the field's language
$langcode = field_language( 'node', $node, $field_name, NULL );
// Set the value
$node->{$field_name}[ $langcode ] = $value;
$node->title = 'Test node';
// Save the node.
node_save( $node );
?>
<?php
/**
* Drupal 7 snippets - Organic Groups helpers
*
* @author Paulmicha
*/
/**
* Helper function
* Detect nodes in a group in which the user doesn't belong (= isn't a member)
*/
function _node_belongs_to_user_groups( $node, $account = null )
{
// Support current user by default
if ( !$account )
{
global $user;
$account = $user;
}
// If there's at least 1 group referred by the node in which the user isn't a member, it's a fail.
// @evol 2013/03/01 17:06:37 - support softer test - only private groups result in a fail ?
$node_groups = og_get_entity_groups( 'node', $node );
if ( !empty( $node_groups[ 'node' ]))
foreach( $node_groups[ 'node' ] as $gid )
if ( !og_is_member( 'node', $gid, 'user', $account ))
return false;
// Don't care if we got this far
return true;
}
<?php
/**
* Drupal 7 API snippet - Panels related stuff
*
* Source :
* http://codekarate.com/blog/embed-panel-node-view-code
*/
//-----------------------------------------------------------------------------
// Render "panelized" node manually
$nid = 1;
$output = "";
$node = node_load($nid);
// Get the node_view task.
$task = page_manager_get_task('node_view');
// Load the node into a context.
ctools_include('context');
ctools_include('context-task-handler');
// Load the node context.
$contexts = ctools_context_handler_get_task_contexts($task, '', array($node));
// Render the node output.
$output = ctools_context_handler_render($task, '', $contexts, array($node->nid));
<?php
/**
* Drupal 7 API snippet - Recover Admin Password
* Tested on Debian 6 "Squeeze"
*
* Sources :
* https://drupal.org/node/1023428
* http://randyfay.com/content/resetting-drupal-passwords-drupal-7-drush-or-without
*/
// With SSH
// @see https://drupal.org/node/1023428
cd /var/www/my/drupal7/root
./scripts/password-hash.sh newpwd
// With Drush
// @see http://randyfay.com/content/resetting-drupal-passwords-drupal-7-drush-or-without
# Get an admin login link
drush uli
# Set the password for any user
drush upwd admin --password="newpassword"
// English
a,an,as,at,before,but,by,for,from,is,in,into,like,of,off,on,onto,per,since,than,the,this,that,to,up,via,with
// French
alors,au,aux,aussi,autre,avec,car,ce,cela,celui,celle,ces,ceux,chaque,chez,ci,comme,comment,dans,des,du,de,dedans,dehors,depuis,donc,dos,elle,elles,en,encore,entre,es,est,et,etaient,etions,etre,eu,ete,fait,fais,faites,font,hors,ici,il,ils,je,juste,la,le,les,leur,la,lors,ma,maintenant,mais,mes,moins,mon,meme,ni,notre,nos,nous,ou,ou,par,parce,pas,peut,peu,plupart,pour,pourquoi,quand,que,quel,quelle,quelles,quels,qui,sa,sans,ses,seulement,si,sien,sienne,siens,siennes,son,sont,sous,soyez,sur,ta,tandis,tellement,tels,tes,ton,tous,tout,toute,toutes,trop,tres,tu,un,une,vont,votre,vos,vous,ca,c,j,l,d,t,m,n,y,s,qu
// French + English
a,an,as,at,before,but,by,for,from,is,in,into,like,of,off,on,onto,per,since,than,the,this,that,to,up,via,with,alors,au,aux,aussi,autre,avec,car,ce,cela,celui,celle,ces,ceux,chaque,chez,ci,comme,comment,dans,des,du,de,dedans,dehors,depuis,donc,dos,elle,elles,en,encore,entre,es,est,et,etaient,etions,etre,eu,ete,fait,fais,faites,font,hors,ici,il,ils,je,juste,la,le,les,leur,la,lors,ma,maintenant,mais,mes,moins,mon,meme,ni,notre,nos,nous,ou,ou,par,parce,pas,peut,peu,plupart,pour,pourquoi,quand,que,quel,quelle,quelles,quels,qui,sa,sans,ses,seulement,si,sien,sienne,siens,siennes,son,sont,sous,soyez,sur,ta,tandis,tellement,tels,tes,ton,tous,tout,toute,toutes,trop,tres,tu,un,une,vont,votre,vos,vous,ca,c,j,l,d,t,m,n,y,s,qu
// Tokens quick copy/paste
[node:content-type]/[node:title]
[current-date:custom:Y]/[current-date:custom:m]/[node:title]
// admin/config/search/path/settings
// (console)
jQuery("#edit-punctuation select").val(1);
/**
* Drupal 7 API Notes : Theming - template suggestions cheatsheet
* @see https://drupal.org/node/1089656
*/
Drupal 7 Template (Theme Hook) Suggestions
Last updated April 1, 2014. Created by Carolyn on March 11, 2011.
Edited by gisle, Heihachi88, rooby, polishyourimage. Log in to edit this page.
A theme hook suggestions is an alternate template (.tpl.php) file that you have created to override the base or original template file.
Custom Theme Hook Suggestions
Custom suggestions beyond the ones listed below can be created. See the page Working with template suggestions.
Default Theme Hook Suggestions in Core
block--[region|[module|--delta]].tpl.php
base template: block.tpl.php
Theme hook suggestions are made based on these factors, listed from the most specific template to the least. Drupal will use the most specific template it finds:
block--module--delta.tpl.php
block--module.tpl.php
block--region.tpl.php
"module" being the name of the module and "delta", the internal id assigned to the block by the module.
For example, "block--block--1.tpl.php" would be used for the first user-submitted block added from the block administration screen since it was created by the block module with the id of 1. "region" will take effect for specific regions. An example of a region-specific template would be "block--sidebar_first.tpl.php".
If you had a block created by a custom module called "custom" and a delta of "my-block", the theme hook suggestion would be called "block--custom--my-block.tpl.php."
Also one more example with Views, if you have a block created by views with a view name "front_news" and display id "block_1" then the theme hook suggestion would be: block--views--front-news-block-1.tpl.php (notice, when you have underscores in a display id or in a view name - you have to transform them in to a single dash)
Be aware that module names are case sensitive in this context. For instance if your module is called 'MyModule', the most general theme hook suggestion for this module would be "block--MyModule.tpl.php."
comment--node-[type].tpl.php
base template: comment.tpl.php
Support was added to create comment--node-type.tpl.php files, to format comments of a certain node type differently than other comments in the site. For example, a comment made on an article-type node would be "comment--node-article.tpl.php".
comment-wrapper--node-[type].tpl.php
base template: comment-wrapper.tpl.php
Similar to the above but for the wrapper template.
field--[type|name[--content-type]|content-type].tpl.php
base template: field.tpl.php
Theme hook suggestions are made based on these factors, listed from the most specific template to the least. Drupal will use the most specific template it finds:
field--field-name--content-type.tpl.php
field--content-type.tpl.php
field--field-name.tpl.php
field--field-type.tpl.php
Note that underscores in a Field's machine name are replaced by hyphens. Also remember to include "field-" in custom field names, e.g: field--field-phone.tpl.php.
forums--[[container|topic]--forumID].tpl.php
base template: forums.tpl.php
Theme hook suggestions are made based on these factors, listed from the most specific template to the least. Drupal will use the most specific template it finds:
For forum containers:
forums--containers--forumID.tpl.php
forums--forumID.tpl.php
forums--containers.tpl.php
For forum topics:
forums--topics--forumID.tpl.php
forums--forumID.tpl.php
forums--topics.tpl.php
html.tpl.php
base template: html.tpl.php
The following are some examples of how you may override the base template:
html--internalviewpath.tpl.php
html--node--id.tpl.php
See html.tpl.php in the Drupal API documentation for more information.
maintenance-page--[offline].tpl.php
base template: maintenance-page.tpl.php
This applies when the database fails. Useful for presenting a friendlier page without error messages. Theming the maintenance page must be properly setup first.
node--[type|nodeid].tpl.php
base template: node.tpl.php
Theme hook suggestions are made based on these factors, listed from the most specific template to the least. Drupal will use the most specific template it finds:
node--nodeid.tpl.php
node--type.tpl.php
node.tpl.php
See node.tpl.php in the Drupal API documentation for more information.
page--[front|internal/path].tpl.php
base template: page.tpl.php
The suggestions are numerous. The one that takes precedence is for the front page. The rest are based on the internal path of the current page. Do not confuse the internal path to path aliases which are not accounted for. Keep in mind that the commonly-used Pathauto module uses path aliases.
The front page can be set at "Administration > Configuration > System > Site information." In Drupal 6, at "Administrator > Site configuration > Site information." Anything set there will trigger the suggestion of "page--front.tpl.php" for it.
The list of suggested template files is in order of specificity based on internal paths. One suggestion is made for every element of the current path, though numeric elements are not carried to subsequent suggestions. For example, "http://www.example.com/node/1/edit" would result in the following suggestions:
page--node--edit.tpl.php
page--node--1.tpl.php
page--node.tpl.php
page.tpl.php
Also see page.tpl.php in the Drupal API documentation for more information.
How Drupal determines page theme hook suggestions based on path
Here is another explanation based on the theme_get_suggestions() function:
The list of possible templates for a given page is generated by Drupal through the theme_get_suggestions() function, which is called by the template_preprocess_page() function.
The Drupal path of the page is first broken up into its components. As mentioned above, the Drupal path is not any of its aliases: there is one and only one Drupal path for a page. For the examples "http://www.example.com/node/1/edit" and "http://www.example.com/mysitename?q=node/1/edit", the Drupal path is node/1/edit, and its components are "node", 1, and "edit".
Next, the prefix is set to "page". Then, for every component, the following logic is followed:
If the component is a number, add the prefix plus "__%" to the list of suggestions.
Regardless of whether the component is a number or not, add the prefix plus "__" plus the component to the list of suggestions.
If the component is not a number, append "__" plus the component to the prefix.
After the list of components is iterated through, if the page is the front page (as set through "Administration > Configuration > System > Site information."), then "page__front" is added to the list of suggestions.
Note that eventually, to turn a suggestion into an actual file name, "__" gets turned into "--", and ".tpl.php" gets appended to the suggestion. Thus, for node/1/edit, we get the following list of suggestions:
page.tpl.php (this is always a suggestion)
page--node.tpl.php (and prefix is set to page__node)
page--node--%.tpl.php
page--node--1.tpl.php (prefix is not changed because the component is a number)
page--node--edit.tpl.php (and prefix is set to page__node__edit)
page--front.tpl.php (but only if node/1/edit is the front page)
When the page is actually rendered, the last suggestion is checked. If it exists, that suggestion is used. Otherwise the next suggestion up is checked, and so on. Of course, if none of the overriding suggestions exist, page.tpl.php is the final suggestion. This also explains why page--front.tpl.php, if it exists, overrides any other suggestion for the front page: it is always the last suggestion for the page designated as the front page.
poll-results--[block].tpl.php
base template: poll-results.tpl.php
The theme function that generates poll results are shared for nodes and blocks. The default is to use it for nodes but a suggestion is made for rendering them inside block regions. This suggestion is used by default and the template file is located at "modules/poll/poll-results--block.tpl.php".
poll-vote--[block].tpl.php
base template: poll-vote.tpl.php
Similar to poll-results--[block].tpl.php but for generating the voting form. You must provide your own template for it to take effect.
poll-bar--[block].tpl.php
base template: poll-bar.tpl.php
Same as poll-vote--[block].tpl.php but for generating individual bars.
profile-wrapper--[field].tpl.php
base template: profile-wrapper.tpl.php
The profile wrapper template is used when browsing the member listings page. When browsing specific fields, a suggestion is made with the field name. For example, http://drupal.org/profile/country/Belgium would suggest "profile-wrapper--country.tpl.php".
region--[region].tpl.php
base template: region.tpl.php
The region template is used when a page region has content, either from the Block system or a function like hook_page_build(). Possible region names are determined by the theme's .info file.
search-results--[searchType].tpl.php
base template: search-results.tpl.php
search-results.tpl.php is the default wrapper for search results. Depending on type of search different suggestions are made. For example, "example.com/search/node/Search+Term" would result in "search-results--node.tpl.php" being used. Compare that with "example.com/search/user/bob" resulting in "search-results--user.tpl.php". Modules can extend search types adding more suggestions of their type.
search-result--[searchType].tpl.php
base template: search-result.tpl.php
The same as above but for individual search results.
taxonomy-term--[vocabulary-machine-name|tid].tpl.php
base template: taxonomy-term.tpl.php
Theme hook suggestions are made based on these factors, listed from the most specific template to the least. Drupal will use the most specific template it finds:
taxonomy-term--tid.tpl.php
taxonomy-term--vocabulary-machine-name.tpl.php
taxonomy-term.tpl.php
Note that underscores in a vocabulary's machine name are replaced by hyphens.
Add a page.tpl.php depending on content type.
In Drupal 7, you do this by having this code in the function THEME_preprocess_page (where THEME is the name of the theme) in the theme's template.php.
function THEME_preprocess_page(&$vars, $hook) {
if (isset($vars['node']->type)) {
// If the content type's machine name is "my_machine_name" the file
// name will be "page--my-machine-name.tpl.php".
$vars['theme_hook_suggestions'][] = 'page__' . $vars['node']->type;
}
}
Add the if-statement at the end if this function already exists in the theme's template.php, otherwise, add the functions.
/**
* Drupal 7 API Notes : Alter hooks available to themes
* @see http://drupal.org/node/254940#theme_alter
*/
Hooks that are used to alter content before being displayed on the page are now available to themes.
Some important ones to note are:
hook_page_alter
hook_form_alter
hook_js_alter
hook_css_alter
Note that although technically all of the alter hooks are exposed to the theme, only a given number of them will actually work due to the way the Drupal bootstrap works. If you need to use hook_menu_alter, for example, you'll have to use a module. These hooks can be exposed in template.php.
<?php
/**
* Drupal 7 API snippet - Views SQL debug snippets
*
* source : http://drupal.stackexchange.com/questions/29116/get-the-actual-query-executed-by-a-view
*/
// Get Views generated Query
// @see http://drupal.stackexchange.com/questions/29116/get-the-actual-query-executed-by-a-view
$view = views_get_view( 'view_id' );
$view->init_display();
$view->pre_execute();
$view->execute();
$query_str = dpq( $view->build_info[ 'query' ], true );
// Without devel :
$query = $view->build_info[ 'query' ];
$query->preExecute();
$sql = (string) $query;
$quoted = array();
$connection = Database::getConnection();
foreach ((array)$query->arguments() as $key => $val ) {
$quoted[ $key ] = $connection->quote( $val );
}
$query_str = strtr( $sql, $quoted );
<?php
/**
* Drupal 7 API snippet - Watchdog
*
* source : http://api.drupal.org/api/drupal/includes%21bootstrap.inc/function/watchdog/7
*/
watchdog( $type, $message, $variables = array(), $severity = WATCHDOG_NOTICE, $link = NULL );
// Snippets
watchdog( 'module_name', "", array());
watchdog( 'module_name', "", array(), WATCHDOG_ERROR );
watchdog( 'module_name', "", array(), WATCHDOG_WARNING );
watchdog( 'module_name', "", array(), WATCHDOG_DEBUG );
watchdog( 'module_name', "", array(), WATCHDOG_INFO );
// Parameters :
/**
$type: The category to which this message belongs. Can be any string, but the general practice is to use the name of the module calling watchdog().
$message: The message to store in the log. Keep $message translatable by not concatenating dynamic values into it! Variables in the message should be added by using placeholder strings alongside the variables argument to declare the value of the placeholders. See t() for documentation on how $message and $variables interact.
$variables: Array of variables to replace in the message on display or NULL if message is already translated or not possible to translate.
$severity: The severity of the message; one of the following values as defined in RFC 3164:
WATCHDOG_EMERGENCY: Emergency, system is unusable.
WATCHDOG_ALERT: Alert, action must be taken immediately.
WATCHDOG_CRITICAL: Critical conditions.
WATCHDOG_ERROR: Error conditions.
WATCHDOG_WARNING: Warning conditions.
WATCHDOG_NOTICE: (default) Normal but significant conditions.
WATCHDOG_INFO: Informational messages.
WATCHDOG_DEBUG: Debug-level messages.
$link: A link to associate with the message.
/**/
<?php
/**
* Drupal 7 API snippet - Workbench
*
* Sources :
* http://www.myplanetdigital.com/article/troubleshooting-workbench#wisdom
*/
/**
* Automatically fetch vid depending on context (tab) :
* view (published) - node/%nid,
* draft - node/%nid/draft,
* specific revision - node/%nid/revisions/%revision_id/view
*
* @see http://www.myplanetdigital.com/article/troubleshooting-workbench#wisdom
*/
function get_node_revision_by_context( $nid = NULL )
{
if ( arg( 0 ) == 'node' && $nid == NULL ) {
$nid = arg( 1 );
}
if ( is_numeric( $nid ))
{
$node = node_load( $nid );
if ( !empty( $node ))
{
// Getting vid on the node/%nid page
$vid = $node->vid;
if ( arg( 2 ) == 'draft' && isset( $node->workbench_moderation[ 'current' ]->vid ) && ( $node->vid != $node->workbench_moderation[ 'current' ]->vid ))
{
// Getting vid on the node/%nid/draft page
$vid = $node->workbench_moderation[ 'current' ]->vid;
}
else if ( arg( 2 ) == 'revisions' && is_numeric( arg( 3 )))
{
// Getting vid on the node/%nid/revisions/%revision_id/view page
$vid = arg( 3 );
}
}
return $vid;
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment