block_titlelink.module in Block Title Link 8
Same filename and directory in other branches
module for adding a link to a block title
File
block_titlelink.moduleView source
<?php
/**
* @file module for adding a link to a block title
*/
use Drupal\Component\Utility\Html;
use Drupal\Component\Utility\Xss;
use Drupal\Core\Form\FormStateInterface;
use Drupal\Core\Template\Attribute;
/**
* Implementation of hook_form_alter
*/
function block_titlelink_form_alter(&$form, FormStateInterface $form_state, $form_id) {
if ($form_id == 'block_form' || $form_id == 'basic_custom_block_form') {
$target_values = [
'_blank',
'_self',
'_parent',
'_top',
];
$targets = array_combine($target_values, $target_values);
$config = \Drupal::config('block_titlelink.settings');
$block_id = $form['id']['#default_value'];
$display = $config
->get($block_id . '.display_link');
$display = isset($display) ? $display : TRUE;
$form['block_titlelink'] = [
'#type' => 'details',
'#title' => t('Block Title Link Settings'),
'#collapsible' => TRUE,
'#weight' => 0,
'#open' => FALSE,
];
$form['block_titlelink']['title_link'] = [
'#type' => 'textfield',
'#title' => t('Title Path'),
'#description' => t('URL path of Block Title. Tokens are supported.'),
'#default_value' => $config
->get($block_id . '.title_link'),
];
$form['block_titlelink']['title_link_title'] = [
'#type' => 'textfield',
'#title' => t('Title Attribute'),
'#description' => t('Value for the <a> title attribute.'),
'#default_value' => $config
->get($block_id . '.title'),
];
$form['block_titlelink']['title_link_target'] = [
'#type' => 'select',
'#title' => t('Link Target'),
'#options' => $targets,
'#empty_value' => '',
'#description' => t('Add a target to open the link in a new tab/window'),
'#default_value' => $config
->get($block_id . '.target'),
];
$form['block_titlelink']['display_link'] = [
'#type' => 'checkbox',
'#title' => t('Display Link'),
'#description' => t('Select this option if title should render as a link. If deselected, the title path value is stored within the block object as $block->title_link but is not rendered. This is useful if you wish to use the link elsewhere in the block template (ex: as an icon).'),
'#default_value' => $display,
];
$form['actions']['submit']['#validate'][] = 'block_titlelink_form_validate';
$form['actions']['submit']['#submit'][] = 'block_titlelink_form_submit';
}
}
/**
* Form validation callback for block_titlelink_form_alter
*/
function block_titlelink_form_validate(&$form, FormStateInterface &$form_state) {
$title_link = trim($form_state
->getValue([
'block_titlelink',
'title_link',
]));
$valid = _block_titlelink_validate_url($title_link);
if (!empty($title_link) && !$valid) {
$form_state
->setErrorByName('block_search_form_blocktitlelink][title_link', t('The title path appears to contain an invalid URL.'));
}
}
/**
* Form submission callback for block_titlelink_form_alter
*/
function block_titlelink_form_submit(&$form, FormStateInterface &$form_state) {
$config = \Drupal::configFactory()
->getEditable('block_titlelink.settings');
$block_id = $form['id']['#default_value'];
$url = trim($form_state
->getValue([
'block_titlelink',
'title_link',
]));
$data = [
'url' => $url,
'display' => $form_state
->getValue([
'block_titlelink',
'display_link',
]),
'title' => $form_state
->getValue([
'block_titlelink',
'title_link_title',
]),
'target' => $form_state
->getValue([
'block_titlelink',
'title_link_target',
]),
];
if (empty($url)) {
$config
->clear($block_id);
$config
->save();
}
else {
$config
->set($block_id . '.title_link', $data['url'])
->set($block_id . '.display_link', $data['display'])
->set($block_id . '.title', $data['title'])
->set($block_id . '.target', $data['target'])
->save();
}
}
/**
* Implements hook_preprocess_hook().
*/
function block_titlelink_preprocess_block(&$vars) {
// Get the block id
$block_id = $vars['elements']['#id'];
$config = \Drupal::config('block_titlelink.settings');
$url = $config
->get($block_id . '.title_link');
$url = isset($url) ? trim($url) : NULL;
$display = $config
->get($block_id . '.display_link');
$display = isset($display) ? $display : TRUE;
$titlelink_title = $config
->get($block_id . '.title');
$titlelink_title = isset($titlelink_title) ? Html::escape($titlelink_title) : NULL;
$target = $config
->get($block_id . '.target');
$target = isset($target) ? $target : NULL;
if (\Drupal::moduleHandler()
->moduleExists('php')) {
$url = php_eval($url);
}
if (!empty($url) && $display) {
$attributes = [
'attributes' => [
'class' => [
'block-title-link',
],
],
'html' => TRUE,
];
if (!empty($titlelink_title)) {
$attributes['attributes']['title'] = $titlelink_title;
}
if (!empty($target)) {
$attributes['attributes']['target'] = $target;
}
$attributes = new Attribute($attributes['attributes']);
$vars['label'] = Xss::filter('<a href="' . $url . '"' . $attributes . '>' . t($vars['label']) . '</a>');
}
}
/**
* Heisted the url validation from the link field module.
*
* @param string $url
* The url to validate.
*
* @return string
* The url type if url is valid, FALSE otherwise.
*/
function _block_titlelink_validate_url($url) {
$text = $url;
// These constants were heisted from the field_module.
// Check if they exist
if (!defined('LINK_EXTERNAL')) {
define('LINK_EXTERNAL', 'external');
}
if (!defined('LINK_INTERNAL')) {
define('LINK_INTERNAL', 'internal');
}
if (!defined('LINK_FRONT')) {
define('LINK_FRONT', 'front');
}
if (!defined('LINK_EMAIL')) {
define('LINK_EMAIL', 'email');
}
if (!defined('LINK_NEWS')) {
define('LINK_NEWS', 'news');
}
if (!defined('LINK_DOMAINS')) {
define('LINK_DOMAINS', 'aero|arpa|asia|biz|com|cat|coop|edu|gov|info|int|jobs|mil|museum|name|nato|net|org|pro|travel|mobi|local');
}
$LINK_ICHARS_DOMAIN = (string) html_entity_decode(implode("", [
"æ",
// æ
"Æ",
// Æ
"ø",
// ø
"Ø",
// Ø
"å",
// å
"Å",
// Å
"ä",
// ä
"Ä",
// Ä
"ö",
// ö
"Ö",
// Ö
"ü",
// ü
"Ü",
// Ü
"Ñ",
// Ñ
"ñ",
]), ENT_QUOTES, 'UTF-8');
$LINK_ICHARS = $LINK_ICHARS_DOMAIN . (string) html_entity_decode(implode("", [
"ß",
]), ENT_QUOTES, 'UTF-8');
$allowed_protocols = [
'http',
'https',
'ftp',
'news',
'nntp',
'telnet',
'mailto',
'irc',
'ssh',
'sftp',
'webcal',
];
$protocol = '((' . implode("|", $allowed_protocols) . '):\\/\\/)';
$authentication = '(([a-z0-9%' . $LINK_ICHARS . ']+(:[a-z0-9%' . $LINK_ICHARS . '!]*)?)?@)';
$domain = '(([a-z0-9' . $LINK_ICHARS_DOMAIN . ']([a-z0-9' . $LINK_ICHARS_DOMAIN . '\\-_\\[\\]])*)(\\.(([a-z0-9' . $LINK_ICHARS_DOMAIN . '\\-_\\[\\]])+\\.)*(' . LINK_DOMAINS . '|[a-z]{2}))?)';
$ipv4 = '([0-9]{1,3}(\\.[0-9]{1,3}){3})';
$ipv6 = '([0-9a-fA-F]{1,4}(\\:[0-9a-fA-F]{1,4}){7})';
$port = '(:([0-9]{1,5}))';
// Pattern specific to external links.
$external_pattern = '/^' . $protocol . '?' . $authentication . '?(' . $domain . '|' . $ipv4 . '|' . $ipv6 . ' |localhost)' . $port . '?';
// Pattern specific to internal file link.
$internal_pattern_file = "/^([a-z0-9" . $LINK_ICHARS . "_\\-+\\[\\]\\.]+)\$/i";
$directories = "(\\/[a-z0-9" . $LINK_ICHARS . "_\\-\\.~+%=&,\$'!():;*@\\[\\]]*)*";
// Yes, four backslashes == a single backslash.
$query = "(\\/?\\?([?a-z0-9" . $LINK_ICHARS . "+_|\\-\\.\\/\\\\%=&,\$'():;*@\\[\\]{} ]*))";
$anchor = "(#[a-z0-9" . $LINK_ICHARS . "_\\-\\.~+%=&,\$'():;*@\\[\\]\\/\\?]*)";
// The rest of the path for a standard URL.
$end = $directories . '?' . $query . '?' . $anchor . '?' . '$/i';
$message_id = '[^@].*@' . $domain;
$newsgroup_name = '([0-9a-z+-]*\\.)*[0-9a-z+-]*';
$news_pattern = '/^news:(' . $newsgroup_name . '|' . $message_id . ')$/i';
$user = '[a-zA-Z0-9' . $LINK_ICHARS . '_\\-\\.\\+\\^!#\\$%&*+\\/\\=\\?\\`\\|\\{\\}~\'\\[\\]]+';
$email_pattern = '/^mailto:' . $user . '@' . '(' . $domain . '|' . $ipv4 . '|' . $ipv6 . '|localhost)' . $query . '?$/';
if (strpos($text, '<front>') === 0) {
return LINK_FRONT;
}
if (in_array('mailto', $allowed_protocols) && preg_match($email_pattern, $text)) {
return LINK_EMAIL;
}
if (in_array('news', $allowed_protocols) && preg_match($news_pattern, $text)) {
return LINK_NEWS;
}
if (\Drupal::service('path.validator')
->isValid($text)) {
return LINK_INTERNAL;
}
if (preg_match($external_pattern . $end, $text)) {
return LINK_EXTERNAL;
}
if (preg_match($internal_pattern_file, $text)) {
return LINK_INTERNAL;
}
return FALSE;
}
Functions
Name![]() |
Description |
---|---|
block_titlelink_form_alter | Implementation of hook_form_alter |
block_titlelink_form_submit | Form submission callback for block_titlelink_form_alter |
block_titlelink_form_validate | Form validation callback for block_titlelink_form_alter |
block_titlelink_preprocess_block | Implements hook_preprocess_hook(). |
_block_titlelink_validate_url | Heisted the url validation from the link field module. |