View source
<?php
define('PATH_BREADCRUMBS_RICH_SNIPPETS_DISABLED', 0);
define('PATH_BREADCRUMBS_RICH_SNIPPETS_RDFA', 1);
define('PATH_BREADCRUMBS_RICH_SNIPPETS_MICRODATA', 2);
function path_breadcrumbs_page_alter() {
$breadcrumbs = path_breadcrumbs_load_variant(current_path());
if ($breadcrumbs) {
drupal_set_breadcrumb($breadcrumbs);
}
}
function path_breadcrumbs_load_variant($path) {
if (!$path) {
return FALSE;
}
$variants = path_breadcrumbs_load_by_path($path);
foreach ($variants as $breadcrumb) {
$matched_path = preg_replace("\n /\\/% # start with slash-percent\n [^\\/]+ # all symbols except for the slash\n /x", '/*', $breadcrumb->path);
if (drupal_match_path($path, $matched_path)) {
$contexts = path_breadcrumbs_get_contexts_from_arguments($breadcrumb->arguments);
if (isset($contexts['broken_context'])) {
continue;
}
if (!empty($breadcrumb->access)) {
$access = ctools_access($breadcrumb->access, $contexts);
if (!$access) {
continue;
}
}
return _path_breadcrumbs_build_breadcrumbs($breadcrumb, $contexts);
}
}
return FALSE;
}
function _path_breadcrumbs_build_breadcrumbs($path_breadcrumb, $contexts = array()) {
$breadcrumb = array();
module_invoke_all('path_breadcrumbs_view', $path_breadcrumb, $contexts);
if ($path_breadcrumb->home == TRUE) {
$home = variable_get('path_breadcrumbs_home_link_title', 'Home');
$breadcrumb[] = l(t($home), '<front>');
}
$titles = implode("\n", $path_breadcrumb->titles);
$paths = implode("\n", $path_breadcrumb->paths);
$replace = array();
$search = array();
if (!empty($path_breadcrumb->arguments)) {
foreach ($path_breadcrumb->arguments as $keyword => $argument) {
$search[] = '!' . $keyword;
$replace[] = arg($argument['position']);
}
}
$search[] = '!page_title';
$replace[] = drupal_get_title();
$titles = str_replace($search, $replace, $titles);
$paths = str_replace($search, $replace, $paths);
if (!empty($contexts)) {
$titles = ctools_context_keyword_substitute($titles, array(), $contexts);
$paths = ctools_context_keyword_substitute($paths, array(), $contexts);
}
$path_breadcrumb->titles_prepared = explode("\n", $titles);
$path_breadcrumb->paths_prepared = explode("\n", $paths);
foreach ($path_breadcrumb->titles_prepared as $key => $title) {
if (empty($title)) {
continue;
}
if ($path_breadcrumb->translatable == TRUE) {
$title = t($title);
}
$decode_html_entities = variable_get('path_breadcrumbs_decode_entities', TRUE);
if ($decode_html_entities) {
$title = html_entity_decode($title, ENT_QUOTES, 'UTF-8');
}
if (isset($path_breadcrumb->paths_prepared[$key]) && $path_breadcrumb->paths_prepared[$key] != '<none>') {
$breadcrumb[] = l($title, $path_breadcrumb->paths_prepared[$key]);
}
elseif (isset($path_breadcrumb->paths_prepared[$key]) && $path_breadcrumb->paths_prepared[$key] == '<none>') {
$breadcrumb[] = check_plain($title);
}
}
drupal_alter('path_breadcrumbs_view', $breadcrumb, $path_breadcrumb, $contexts);
return $breadcrumb;
}
function path_breadcrumbs_theme_registry_alter(&$theme_registry) {
$internal_render = variable_get('path_breadcrumbs_internal_render', 1);
if ($internal_render) {
$theme_registry['breadcrumb']['theme path'] = drupal_get_path('module', 'path_breadcrumbs');
$theme_registry['breadcrumb']['function'] = 'path_breadcrumbs_breadcrumb';
}
}
function path_breadcrumbs_breadcrumb($variables) {
$breadcrumbs = $variables['breadcrumb'];
if (!empty($breadcrumbs)) {
$output = '<h2 class="element-invisible">' . t('You are here') . '</h2>';
$hide_single_breadcrumb = variable_get('path_breadcrumbs_hide_single_breadcrumb', 0);
if ($hide_single_breadcrumb && count($breadcrumbs) == 1) {
return FALSE;
}
$elem_tag = 'span';
$elem_property = '';
$root_property = '';
$options = array();
$snippet = variable_get('path_breadcrumbs_rich_snippets', PATH_BREADCRUMBS_RICH_SNIPPETS_DISABLED);
if ($snippet == PATH_BREADCRUMBS_RICH_SNIPPETS_RDFA) {
$options = array(
'attributes' => array(
'rel' => 'v:url',
'property' => 'v:title',
),
'absolute' => TRUE,
'html' => TRUE,
);
$elem_property = 'typeof="v:Breadcrumb"';
$root_property = 'xmlns:v="http://rdf.data-vocabulary.org/#"';
}
elseif ($snippet == PATH_BREADCRUMBS_RICH_SNIPPETS_MICRODATA) {
$options = array(
'attributes' => array(
'itemprop' => 'url',
),
'absolute' => TRUE,
'html' => TRUE,
);
$elem_property = 'itemscope itemtype="http://data-vocabulary.org/Breadcrumb"';
$elem_tag = 'div';
drupal_add_css(drupal_get_path('module', 'path_breadcrumbs') . '/path_breadcrumbs.css');
}
foreach ($breadcrumbs as $key => $breadcrumb) {
$classes = array(
'inline',
);
$classes[] = $key % 2 ? 'even' : 'odd';
if ($key == 0) {
$classes[] = 'first';
}
if (count($breadcrumbs) == $key + 1) {
$classes[] = 'last';
}
preg_match('/href="([^"]+?)"/', $breadcrumb, $matches);
$href = '';
if (!empty($matches[1])) {
global $base_path;
global $language;
$base_string = $base_path;
if (!empty($language->prefix)) {
$base_string .= $language->prefix . '/';
}
if (drupal_strlen($base_string) > drupal_strlen($matches[1])) {
$href = '';
}
elseif (stripos($matches[1], $base_string) === 0) {
$href = drupal_substr($matches[1], drupal_strlen($base_string));
}
else {
$href = stripos($matches[1], '/') === 0 ? drupal_substr($matches[1], 1) : $matches[1];
}
$href = empty($href) ? '<front>' : $href;
}
$title = trim(strip_tags($breadcrumb));
if ($snippet == PATH_BREADCRUMBS_RICH_SNIPPETS_MICRODATA) {
$title = '<span itemprop="title">' . $title . '</span>';
}
$new_breadcrumb = !empty($href) ? l($title, $href, $options) : $title;
$breadcrumbs[$key] = '<' . $elem_tag . ' class="' . implode(' ', $classes) . '" ' . $elem_property . '>' . $new_breadcrumb . '</' . $elem_tag . '>';
}
$delimiter = variable_get('path_breadcrumbs_delimiter', '»');
$output .= '<div class="breadcrumb"' . $root_property . '>' . implode(' ' . trim($delimiter) . ' ', $breadcrumbs) . '</div>';
return $output;
}
return FALSE;
}
function path_breadcrumbs_save($path_breadcrumbs) {
ctools_include('export');
if (!empty($path_breadcrumbs->access) && !empty($path_breadcrumbs->logic)) {
$path_breadcrumbs->access['logic'] = $path_breadcrumbs->logic;
}
elseif (empty($path_breadcrumbs->access)) {
$path_breadcrumbs->access = array();
}
$path_breadcrumbs->data = array(
'titles' => $path_breadcrumbs->titles,
'paths' => $path_breadcrumbs->paths,
'home' => $path_breadcrumbs->home,
'translatable' => $path_breadcrumbs->translatable,
'arguments' => $path_breadcrumbs->arguments,
'access' => $path_breadcrumbs->access,
);
$save_result = ctools_export_crud_save('path_breadcrumbs', $path_breadcrumbs);
if ($save_result) {
path_breadcrumbs_object_cache_clear($path_breadcrumbs->machine_name);
$path_breadcrumbs->is_new = $save_result == SAVED_NEW;
module_invoke_all('path_breadcrumbs_save', $path_breadcrumbs);
cache_clear_all('path_breadcrumbs', 'cache', TRUE);
}
return $save_result;
}
function path_breadcrumbs_delete($name) {
$path_breadcrumbs = path_breadcrumbs_load_by_name($name);
module_invoke_all('path_breadcrumbs_delete', $path_breadcrumbs);
ctools_export_crud_delete('path_breadcrumbs', $path_breadcrumbs);
cache_clear_all('path_breadcrumbs', 'cache', TRUE);
}
function path_breadcrumbs_load_prepare($path_breadcrumbs_raw) {
$path_breadcrumbs = (object) array_merge((array) $path_breadcrumbs_raw, $path_breadcrumbs_raw->data);
$path_breadcrumbs->disabled = isset($path_breadcrumbs->disabled) ? $path_breadcrumbs->disabled : FALSE;
$path_breadcrumbs->is_overwritten = $path_breadcrumbs->export_type == (EXPORT_IN_DATABASE | EXPORT_IN_CODE);
unset($path_breadcrumbs->data);
return $path_breadcrumbs;
}
function path_breadcrumbs_load($path_id) {
$paths =& drupal_static(__FUNCTION__);
if (!isset($paths[$path_id])) {
ctools_include('export');
$result = ctools_export_load_object('path_breadcrumbs', 'conditions', array(
'path_id' => $path_id,
));
$path_breadcrumbs = reset($result);
if (!empty($path_breadcrumbs)) {
$path_breadcrumbs = path_breadcrumbs_load_prepare($path_breadcrumbs);
$paths[$path_id] = $path_breadcrumbs;
}
}
return isset($paths[$path_id]) ? $paths[$path_id] : FALSE;
}
function path_breadcrumbs_load_by_name($name) {
ctools_include('export');
$result = ctools_export_load_object('path_breadcrumbs', 'names', array(
$name,
));
if (!empty($result[$name])) {
$path_breadcrumbs = $result[$name];
$path_breadcrumbs = path_breadcrumbs_load_prepare($path_breadcrumbs);
}
return isset($path_breadcrumbs) ? $path_breadcrumbs : FALSE;
}
function path_breadcrumbs_load_by_name_multiple($names) {
ctools_include('export');
$result = ctools_export_load_object('path_breadcrumbs', 'names', $names);
foreach ($result as $name => $path_breadcrumbs) {
$result[$name] = path_breadcrumbs_load_prepare($path_breadcrumbs);
}
return $result;
}
function path_breadcrumbs_load_all() {
$data =& drupal_static(__FUNCTION__);
if (empty($data)) {
ctools_include('export');
$data = ctools_export_load_object('path_breadcrumbs', 'all');
$data = array_map('path_breadcrumbs_load_prepare', $data);
uasort($data, '_path_breadcrumbs_sort_weight');
}
return $data;
}
function path_breadcrumbs_load_by_path($path) {
$data =& drupal_static(__FUNCTION__);
$pattern_needle = path_breadcrumbs_path_pattern($path);
if (empty($data[$pattern_needle])) {
if ($cache = cache_get(__FUNCTION__)) {
$data = $cache->data;
}
else {
ctools_include('export');
$result = path_breadcrumbs_load_all();
foreach ($result as $path_breadcrumbs) {
if (empty($path_breadcrumbs->disabled)) {
$pattern = path_breadcrumbs_path_pattern($path_breadcrumbs->path);
$data[$pattern][] = $path_breadcrumbs;
}
}
cache_set(__FUNCTION__, $data, 'cache');
}
}
return isset($data[$pattern_needle]) ? $data[$pattern_needle] : array();
}
function path_breadcrumbs_get_contexts_from_arguments($arguments, $empty = FALSE) {
$contexts = array();
ctools_include('context');
if (!empty($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']);
}
$arg = $empty ? NULL : arg($arg['position']);
$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;
}
function path_breadcrumbs_object_cache_get($name, $skip_cache = FALSE) {
ctools_include('object-cache');
return ctools_object_cache_get('path_breadcrumbs', $name, $skip_cache);
}
function path_breadcrumbs_object_cache_set($name, $data) {
ctools_include('object-cache');
$data = (object) $data;
ctools_object_cache_set('path_breadcrumbs', $name, $data);
}
function path_breadcrumbs_object_cache_clear($name) {
ctools_include('object-cache');
ctools_object_cache_clear('path_breadcrumbs', $name);
}
function path_breadcrumbs_path_pattern($path) {
$cache =& drupal_static(__FUNCTION__);
if (empty($cache[$path])) {
$cache[$path] = preg_replace("\n /\\/ # start with slash\n [^\\/]+ # all symbols except for the slash\n /x", '/%', $path);
}
return $cache[$path];
}
function _path_breadcrumbs_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;
}
function path_breadcrumbs_export($path_breadcrumbs, $indent) {
$path_breadcrumbs->data = array(
'titles' => $path_breadcrumbs->titles,
'paths' => $path_breadcrumbs->paths,
'home' => $path_breadcrumbs->home,
'translatable' => $path_breadcrumbs->translatable,
'arguments' => $path_breadcrumbs->arguments,
'access' => $path_breadcrumbs->access,
);
return ctools_export_object('path_breadcrumbs', $path_breadcrumbs, $indent);
}
function path_breadcrumbs_export_list() {
$list = array();
$result = path_breadcrumbs_load_all();
foreach ($result as $path_breadcrumbs) {
$string = $path_breadcrumbs->name . " (" . $path_breadcrumbs->machine_name . ")";
$list[$path_breadcrumbs->machine_name] = check_plain($string);
}
return $list;
}