site_status_message_external_link.module in Site Status Message 7
Site Status Message External Link.
Allows Site Status Message module to use external links.
@author: Gideon Cresswell (DrupalGideon) <https://www.drupal.org/u/drupalgideon>
File
modules/site_status_message_external_link/site_status_message_external_link.moduleView source
<?php
/**
* @file
* Site Status Message External Link.
*
* Allows Site Status Message module to use external links.
*
* @author: Gideon Cresswell (DrupalGideon)
* <https://www.drupal.org/u/drupalgideon>
*/
/**
* Implements hook_form_FORM_ID_alter().
*/
function site_status_message_external_link_form_site_status_message_settings_alter(&$form, &$form_state, $form_id) {
// Add option to select an external link.
$form['site_status']['site_status_message_use_external_link'] = array(
'#type' => 'checkbox',
'#title' => t('Use external link'),
'#default_value' => variable_get('site_status_message_use_external_link'),
'#description' => t('Use external rather than internal link.'),
'#weight' => 11,
'#states' => array(
'visible' => array(
':input[name="site_status_message_showlink"]' => array(
'checked' => TRUE,
),
),
),
);
// Provide text field for external link.
$form['site_status']['site_status_message_external_link'] = array(
'#type' => 'textfield',
'#size' => 40,
'#maxlength' => 256,
'#title' => t('More information page'),
'#default_value' => variable_get('site_status_message_external_link'),
'#description' => t('An optional external link to show more information about the status message. Include http:// or https:// in the link.'),
'#weight' => 21,
'#element_validate' => array(
'_site_status_message_external_link_link_validate',
),
'#states' => array(
'visible' => array(
':input[name="site_status_message_showlink"]' => array(
'checked' => TRUE,
),
':input[name="site_status_message_use_external_link"]' => array(
'checked' => TRUE,
),
),
),
);
// Update the visibility state for the internal link so it will not show.
$form['site_status']['site_status_message_link']['#states']['visible'][':input[name="site_status_message_use_external_link"]'] = array(
'checked' => FALSE,
);
// Provide external link attributes.
$form['site_status']['site_status_message_external_link_attributes'] = array(
'#type' => 'fieldset',
'#title' => 'External link attributes',
'#weight' => 22,
'#states' => array(
'visible' => array(
':input[name="site_status_message_showlink"]' => array(
'checked' => TRUE,
),
':input[name="site_status_message_use_external_link"]' => array(
'checked' => TRUE,
),
),
),
'site_status_message_external_link_new_tab' => array(
'#type' => 'checkbox',
'#title' => t('Open link in a new browser tab.'),
'#default_value' => variable_get('site_status_message_external_link_new_tab'),
'#weight' => 25,
),
'site_status_message_external_link_no_follow' => array(
'#type' => 'checkbox',
'#title' => t('Use %nofollow attribute.', array(
'%nofollow' => 'rel="nofollow"',
)),
'#default_value' => variable_get('site_status_message_external_link_no_follow'),
'#weight' => 28,
),
);
$form['#after_build'][] = '_site_status_message_external_link_after_build';
if (!variable_get('site_status_message_valid_external_link') && variable_get('site_status_message_external_link')) {
drupal_set_message(t('The external link is no longer a valid path.'), 'warning');
}
}
/**
* Implements hook_preprocess_HOOK().
*
* Preprocess function for the theme template.
*/
function site_status_message_external_link_preprocess_site_status_message(&$variables) {
if (variable_get('site_status_message_showlink') && variable_get('site_status_message_use_external_link')) {
$link = variable_get('site_status_message_external_link');
// Only show the link if the external URL is valid.
if (variable_get('site_status_message_valid_external_link')) {
$readmore = filter_xss(variable_get('site_status_message_readmore', 'Read more'));
$attributes = array();
// Check if link needs to be opened in a new browser tab.
if (variable_get('site_status_message_external_link_new_tab', '')) {
$attributes['target'] = array(
'_blank',
);
// Newly opened tab can change the window.opener.location so adding
// these additional attributes should prevent this.
$attributes['rel'] = array(
'noopener',
'noreferrer',
);
}
// Check for nofollow attribute.
if (variable_get('site_status_message_external_link_no_follow')) {
$attributes['rel'][] = 'nofollow';
}
$variables['link'] = l($readmore, $link, array(
'attributes' => $attributes,
));
}
}
}
/**
* Implements hook_cron().
*/
function site_status_message_external_link_cron() {
if (variable_get('site_status_message_showlink') && variable_get('site_status_message_use_external_link')) {
// Delete the variable that contains the currently validity of the link.
variable_del('site_status_message_valid_external_link');
$link = variable_get('site_status_message_external_link');
// Check if the external link is still valid every time cron runs.
$valid_link = _site_status_message_external_link_is_url_valid($link);
if (!$valid_link) {
watchdog('site status message external link', '%link is no longer a valid link!', array(
'%link' => $link,
), WATCHDOG_ERROR);
}
variable_set('site_status_message_valid_external_link', $valid_link);
}
}
/**
* Remove internal link validation if external link is being used.
*
* Callback for #after_build.
*
* @param array $form
* The form array.
* @param array $form_state
* The form_state array.
*
* @return array
* The amended form array.
*/
function _site_status_message_external_link_after_build(array $form, array &$form_state) {
$use_link = $form_state['values']['site_status_message_use_external_link'];
// Only remove the validation if the 'use external link' checkbox is selected.
if ($use_link) {
$element_validate = $form['site_status']['site_status_message_link']['#element_validate'];
$key = array_search('_site_status_message_link_validate', $element_validate);
unset($form['site_status']['site_status_message_link']['#element_validate'][$key]);
}
return $form;
}
/**
* Validation callback for the Site Status Message External Link link field.
*
* Callback for #element_validate.
*
* @param array $element
* The element field being validated.
* @param array $form_state
* The form_state array.
*/
function _site_status_message_external_link_link_validate(array $element, array &$form_state) {
if ($form_state['values']['site_status_message_use_external_link']) {
$link = $form_state['values']['site_status_message_external_link'];
$valid_link = _site_status_message_external_link_is_url_valid($link);
if (!$valid_link) {
form_error($element, t('You must enter a valid external path.'));
}
else {
variable_set('site_status_message_valid_external_link', $valid_link);
}
}
}
/**
* Check whether the external URL provided is a valid link.
*
* @param string $link
* Text string containing a possible link.
*
* @return bool
* Whether the string provided is valid or not.
*/
function _site_status_message_external_link_is_url_valid($link) {
$valid_link = variable_get('site_status_message_valid_external_link');
$current_link = variable_get('site_status_message_external_link');
// We don't want to be running curl on every request so we store whether the
// link is valid or not. The link is periodically checked with cron.
if (!$valid_link || $link !== $current_link) {
$schema = parse_url($link, PHP_URL_SCHEME);
// If the schema isn't provided, return error before trying curl request.
if (!_site_status_message_external_link_is_valid_schema($schema)) {
return FALSE;
}
// Simpler than drupal_http_request().
$ch = curl_init($link);
curl_setopt($ch, CURLOPT_NOBODY, TRUE);
curl_setopt($ch, CURLOPT_USERAGENT, 'Mozilla/5.0 (Windows NT 6.1) AppleWebKit/537.2 (KHTML, like Gecko) Chrome/22.0.1216.0 Safari/537.2');
curl_exec($ch);
$http_code = curl_getinfo($ch, CURLINFO_HTTP_CODE);
curl_close($ch);
$valid_link = _site_status_message_external_link_is_valid_http_code($http_code);
}
return $valid_link;
}
/**
* List of all valid schemas.
*
* @return array
* Array of valid schemas.
*/
function _site_status_message_external_link_valid_schemas() {
return array(
'http',
'https',
);
}
/**
* List of all valid http response codes.
*
* @return array
* Array of valid http response codes.
*/
function _site_status_message_external_link_valid_response_codes() {
// Allow redirects as well as the 200 response code only.
return array(
200,
301,
302,
);
}
/**
* Check if the provided schema is in the allowed list.
*
* @param string $schema
* The schema to test.
*
* @return bool
* Whether the schema is valid or not.
*/
function _site_status_message_external_link_is_valid_schema($schema = NULL) {
return in_array($schema, _site_status_message_external_link_valid_schemas());
}
/**
* Check if the provided http code is in the allowed list.
*
* @param string $http_code
* The http code to test.
*
* @return bool
* Whether the code is valid or not.
*/
function _site_status_message_external_link_is_valid_http_code($http_code = NULL) {
return in_array((int) $http_code, _site_status_message_external_link_valid_response_codes());
}