path_metatags.module in Path metatags 7
Provide core functions for path metatags module.
File
path_metatags.moduleView source
<?php
/**
* @file
* Provide core functions for path metatags module.
*/
/**
* Implements hook_html_head_alter().
*/
function path_metatags_html_head_alter(&$head_elements) {
// See if current page has metatags.
$metatags = path_metatags_load_variant(current_path());
if ($metatags) {
// Build metatags.
foreach ($metatags as $metatag => $metatag_data) {
if ($metatag != 'title') {
// Apply metatags as head element.
$head_meta[$metatag] = array(
'#type' => 'html_tag',
'#tag' => 'meta',
'#attributes' => array(
$metatag_data['group'] => $metatag,
'content' => $metatag_data['content'],
),
);
$build_meta[$metatag] = $metatag_data['group'];
}
}
// Search and remove duplicates in meta tags.
foreach ($head_elements as $name => $element) {
if (!isset($element['#tag']) || $element['#tag'] != 'meta') {
continue;
}
// Unset head element by its name.
if (isset($element['#name']) && isset($build_meta[$element['#name']])) {
unset($head_elements[$name]);
}
// Search for duplicates in element attributes.
if (isset($element['#attributes'])) {
foreach ($element['#attributes'] as $group => $value) {
if (!is_array($value) && !empty($build_meta[$value]) && $build_meta[$value] == $group) {
unset($head_elements[$name]);
}
}
}
}
if (!empty($head_meta)) {
// Add chance for other modules to alter header.
drupal_alter('path_metatags_view', $head_meta);
// Add meta information to site header.
$head_elements += $head_meta;
}
}
}
/**
* Implements hook_preprocess_html().
*/
function path_metatags_preprocess_html(&$vars) {
$metatags = path_metatags_load_variant(current_path());
if ($metatags && !empty($metatags['title']['content'])) {
$vars['head_title'] = check_plain($metatags['title']['content']);
}
}
/**
* Implements hook_ctools_plugin_directory().
*/
function path_metatags_ctools_plugin_directory($owner, $plugin_type) {
if ($owner == 'ctools') {
return 'plugins/' . $plugin_type;
}
}
/**
* Load metatags based on path and visibility settings.
*
* @param $path
* @return array|bool
*/
function path_metatags_load_variant($path) {
if (!$path) {
return FALSE;
}
// Select all variants matching current path.
$variants = path_metatags_load_by_path($path);
// Check if current path maches variant.
// When first variant is found - return it.
foreach ($variants as $metatags) {
// Replace placeholder in path with '*'.
// Example: 'node/%node/view' -> 'node/*/view'.
$matched_path = preg_replace("\n /\\/% # start with slash-percent\n [^\\/]+ # all symbols except for the slash\n /x", '/*', $metatags->path);
if (drupal_match_path($path, $matched_path)) {
// Load metatags' contexts from current path.
$contexts = path_metatags_get_contexts_from_arguments($metatags->arguments);
// If metatags contains broken context
// it means that unable to load context from URL.
if (isset($contexts['broken_context'])) {
continue;
}
// Check if metatags is accessable.
if (!empty($metatags->access)) {
$access = ctools_access($metatags->access, $contexts);
if (!$access) {
continue;
}
}
// Build suitable metatags variant.
return _path_metatags_build_metatags($metatags, $contexts);
}
}
return FALSE;
}
/**
*
* Build metatags navigation from loaded path metatags variant.
*
* @param $path_metatags
* Object with path metatags variant loaded from database.
* @param $contexts
* Ctools contexts from current URL.
* @return array
* Array with metatags.
*/
function _path_metatags_build_metatags($path_metatags, $contexts = array()) {
// Add hook_path_metatags_view() for other developers.
module_invoke_all('path_metatags_view', $path_metatags, $contexts);
// Add custom ctools context for site.
$site = new ctools_context('site');
$site->plugin = 'site';
$site->keyword = 'site';
$contexts['site'] = $site;
// Convert arguments from url to contexts.
if (!empty($contexts) && !empty($path_metatags->metatags_values)) {
foreach ($path_metatags->metatags_values as $key => $value) {
// Replace placeholders by current context values.
$path_metatags->metatags_values[$key] = ctools_context_keyword_substitute($value, array(), $contexts);
}
}
$build = array();
$metatags = path_metatags_load_metatags_list();
if (!empty($path_metatags->metatags)) {
foreach ($path_metatags->metatags as $i => $metatag) {
// Check if current metatag exists in list of metatags.
if (!empty($metatags[$metatag])) {
// Display metatag only if it has value.
if (!empty($path_metatags->metatags_values[$i])) {
$metatag_value = $path_metatags->metatags_values[$i];
// Remove all HTML tags if needed.
$remove_tags = variable_get('path_metatags_skip_tags', 1);
if ($remove_tags) {
$metatag_value = trim(strip_tags($metatag_value));
}
// If metatag value still exists add it to build array.
if (!empty($metatag_value)) {
// Information about metatag from hook_path_metatag_info().
$metatag_info = $metatags[$metatag];
// Build output with metatag information about current page.
$build[$metatag] = array(
'group' => $metatag_info['group'],
'content' => $metatag_value,
);
}
}
}
}
}
return $build;
}
/**
* Load list of metatags.
*
* @return array|mixed
*/
function path_metatags_load_metatags_list() {
$metatags = array();
foreach (module_implements('path_metatags_info') as $module) {
$metatags += call_user_func($module . '_path_metatags_info');
}
// Last chance for modules to alter metatags list.
drupal_alter('path_metatags_info', $metatags);
return $metatags;
}
/**
* Save path metatags.
*
* @param $path_metatags
* Object with path metatags data.
* @return int
* ID of inserted/updated path metatags.
*/
function path_metatags_save($path_metatags) {
ctools_include('export');
// Build array with full access data.
if (!empty($path_metatags->access) && !empty($path_metatags->logic)) {
$path_metatags->access['logic'] = $path_metatags->logic;
}
elseif (empty($path_metatags->access)) {
$path_metatags->access = array();
}
// Ctools will serialize data itself.
$path_metatags->data = array(
'metatags' => $path_metatags->metatags,
'metatags_values' => $path_metatags->metatags_values,
'translatable' => $path_metatags->translatable,
'arguments' => $path_metatags->arguments,
'access' => $path_metatags->access,
);
$save_result = ctools_export_crud_save('path_metatags', $path_metatags);
// FALSE means error while saving.
if ($save_result) {
// Remove data from ctools object cache table.
path_metatags_object_cache_clear($path_metatags->machine_name);
// Allow modules to know that path_metatags were saved.
$path_metatags->is_new = $save_result == SAVED_NEW;
module_invoke_all('path_metatags_save', $path_metatags);
cache_clear_all('path_metatags', 'cache', TRUE);
}
// Return saving result, SAVED_NEW or SAVED_UPDATED.
return $save_result;
}
/**
* Delete path metatag.
*
* @param $name
* Path metatag's name.
* @return void
*/
function path_metatags_delete($name) {
$path_metatags = path_metatags_load_by_name($name);
// Inform modules about deleting path_metatags.
module_invoke_all('path_metatags_delete', $path_metatags);
// Call ctools functions to remove object correctly.
ctools_export_crud_delete('path_metatags', $path_metatags);
path_metatags_object_cache_clear($name);
cache_clear_all('path_metatags', 'cache', TRUE);
}
/**
* Prepare raw object from Ctools to normal path_metatags object.
*
* @param $path_metatags_raw
* Object loaded from database or ctools_export_load_object().
* @return object $path_metatags.
*/
function path_metatags_load_prepare($path_metatags_raw) {
// Merge metatags data with parent for more flattening structure.
$path_metatags = (object) array_merge((array) $path_metatags_raw, $path_metatags_raw->data);
$path_metatags->disabled = isset($path_metatags->disabled) ? $path_metatags->disabled : FALSE;
$path_metatags->is_overwritten = $path_metatags->export_type == (EXPORT_IN_DATABASE | EXPORT_IN_CODE);
unset($path_metatags->data);
return $path_metatags;
}
/**
* Load path metatags by ID.
*
* @param $path_id
* ID of path metatags that should be loaded
* @return object
* Loaded path metatags
*/
function path_metatags_load($path_id) {
// Cache it because Ctools cache is not helpful for 'conditions' loading.
$paths =& drupal_static(__FUNCTION__);
if (!isset($paths[$path_id])) {
ctools_include('export');
$result = ctools_export_load_object('path_metatags', 'conditions', array(
'path_id' => $path_id,
));
$path_metatags = reset($result);
if (!empty($path_metatags)) {
// Merge metatags data with parent for more flattening structure.
$path_metatags = path_metatags_load_prepare($path_metatags);
$paths[$path_id] = $path_metatags;
}
}
return isset($paths[$path_id]) ? $paths[$path_id] : FALSE;
}
/**
* Load path metatags by name.
*
* @param $name
* Path metatags's name.
* @return object
* Object with path metatags.
*/
function path_metatags_load_by_name($name) {
ctools_include('export');
$result = ctools_export_load_object('path_metatags', 'names', array(
$name,
));
if (!empty($result[$name])) {
// Merge metatags data with parent for more flattening structure.
$path_metatags = path_metatags_load_prepare($result[$name]);
}
return isset($path_metatags) ? $path_metatags : FALSE;
}
/**
* Load multiple objects by names.
*
* @param $names
* @return array
*/
function path_metatags_load_by_name_multiple($names) {
ctools_include('export');
$result = ctools_export_load_object('path_metatags', 'names', $names);
// Merge metatags data with parent for more flattening structure.
foreach ($result as $name => $path_metatags) {
$result[$name] = path_metatags_load_prepare($path_metatags);
}
return $result;
}
/**
* Load all path metatags from database and code.
*
* @return array
* Array of path_metatags objects.
*/
function path_metatags_load_all() {
$data =& drupal_static(__FUNCTION__);
if (empty($data)) {
ctools_include('export');
$data = ctools_export_load_object('path_metatags', 'all');
// Make objects more developer-friendly.
$data = array_map('path_metatags_load_prepare', $data);
// Order by weight.
uasort($data, '_path_metatags_sort_weight');
}
return $data;
}
/**
* Load enabled path_metatags by path.
*
* @param string $path
* Current page path.
* @return array
* Array of path_metatags sorted by weight.
*/
function path_metatags_load_by_path($path) {
$data =& drupal_static(__FUNCTION__);
$pattern_needle = path_metatags_path_pattern($path);
if (empty($data[$pattern_needle])) {
$cache = cache_get(__FUNCTION__);
if (!empty($cache)) {
$data = $cache->data;
}
else {
// Do heavy work and cache results.
ctools_include('export');
// No need to sort variants by weight because path_metatags_load_all()
// already sorted all data.
$result = path_metatags_load_all();
foreach ($result as $path_metatags) {
if (empty($path_metatags->disabled)) {
$pattern = path_metatags_path_pattern($path_metatags->path);
$data[$pattern][] = $path_metatags;
}
}
cache_set(__FUNCTION__, $data, 'cache');
}
}
return isset($data[$pattern_needle]) ? $data[$pattern_needle] : array();
}
/**
* Load ctools contexts from path arguments.
*
* @param $arguments
* URL arguments.
* @param bool $empty
* Define load context for empty arguments or not
* @return array
* Array with context plugins.
*/
function path_metatags_get_contexts_from_arguments($arguments, $empty = FALSE) {
$contexts = array();
// Include ctools library for contexts.
ctools_include('context');
if (!empty($arguments)) {
// Get contexts from arguments.
foreach ($arguments as $keyword => $arg) {
if (!empty($arg['argument'])) {
$argument = ctools_get_argument($arg['argument']);
if (isset($arg['settings'])) {
$argument = array_merge($argument, $arg['settings']);
}
// See what we should return: empty contexts or from path arguments.
$arg = $empty ? NULL : arg($arg['position']);
// Build context.
$context = call_user_func($argument['context'], $arg, $argument, $empty);
if (!empty($context)) {
$context->keyword = $keyword;
$context->identifier = $argument['identifier'];
$contexts[$keyword] = $context;
}
else {
$contexts['broken_context'] = $keyword;
}
}
}
}
return $contexts;
}
/**
* Get path metatags data from cache.
*
* @param $name
* Machine name of path metatags that should be loaded.
* @param bool $skip_cache
* Skip current cache or not.
* @return object
* Return cached object.
*/
function path_metatags_object_cache_get($name, $skip_cache = FALSE) {
ctools_include('object-cache');
return ctools_object_cache_get('path_metatags', $name, $skip_cache);
}
/**
* Cache path metatags data.
*
* @param $name
* Machine name of path metatags.
* @param $data
* Data to store.
* @return void
*/
function path_metatags_object_cache_set($name, $data) {
ctools_include('object-cache');
$data = (object) $data;
ctools_object_cache_set('path_metatags', $name, $data);
}
/**
* Clear ctools object cache.
*
* @param $name
* Path metatags name.
*/
function path_metatags_object_cache_clear($name) {
ctools_include('object-cache');
ctools_object_cache_clear('path_metatags', $name);
}
/**
* Create sql pattern from url.
* Replaces all path arguments except the 1st one with %-symbol.
*
* @param string $path
* @return string pattern
*/
function path_metatags_path_pattern($path) {
$cache =& drupal_static(__FUNCTION__);
if (empty($cache[$path])) {
// Example: 'node/%node/view' -> 'node/%/%.
$cache[$path] = preg_replace("\n /\\/ # start with slash\n [^\\/]+ # all symbols except for the slash\n /x", '/%', $path);
}
return $cache[$path];
}
/**
* This is version of drupal_sort_weight() for objects.
* Function used by uasort to sort array of objects by weight.
*
* @param $a
* @param $b
* @return int
*/
function _path_metatags_sort_weight($a, $b) {
$a_weight = isset($a->weight) ? $a->weight : 0;
$b_weight = isset($b->weight) ? $b->weight : 0;
if ($a_weight == $b_weight) {
return 0;
}
return $a_weight < $b_weight ? -1 : 1;
}
/**
* Ctools export callback.
*
* @param $path_metatags
* @param $indent
* @return string
*/
function path_metatags_export($path_metatags, $indent) {
// Structure object according to schema.
$path_metatags->data = array(
'metatags' => $path_metatags->metatags,
'metatags_values' => $path_metatags->metatags_values,
'translatable' => $path_metatags->translatable,
'arguments' => $path_metatags->arguments,
'access' => $path_metatags->access,
);
return ctools_export_object('path_metatags', $path_metatags, $indent);
}
/**
* Ctools list callback of all avalible path_metatags objects.
*
* @return array
*/
function path_metatags_export_list() {
$list = array();
$result = path_metatags_load_all();
foreach ($result as $path_metatags) {
$string = $path_metatags->name . " (" . $path_metatags->machine_name . ")";
$list[$path_metatags->machine_name] = check_plain($string);
}
return $list;
}
/**
* Implements hook_path_metatags_info().
*/
function path_metatags_ui_path_metatags_info() {
$metatags['author'] = array(
'group' => 'name',
);
$metatags['copyright'] = array(
'group' => 'name',
);
$metatags['description'] = array(
'group' => 'name',
);
$metatags['document-state'] = array(
'group' => 'name',
);
$metatags['generator'] = array(
'group' => 'name',
);
$metatags['keywords'] = array(
'group' => 'name',
);
$metatags['resource-type'] = array(
'group' => 'name',
);
$metatags['revisit'] = array(
'group' => 'name',
);
$metatags['robots'] = array(
'group' => 'name',
);
$metatags['url'] = array(
'group' => 'name',
);
$metatags['Content-Script-Type'] = array(
'group' => 'http-equiv',
);
$metatags['Content-Style-Type'] = array(
'group' => 'http-equiv',
);
$metatags['Content-Type'] = array(
'group' => 'http-equiv',
);
$metatags['Expires'] = array(
'group' => 'http-equiv',
);
$metatags['Pragma'] = array(
'group' => 'http-equiv',
);
$metatags['title'] = array(
'group' => 'title',
);
$metatags['refresh'] = array(
'group' => 'http-equiv',
);
$metatags['imagetoolbar'] = array(
'group' => 'http-equiv',
);
return $metatags;
}
Functions
Name | Description |
---|---|
path_metatags_ctools_plugin_directory | Implements hook_ctools_plugin_directory(). |
path_metatags_delete | Delete path metatag. |
path_metatags_export | Ctools export callback. |
path_metatags_export_list | Ctools list callback of all avalible path_metatags objects. |
path_metatags_get_contexts_from_arguments | Load ctools contexts from path arguments. |
path_metatags_html_head_alter | Implements hook_html_head_alter(). |
path_metatags_load | Load path metatags by ID. |
path_metatags_load_all | Load all path metatags from database and code. |
path_metatags_load_by_name | Load path metatags by name. |
path_metatags_load_by_name_multiple | Load multiple objects by names. |
path_metatags_load_by_path | Load enabled path_metatags by path. |
path_metatags_load_metatags_list | Load list of metatags. |
path_metatags_load_prepare | Prepare raw object from Ctools to normal path_metatags object. |
path_metatags_load_variant | Load metatags based on path and visibility settings. |
path_metatags_object_cache_clear | Clear ctools object cache. |
path_metatags_object_cache_get | Get path metatags data from cache. |
path_metatags_object_cache_set | Cache path metatags data. |
path_metatags_path_pattern | Create sql pattern from url. Replaces all path arguments except the 1st one with %-symbol. |
path_metatags_preprocess_html | Implements hook_preprocess_html(). |
path_metatags_save | Save path metatags. |
path_metatags_ui_path_metatags_info | Implements hook_path_metatags_info(). |
_path_metatags_build_metatags | Build metatags navigation from loaded path metatags variant. |
_path_metatags_sort_weight | This is version of drupal_sort_weight() for objects. Function used by uasort to sort array of objects by weight. |