Skip to content

Instantly share code, notes, and snippets.

@davereid
Last active September 29, 2015 07:18
Show Gist options
  • Star 15 You must be signed in to star a gist
  • Fork 1 You must be signed in to fork a gist
  • Save davereid/1566015 to your computer and use it in GitHub Desktop.
Save davereid/1566015 to your computer and use it in GitHub Desktop.
Useful D7 custom functions
<?php
/**
* @file
* Administration menu integration for the custom module.
*/
/**
* Implements hook_admin_menu_cache_info().
*/
function custom_admin_menu_cache_info() {
$caches['bootstrap'] = array(
'title' => t('Bootstrap'),
'callback' => 'custom_admin_menu_cache_flush_bootstrap',
);
$caches['entity'] = array(
'title' => t('Entity'),
'callback' => 'entity_info_cache_clear',
);
$caches['field'] = array(
'title' => t('Field'),
'callback' => 'field_cache_clear',
);
$caches['all'] = array(
'title' => t('ALL THE THINGS!'),
'callback' => 'drupal_flush_all_caches',
);
return $caches;
}
/**
* Cache callback to clear the bootstrap cache.
*/
function custom_admin_menu_cache_flush_bootstrap() {
cache_clear_all('*', 'cache_bootstrap', TRUE);
}
/**
* Implements hook_admin_menu_output_alter().
*/
function custom_admin_menu_output_alter(array &$content) {
// @todo Remove when http://drupal.org/node/1899474 is fixed.
unset($content['icon']['icon']['devel-variables']);
if (module_exists('devel')) {
$devel_tree = menu_tree_all_data('devel');
if ($devel_tree = admin_menu_links_menu($devel_tree)) {
$content['icon']['icon']['devel'] = array(
'#title' => t('Devel'),
'#href' => '#',
'#options' => array(
'external' => TRUE,
),
) + $devel_tree;
}
}
}
<?php
/**
* @file
* Block integration for the custom module.
*/
/**
* Implements hook_block_view().
*/
function custom_block_view($delta) {
$function = 'custom_block_view_' . strtr($delta, '-', '_');
if (function_exists($function)) {
return $function();
}
}
<?php
/**
* @file
* Drush integration for the custom module.
*/
/**
* Implements hook_drush_cache_clear().
*/
function custom_drush_cache_clear(&$types) {
if (drush_drupal_major_version() >= 7) {
$types['bootstrap'] = 'custom_drush_cache_clear_bootstrap';
// @todo Remove when http://drupal.org/node/1899468 is fixed.
if (drush_has_boostrapped(DRUSH_BOOTSTRAP_DRUPAL_FULL)) {
$types['entity'] = 'entity_info_cache_clear';
$types['field'] = 'field_cache_clear';
}
}
}
/**
* Clears the bootstrap cache.
*/
function custom_local_drush_cache_clear_bootstrap() {
cache_clear_all('*', 'cache_bootstrap', TRUE);
}
<?php
/**
* Implements hook_hook_info_alter().
*/
function custom_hook_info(&$info) {
// Add modulename.group.inc support for most core hooks.
$groups['block'] = array('block_configure', 'block_info', 'block_info_alter', 'block_list_alter', 'block_save', 'block_view', 'block_view_alter');
$groups['comment'] = array('comment_delete', 'comment_insert', 'comment_load', 'comment_presave', 'comment_publish', 'comment_unpublish', 'comment_update', 'comment_view', 'comment_view_alter');
$groups['cron'] = array('cron', 'cron_queue_info', 'cron_queue_info_alter');
$groups['date'] = array('date_formats', 'date_formats_alter', 'date_format_types', 'date_format_types_alter');
$groups['entity'] = array('entity_delete', 'entity_info', 'entity_info_alter', 'entity_insert', 'entity_load', 'entity_prepare_view', 'entity_presave', 'entity_query_alter', 'entity_update', 'entity_view' ,'entity_view_alter');
$groups['file'] = array('file_copy', 'file_delete', 'file_download', 'file_download_access', 'file_download_access_alter', 'file_insert', 'file_load', 'file_mimetype_mapping_alter', 'file_move', 'file_presave', 'file_update', 'file_url_alter', 'file_validate');
$groups['image'] = array('image_default_styles', 'image_effect_info', 'image_effect_info_alter', 'image_styles_alter', 'image_style_delete', 'image_style_flush', 'image_style_save', 'image_toolkits');
// Contrib modules.
$groups['admin_menu'] = array('admin_menu_replacements', 'admin_menu_output_build', 'admin_menu_output_alter', 'admin_menu_map', 'admin_menu_map_alter', 'admin_menu_cache_info');
foreach ($groups as $group => $hooks) {
$info += array_fill_keys($hooks, array('group' => $group));
}
}
/**
* Implements hook_menu().
*/
function custom_menu() {
$items = array();
return $items;
}
/**
* Implements hook_menu_alter().
*/
function custom_menu_alter(&$items) {
// Make the delete page for nodes show up as a tab.
$items['node/%node/delete']['context'] = MENU_CONTEXT_PAGE | MENU_CONTEXT_INLINE;
}
/**
* Implements hook_node_view().
*/
function custom_node_view($node, $view_mode, $langcode) {
if (module_exists('comment') && $view_mode == 'teaser') {
_custom_node_add_unpublished_comments_link($node, $langcode);
}
}
function _custom_node_add_unpublished_comments_link($node, $langcode) {
if ($node->comment != COMMENT_NODE_HIDDEN && user_access('administer comments')) {
$unpublished_count = db_query('SELECT COUNT(cid) FROM {comment} WHERE nid = :nid AND status = :status', array(
':nid' => $node->nid,
':status' => COMMENT_NOT_PUBLISHED,
))->fetchField();
if (!empty($unpublished_count)) {
$node->content['links']['comment']['#links']['comment-unpublished-comments'] = array(
'title' => format_plural($unpublished_count, '1 unpublished comment', '@count unpublished comments', array(), array('langcode' => $langcode)),
'href' => "node/$node->nid",
'fragment' => 'comments',
);
}
}
}
/**
* Filter an array of node objects based if the results of node_access().
*/
function custom_array_filter_node_access(array $nodes, $op = 'view', $account = NULL) {
$return = array();
foreach ($nodes as $node) {
if (node_access($op, $node, $account)) {
$return[$node->nid] = $node;
}
}
return $return;
}
/**
* Returns a specific field value, column, and delta.
*
* @param $entity_type
* The type of $entity; e.g., 'node' or 'user'.
* @param $entity
* The entity containing the data to be displayed.
* @param $field_name
* The field to retrieve.
* @param $column
* The column in the field data to retrieve. Default is NULL which will
* return the entire field's data array.
* @param $delta
* The specific delta of the field values to return. Default is 0. If NULL is
* provided then all the field delta values will be returned.
*
* @return
* A field value, or an array of field values, or NULL if no field values
* were available.
*
* @see field_get_items()
* @see custom_array_extract_values()
*/
function custom_field_get_value($entity_type, $entity, $field_name, $column = NULL, $delta = 0) {
if (!empty($entity) && $items = field_get_items($entity_type, $entity, $field_name)) {
if (isset($column)) {
$items = custom_extract_nested_values_to_array($items, array($column));
}
if (isset($delta)) {
if (isset($items[$delta])) {
return $items[$delta];
}
}
else {
return $items;
}
}
}
/**
* Extract array values out from an array of field items.
*
* @param $entity_type
* The entity type
* @param $entity
* An entity object of type $entity_type.
* @param $field
* A field name.
* @param $key
* A key to pass into custom_array_extract_values().
*
* @return
* An array of field values.
*
* @see custom_array_extract_values()
* @see field_get_items()
*/
function custom_field_extract_values($entity_type, $entity, $field, $column) {
if (!empty($entity) && $items = field_get_items($entity_type, $entity, $field)) {
return custom_extract_nested_values_to_array($items, array($column));
}
return array();
}
/**
* Find the delta value of a field item's value.
*
* @param $entity_type
* The entity type
* @param $entity
* An entity object of type $entity_type.
* @param $field
* A field name.
* @param $column
* The column that should have its value compared to $value.
* @param $value
* The field value to compare to.
*
* @return
* The delta value of the field value if found, which can evaluate to zero.
* If the field value is not found, FALSE will be returned.
*/
function custom_field_get_value_delta($entity_type, $entity, $field, $column, $value) {
if (!empty($entity) && $items = field_get_items($entity_type, $entity, $field)) {
foreach ($items as $delta => $item) {
if (isset($item[$column]) && $item[$column] == $value) {
return $delta;
}
}
}
return FALSE;
}
/**
* Check if an entity's field has a specific delta value.
*
* @param $entity_type
* The entity type
* @param $entity
* An entity object of type $entity_type.
* @param $field
* A field name.
* @param $delta
* A delta value to check.
*
* @return bool
* TRUE is the entity's field has a value with the specific delta, or FALSE
* otherwise.
*/
function custom_field_has_delta($entity_type, $entity, $field, $delta) {
if (!empty($entity) && $items = field_get_items($entity_type, $entity, $field)) {
return !empty($items[$delta]);
}
}
/**
* Duplicate of field_view_value() that extracts $item automatically by delta.
*
* @see field_view_value()
*/
function custom_field_view_value($entity_type, $entity, $field_name, $delta = 0, $display = array(), $langcode = NULL) {
$output = array();
if ($item = custom_field_get_value($entity_type, $entity, $field_name, NULL, $delta)) {
// Determine the langcode that will be used by language fallback.
$langcode = field_language($entity_type, $entity, $field_name, $langcode);
// Push the item as the single value for the field, and defer to
// field_view_field() to build the render array for the whole field.
$clone = clone $entity;
$clone->{$field_name}[$langcode] = array($item);
$elements = field_view_field($entity_type, $clone, $field_name, $display, $langcode);
// Extract the part of the render array we need.
$output = isset($elements[0]) ? $elements[0] : array();
if (isset($elements['#access'])) {
$output['#access'] = $elements['#access'];
}
}
return $output;
}
/**
* Filter an array of objects or nested arrays by a variable depth value.
*
* @param array $items
* An array of objects or arrays to filter.
* @param array $parents
* An array of parent keys of the value, starting with the outermost key.
* @param mixed $value
* A value or array of values to match using custom_get_nested_value().
*
* @return array
* An array of items that matched nested value $value.
*/
function custom_filter_by_nested_value(array $items, array $parents, $value) {
$return = array();
foreach ($items as $key => $item) {
$key_exists = FALSE;
$found_value = custom_get_nested_value($item, $parents, $key_exists);
if ($key_exists) {
if (is_array($value) && in_array($found_value, $value)) {
$return[$key] = $item;
}
elseif ($found_value == $value) {
$return[$key] = $item;
}
}
}
return $return;
}
/**
* Retrieves a value from an object or nested array with variable depth.
*
* This is a copy of drupal_array_get_nested_value() but with added support
* for objects.
*
* @param mixed $item
* The array or object from which to get the value.
* @param array $parents
* An array of parent keys of the value, starting with the outermost key.
* @param bool $key_exists
* (optional) If given, an already defined variable that is altered by
* reference if all the keys in $parents were found.
*
* @return mixed
* The requested nested value. Possibly NULL if the value is NULL or not all
* nested parent keys exist. $key_exists is altered by reference and is a
* Boolean that indicates whether all nested parent keys exist (TRUE) or not
* (FALSE). This allows to distinguish between the two possibilities when
* NULL is returned.
*/
function custom_get_nested_value($item, array $parents, &$key_exists = NULL) {
$ref = $item;
foreach ($parents as $parent) {
if (is_array($ref) && array_key_exists($parent, $ref)) {
$ref = &$ref[$parent];
}
elseif (is_object($ref) && property_exists($ref, $parent)) {
$ref = $ref->$parent;
}
elseif (is_object($ref) && method_exists($ref, '__get') && $ref->__get($parent) !== NULL) {
// Support objects that override the __get magic method.
// This also doesn't support if $ref->$parent exists but is set to NULL.
$ref = $ref->$parent;
}
else {
$key_exists = FALSE;
return NULL;
}
}
$key_exists = TRUE;
return $ref;
}
/**
* Extract an associative key/value array from an array of arrays or objects.
*
* @param $items
* An array of objects or arrays.
* @param array $value_parents
* An array of parent keys of the value, starting with the outermost key.
* @param array $key_parents
* (optional) An array of parent keys of the key to return for each item,
* starting with the outermost key. If not provided, the key of the item in
* $items will be used as the returned key.
*/
function custom_extract_nested_values_to_array(array $items, array $value_parents, array $key_parents = NULL) {
$return = array();
foreach ($items as $index => $item) {
$key = isset($key_parents) ? custom_get_nested_value($item, $key_parents) : $index;
$return[$key] = custom_get_nested_value($item, $value_parents);
}
return $return;
}
/**
* Attempt to load the current node. This is useful for sites that use Panels for node pages.
*/
function custom_get_current_node($check_access = FALSE) {
$node = &drupal_static(__FUNCTION__);
if (!isset($node)) {
$node = FALSE;
if (preg_match('/node\/(\d+)/', current_path, $matches)) {
$node = node_load($matches[1]);
if ($check_access && !node_access('view', $node)) {
$node = FALSE;
}
}
}
return $node;
}
/**
* Add an array of classes to the body.
*
* @param $classes
* A string or an array of class strings to add.
*/
function custom_add_class($classes, $hook = 'body') {
if (!is_array($classes)) {
$classes = array($classes);
}
$static = &drupal_static('custom_classes', array());
if (!isset($static[$hook]['add'])) {
$static[$hook]['add'] = array();
}
foreach ($classes as $class) {
$static[$hook]['add'][] = $class;
}
}
/**
* Remove an array of classes from the body.
*
* @param $classes
* A string or an array of class strings to remove.
*/
function custom_remove_class($classes, $hook = 'body') {
if (!is_array($classes)) {
$classes = array($classes);
}
$static = &drupal_static('custom_classes', array());
if (!isset($static[$hook]['remove'])) {
$static[$hook]['remove'] = array();
}
foreach ($classes as $class) {
$static[$hook]['remove'][] = $class;
}
}
/**
* Implements hook_process()
*
* This essentially works like panels_preprocess_html().
*/
function custom_process(&$variables, $hook) {
if (!isset($variables['classes'])) {
return;
}
$classes = drupal_static('custom_classes', array());
if (!empty($classes[$hook]['add'])) {
$add_classes = array_map('drupal_clean_css_identifier', $classes[$hook]['add']);
$variables['classes_array'] = array_unique(array_merge($variables['classes_array'], $add_classes));
}
if (!empty($classes[$hook]['remove'])) {
$remove_classes = array_map('drupal_clean_css_identifier', $classes[$hook]['remove']);
$variables['classes_array'] = array_diff($variables['classes_array'], $remove_classes);
}
// Since this runs after template_process(), we need to re-implode the
// classes array.
$variables['classes'] = implode(' ', $variables['classes_array']);
}
/**
* Implements hook_ajax_render_alter().
*/
function custom_ajax_render_alter() {
// Disable XHProf module on any AJAX requests.
// @todo Remove when http://drupal.org/node/1485190 is fixed.
$GLOBALS['conf']['xhprof_enabled'] = FALSE;
}
/**
* A lightweight version of entity save for field values only.
*/
custom_entity_fields_update($entity_type, $entity) {
list($id) = entity_extract_ids($entity_type, $entity);
if (empty($id)) {
trigger_error('Cannot call custom_entity_fields_update() on a new entity.');
return FALSE;
}
// Some modules use the original property.
if (!isset($entity->original)) {
$entity->original = $entity;
}
// Ensure that file_field_update() will not trigger additional usage.
unset($entity->revision);
// Invoke the field presave and update hooks.
field_attach_presave($entity_type, $entity);
field_attach_update($entity_type, $entity);
// Clear the cache for this entity now.
entity_get_controller($entity_type)->resetCache(array($id));
}
function custom_get_fields_by_type($type) {
$fields = array();
foreach (field_info_field_map() as $field_name => $field_map) {
if ($field_map['type'] == $type) {
$fields[$field_name] = field_info_field($field_name);
}
}
return $fields;
}
@davereid
Copy link
Author

FYI I've taken all the reusable API functions and wrapped them up into an updateable module called helper: http://drupal.org/project/helper. I will likely not be maintaining this gist anymore.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment