youtube_cookies-2.0.x-dev/youtube_cookies.module
youtube_cookies.module
<?php
/**
* @file
* Hook implementations for youtube_cookies module.
*/
use Drupal\Core\Form\FormStateInterface;
use Drupal\Core\Render\RenderContext;
/**
* Implements hook_library_info_alter().
*/
function youtube_cookies_library_info_alter(&$libraries, $extension) {
// Add the oembed_lazyload library as a dependency if the module is enabled
// to ensure correct libraries order.
$moduleHandler = \Drupal::service('module_handler');
if ($moduleHandler->moduleExists('oembed_lazyload') && $extension === 'youtube_cookies') {
$libraries['youtube-cookies']['dependencies'][] = 'oembed_lazyload/onclick';
}
}
/**
* Implements hook_preprocess_oembed_lazyload_placeholder__youtube().
*/
function youtube_cookies_page_attachments(&$attachments) {
$config = \Drupal::config('youtube_cookies.settings');
if (!$config->get('enabled')) {
return;
}
$cookie_category = $config->get('cookie_category');
$provider = $config->get('provider');
if (!empty($cookie_category) && !empty($provider)) {
$attachments['#attached']['library'][] = sprintf('youtube_cookies/%s', $provider);
\Drupal::service('renderer')->executeInRenderContext(new RenderContext(), function () use (&$attachments, $config, $provider) {
$attachments['#attached']['drupalSettings']['youtubeCookies']['cookieCategory'] = $config->get('cookie_category');
$attachments['#attached']['drupalSettings']['youtubeCookies']['action'] = $config->get('action');
$attachments['#attached']['drupalSettings']['youtubeCookies']['thumbnailLabel'] = t('Open the YouTube cookie consent pop-up');
$attachments['#attached']['drupalSettings']['youtubeCookies']['popupMessage'] = youtube_cookies_popup_message($config->get('popup_message'));
$attachments['#attached']['drupalSettings']['youtubeCookies']['manageButton'] = youtube_cookies_popup_manage_button($provider, $config->get('button_manage'));
$attachments['#attached']['drupalSettings']['youtubeCookies']['okButton'] = youtube_cookies_ok_button($config->get('button_accept'));
$attachments['#attached']['drupalSettings']['youtubeCookies']['exitButton'] = youtube_cookies_exit_button($config->get('button_exit'));
$attachments['#attached']['drupalSettings']['youtubeCookies']['thumbnailMarkup'] = youtube_cookies_thumbnail_markup();
});
}
}
/**
* Explains that YouTube is using cookies.
*
* @param string $message
* Message body.
*
* @return int|mixed|null
* HTML markup with the message.
*/
function youtube_cookies_popup_message($message) {
$button = [
'#type' => 'html_tag',
'#tag' => 'div',
'#value' => $message,
'#attributes' => [
'class' => [
'youtube-cookies-popup-message',
],
],
];
return \Drupal::service('renderer')->render($button);
}
/**
* Button that will open the cookies management window.
*
* @param string $provider
* It can be either onetrust or eu_cookie_compliance.
* @param string $button_text
* Text to display in the button.
*
* @return int|mixed|null
* HTML with cookies management window.
*/
function youtube_cookies_popup_manage_button($provider, $button_text) {
$button = [
'#type' => 'html_tag',
'#tag' => 'button',
'#value' => $button_text,
'#attributes' => [
'class' => [
'youtube-cookies-button',
'youtube-cookies-button--manage',
'youtube-cookies-button--manage-' . $provider,
],
],
];
return \Drupal::service('renderer')->render($button);
}
/**
* Let the user accept that the cookies will be used.
*
* @param string $button_text
* Text to display in the button.
*
* @return int|mixed|null
* HTML markup to accept cookies.
*/
function youtube_cookies_ok_button($button_text) {
$button = [
'#type' => 'html_tag',
'#tag' => 'button',
'#value' => $button_text,
'#attributes' => [
'class' => [
'youtube-cookies-button',
'youtube-cookies-button--accept',
],
],
];
return \Drupal::service('renderer')->render($button);
}
/**
* Let the user leave the popup without accepting.
*
* @param string $button_text
* Text to display in the button.
*
* @return int|mixed|null
* HTML markup to reject the cookies popup.
*/
function youtube_cookies_exit_button($button_text) {
$button = [
'#type' => 'html_tag',
'#tag' => 'button',
'#value' => $button_text,
'#attributes' => [
'class' => [
'youtube-cookies-button',
'youtube-cookies-button--reject',
],
],
];
return \Drupal::service('renderer')->render($button);
}
/**
* Provide the thumbnails markup (svg icon + images).
*
* @return string
* HTML markup .
*/
function youtube_cookies_thumbnail_markup() {
$svg = '<svg class="youtube_cookies__play-icon" height="100%" viewBox="0 0 68 48" width="100%">'
.'<path class="youtube_cookies__play-icon__fill" d="M66.52,7.74c-0.78-2.93-2.49-5.41-5.42-6.19C55.79,.13,34,0,34,0S12.21,.13,6.9,1.55 C3.97,2.33,2.27,4.81,1.48,7.74C0.06,13.05,0,24,0,24s0.06,10.95,1.48,16.26c0.78,2.93,2.49,5.41,5.42,6.19 C12.21,47.87,34,48,34,48s21.79-0.13,27.1-1.55c2.93-0.78,4.64-3.26,5.42-6.19C67.94,34.95,68,24,68,24S67.94,13.05,66.52,7.74z" fill="#f00"></path>'
.'<path d="M 45,24 27,14 27,34" fill="#fff"></path>'
.'</svg>';
$picture = '<picture class="youtube-cookies__thumbnail__picture">'
.'<source srcset="https://i.ytimg.com/vi_webp/videoId/sddefault.webp, https://i.ytimg.com/vi_webp/videoId/maxresdefault.webp 2x" type="image/webp">'
.'<source srcset="https://i.ytimg.com/vi/videoId/sddefault.jpg, https://i.ytimg.com/vi/videoId/maxresdefault.jpg 2x" type="image/jpeg">'
.'<img class="oembed-lazyload__img" src="https://i.ytimg.com/vi/videoId/sddefault.jpg" width="300" height="182" alt="' . t('Video thumbnail') . '">'
.'</picture>';
return $svg . $picture;
}
/**
* Implements hook_preprocess_HOOK().
*/
function youtube_cookies_preprocess_field(&$variables) {
$config = \Drupal::config('youtube_cookies.settings');
if (!$config->get('enabled')) {
return;
}
if (isset($variables['element']['#formatter']) && $variables['element']['#formatter'] === 'oembed') {
_youtube_cookies_process_media_oembed($variables);
}
if (isset($variables['element']['#field_type']) && $variables['element']['#field_type'] === 'iframe') {
_youtube_cookies_process_iframe_field_types($variables);
}
}
/**
* Process the media oembed fields to obfuscate the src attribute.
*
* @param array $variables
* Render array.
*
* @return void
* Render array.
*/
function _youtube_cookies_process_media_oembed(array &$variables) {
foreach ($variables['items'] as &$item) {
if (!_youtube_cookies_is_youtube_source($item['content']['#attributes']['src'])) {
continue;
}
$item['content']['#attributes']['data-src'] = $item['content']['#attributes']['src'];
$item['content']['#attributes']['src'] = '';
$item['content']['#attributes']['class'][] = 'youtube-cookies__iframe';
$item['content']['#attributes']['class'][] = 'youtube-cookies__iframe--oembed';
}
}
/**
* Process the iframe field type to obfuscate the src attribute.
*
* @param array $variables
* Render array.
*
* @return void
* Render array.
*/
function _youtube_cookies_process_iframe_field_types(array &$variables) {
foreach ($variables['items'] as &$item) {
if (!_youtube_cookies_is_youtube_source($item['content']['#src'])) {
continue;
}
$item['content']['#attributes']->setAttribute('data-src', $item['content']['#src']);
$item['content']['#attributes']->setAttribute('src', '');
$item['content']['#src'] = '';
$item['content']['#attributes']->addClass([
'youtube-cookies__iframe',
'youtube-cookies__iframe--iframe-field',
]);
$wrapper = [
'#type' => 'html_tag',
'#tag' => 'div',
'content' => $item['content'],
'#attributes' => [
'class' => [
'youtube-cookies__iframe-container'
]
]
];
$item['content'] = $wrapper;
}
}
/**
* Check if the given source is a YouTube one.
*
* @param string $string
* The source string to be checked.
*
* @return false|int
* False if the URL is not from YouTube.
*/
function _youtube_cookies_is_youtube_source(string $string) {
$pattern = '/youtube\.com|youtu\.be/';
return preg_match($pattern, $string);
}
/**
* Implements hook_form_FORM_ID_alter().
*/
function youtube_cookies_form_filter_format_add_form_alter(array &$form, FormStateInterface $form_state, $form_id) {
// Add an additional validate callback so we can ensure the order of filters
// is correct.
$form['#validate'][] = '_youtube_cookies_filter_format_edit_form_validate';
}
/**
* Implements hook_form_FORM_ID_alter().
*/
function youtube_cookies_form_filter_format_edit_form_alter(array &$form, FormStateInterface $form_state, $form_id) {
// Add an additional validate callback so we can ensure the order of filters
// is correct.
$form['#validate'][] = '_youtube_cookies_filter_format_edit_form_validate';
}
/**
* Validate callback to ensure filter order and allowed_html are compatible.
*/
function _youtube_cookies_filter_format_edit_form_validate($form, FormStateInterface $form_state) {
if ($form_state->getTriggeringElement()['#name'] !== 'op') {
return;
}
$allowed_html_path = [
'filters',
'filter_html',
'settings',
'allowed_html',
];
$filter_html_settings_path = [
'filters',
'filter_html',
'settings',
];
$youtube_cookies_filter_enabled = $form_state->getValue([
'filters',
'youtube_cookies_wysiwyg_filter',
'status',
]);
if (!$youtube_cookies_filter_enabled) {
return;
}
$get_filter_label = function ($filter_plugin_id) use ($form) {
return (string) $form['filters']['order'][$filter_plugin_id]['filter']['#markup'];
};
if ($youtube_cookies_filter_enabled && $form_state->getValue($allowed_html_path)) {
/** @var \Drupal\filter\Entity\FilterFormat $filter_format */
$filter_format = $form_state->getFormObject()->getEntity();
$filter_html = clone $filter_format->filters()->get('filter_html');
$filter_html->setConfiguration(['settings' => $form_state->getValue($filter_html_settings_path)]);
$restrictions = $filter_html->getHTMLRestrictions();
$allowed = $restrictions['allowed'];
// Require `<iframe>` HTML tag if filter_html is enabled.
if (!isset($allowed['iframe'])) {
$form_state->setError($form['filters']['settings']['filter_html']['allowed_html'], t('The %youtube-cookies-filter-label filter requires <code><iframe></code> among the allowed HTML tags.', [
'%youtube-cookies-filter-label' => $get_filter_label('youtube_cookies_wysiwyg_filter'),
]));
}
else {
$required_attributes = [
'class',
];
// If there are no attributes, the allowed item is set to FALSE,
// otherwise, it is set to an array.
if ($allowed['iframe'] === FALSE) {
$missing_attributes = $required_attributes;
}
else {
$missing_attributes = array_diff($required_attributes, array_keys($allowed['iframe']));
}
if ($missing_attributes) {
$form_state->setError($form['filters']['settings']['filter_html']['allowed_html'], t('The <code><iframe></code> tag in the allowed HTML tags is missing the following attributes: <code>%list</code>.', [
'%list' => implode(', ', $missing_attributes),
]));
}
}
}
}
