Skip to content
Snippets Groups Projects
Commit 7764741c authored by Arun Sahijpal's avatar Arun Sahijpal
Browse files

Merge branch '3484416-addressed-pipelines-issues' into '8.x-2.x'

3484416-addressed-pipelines-issues: Fixed the issues.

See merge request !7
parents 2f1f037c 97ea1573
No related branches found
No related tags found
No related merge requests found
Pipeline #355797 passed
......@@ -27,3 +27,4 @@ variables:
OPT_IN_TEST_NEXT_MAJOR: '1'
# SKIP_ESLINT: '1'
# _CURL_TEMPLATES_REF: 'main'
_CSPELL_WORDS: 'cchoe,Tombras,WSOD,quickedit'
......@@ -87,7 +87,7 @@ selector is actually apart of the HTML. The field will not create the selector
you choose, it already has to exist for it to work.
If you don't see any available responsive image styles in the managed display
setting on the entity type you will most likley need to create one following the
setting on the entity type you will most likely need to create one following the
outline configurations above.
......
name: Background Image Field
description: Allows you to add responsive background images based on selctors.
core: 8.x
description: Allows you to add responsive background images based on selectors.
core_version_requirement: ^9 || ^10 || ^11
type: module
package: Field types
......
......@@ -5,9 +5,9 @@
* Provides a way to add background images dynamically.
*/
use Drupal\Core\Url;
use Drupal\Core\Form\FormStateInterface;
use Drupal\Core\Routing\RouteMatchInterface;
use Drupal\Core\Url;
/**
* Implements hook_help().
......
......@@ -4,6 +4,7 @@
"type": "drupal-module",
"license": "GPL-2.0-or-later",
"require": {
"drupal/core": "^9 || ^10 || ^11"
"drupal/core": "^9 || ^10 || ^11",
"drupal/token": "^1.15"
}
}
......@@ -2,22 +2,24 @@
namespace Drupal\bg_img_field\Plugin\Field\FieldFormatter;
use Drupal\bg_img_field\Component\Render\CSSSnippet;
use Drupal\Core\Cache\Cache;
use Drupal\Core\Entity\EntityInterface;
use Drupal\Core\Entity\EntityStorageInterface;
use Drupal\Core\Entity\EntityTypeManagerInterface;
use Drupal\Core\Field\FieldDefinitionInterface;
use Drupal\Core\Field\FieldItemListInterface;
use Drupal\Core\File\FileSystemInterface;
use Drupal\Core\File\FileUrlGeneratorInterface;
use Drupal\Core\Form\FormStateInterface;
use Drupal\Core\Image\ImageFactory;
use Drupal\Core\Logger\LoggerChannelTrait;
use Drupal\Core\Plugin\ContainerFactoryPluginInterface;
use Drupal\Core\Routing\UrlGeneratorInterface;
use Drupal\Core\Session\AccountInterface;
use Drupal\Core\Url;
use Drupal\Core\Utility\LinkGeneratorInterface;
use Drupal\bg_img_field\Component\Render\CSSSnippet;
use Drupal\breakpoint\BreakpointManagerInterface;
use Drupal\responsive_image\Plugin\Field\FieldFormatter\ResponsiveImageFormatter;
use Drupal\token\Token;
use Symfony\Component\DependencyInjection\ContainerInterface;
use Symfony\Component\HttpFoundation\RequestStack;
/**
* Plugin implementation of the 'image' formatter.
......@@ -35,32 +37,42 @@ use Symfony\Component\DependencyInjection\ContainerInterface;
*/
class BgImgFieldFormatter extends ResponsiveImageFormatter implements ContainerFactoryPluginInterface {
use LoggerChannelTrait;
/**
* Logger channel trait.
* The token service.
*
* @var Drupal\Core\Logger\LoggerChannelTrait */
use LoggerChannelTrait;
* @var \Drupal\token\TokenServiceInterface
*/
protected $tokenService;
/**
* The RequestStack service.
*
* @var \Symfony\Component\HttpFoundation\RequestStack
*/
protected $requestStack;
/**
* The file system service.
* The Breakpoint Manager service.
*
* @var \Drupal\Core\File\FileSystemInterface
* @var \Drupal\breakpoint\BreakpointManagerInterface
*/
protected $fileSystem;
protected $breakpointManager;
/**
* The image factory service.
* The URL generator service.
*
* @var \Drupal\Core\Image\ImageFactory
* @var \Drupal\Core\Routing\UrlGeneratorInterface
*/
protected $imageFactory;
protected $urlGenerator;
/**
* The entityTypeManager service.
* The file URL generator service.
*
* @var \Drupal\Core\Entity\EntityStorageInterface
* @var \Drupal\Core\File\FileUrlGeneratorInterface
*/
protected $entityTypeManager;
protected $fileUrlGenerator;
/**
* Constructor for the Background Image Formatter.
......@@ -74,26 +86,30 @@ class BgImgFieldFormatter extends ResponsiveImageFormatter implements ContainerF
* @param array $settings
* The stored setting for the formatter.
* @param string $label
* The formatters label.
* The formatter's label.
* @param string $view_mode
* Which view mode the formatter is in.
* @param array $third_party_settings
* Any third party setting that might change how the formatter render the
* css.
* Any third party setting that might change how the formatter renders the
* CSS.
* @param \Drupal\Core\Entity\EntityStorageInterface $responsive_image_style_storage
* The responsive image styles created in the system.
* @param \Drupal\Core\Entity\EntityStorageInterface $image_style_storage
* The image styles that have been created int eh system.
* The image styles that have been created in the system.
* @param \Drupal\Core\Utility\LinkGeneratorInterface $link_generator
* Help generate links.
* @param \Drupal\Core\Session\AccountInterface $current_user
* The current user.
* @param \Drupal\Core\File\FileSystemInterface $fileSystem
* The file system.
* @param \Drupal\Core\Image\ImageFactory $imageFactory
* The image factory.
* @param \Drupal\Core\Entity\EntityTypeManagerInterface $entityTypeManager
* The entity type manager.
* @param \Drupal\breakpoint\BreakpointManagerInterface $breakpoint_manager
* The breakpoint manager service.
* @param \Drupal\token\TokenServiceInterface $token_service
* The token service used to generate tokens.
* @param \Symfony\Component\HttpFoundation\RequestStack $request_stack
* The request stack for the current request context.
* @param \Drupal\Core\Url\UrlGeneratorInterface $url_generator
* The URL generator for generating URLs for routes.
* @param \Drupal\Core\File\FileUrlGeneratorInterface $file_url_generator
* The file URL generator to generate absolute file URLs.
*/
public function __construct(
$plugin_id,
......@@ -107,9 +123,11 @@ class BgImgFieldFormatter extends ResponsiveImageFormatter implements ContainerF
EntityStorageInterface $image_style_storage,
LinkGeneratorInterface $link_generator,
AccountInterface $current_user,
FileSystemInterface $fileSystem,
ImageFactory $imageFactory,
EntityTypeManagerInterface $entityTypeManager
BreakpointManagerInterface $breakpoint_manager,
Token $token_service,
RequestStack $request_stack,
UrlGeneratorInterface $url_generator,
FileUrlGeneratorInterface $file_url_generator,
) {
parent::__construct(
$plugin_id,
......@@ -125,10 +143,11 @@ class BgImgFieldFormatter extends ResponsiveImageFormatter implements ContainerF
$current_user
);
$this->logger = $this->getLogger('bg_img_field');
$this->entityTypeManager = $entityTypeManager;
$this->fileSystem = $fileSystem;
$this->imageFactory = $imageFactory;
$this->breakpointManager = $breakpoint_manager;
$this->tokenService = $token_service;
$this->requestStack = $request_stack;
$this->urlGenerator = $url_generator;
$this->fileUrlGenerator = $file_url_generator;
}
/**
......@@ -147,11 +166,13 @@ class BgImgFieldFormatter extends ResponsiveImageFormatter implements ContainerF
$container->get('entity_type.manager')->getStorage('image_style'),
$container->get('link_generator'),
$container->get('current_user'),
$container->get('file_system'),
$container->get('image.factory'),
$container->get('entity_type.manager')
$container->get('breakpoint.manager'),
$container->get('token'),
$container->get('request_stack'),
$container->get('url_generator'),
$container->get('file_url_generator')
);
}
}
/**
* {@inheritdoc}
......@@ -236,7 +257,7 @@ class BgImgFieldFormatter extends ResponsiveImageFormatter implements ContainerF
foreach ($files as $file) {
$item = $file->_referringItem;
$selector = $item->css_selector;
$selector = \Drupal::token()->replace($selector, [$entity->getEntityTypeId() => $entity], ['clear' => TRUE]);
$selector = $this->tokenService->replace($selector, [$entity->getEntityTypeId() => $entity], ['clear' => TRUE]);
$css = $this->generateBackgroundCss(
$file,
$responsive_image_style,
......@@ -246,7 +267,7 @@ class BgImgFieldFormatter extends ResponsiveImageFormatter implements ContainerF
// Attach to head on element to create style tag in the html head.
if (!empty($css)) {
$current_path = \Drupal::request()->getRequestUri();
$current_path = $this->requestStack->getCurrentRequest()->getRequestUri();
if (preg_match('/node\/(\d+)\/layout/', $current_path, $matches)) {
$elements = [
'#theme' => 'background_style',
......@@ -280,7 +301,7 @@ class BgImgFieldFormatter extends ResponsiveImageFormatter implements ContainerF
/**
* CSS Generator Helper Function.
*
* @param object $image
* @param Drupal\Core\Entity\EntityInterface $file
* URI of the field image.
* @param string $responsive_image_style
* Desired picture mapping to generate CSS.
......@@ -292,7 +313,7 @@ class BgImgFieldFormatter extends ResponsiveImageFormatter implements ContainerF
* @return string
* Generated background image CSS.
*/
protected function generateBackgroundCss($file, $responsive_image_style, $selector, array $options) {
protected function generateBackgroundCss(EntityInterface $file, $responsive_image_style, $selector, array $options) {
$css = "";
if (!$file) {
......@@ -311,58 +332,60 @@ class BgImgFieldFormatter extends ResponsiveImageFormatter implements ContainerF
if (!$responsive_image_style) {
$field_definition = $this->fieldDefinition->getFieldStorageDefinition();
$this->logger->error('
$this->getLogger('bg_img_field')->error('
There is no responsive image style set for the {field_name} field on the {entity_type} entity. Please ensure
that the responsive image style is configured at <a href="{link}">{link}</a>. Then set the correct style on the
formatter for the entity display.
', [
'field_name' => $field_definition->get('field_name'),
'entity_type' => $field_definition->get('entity_type'),
'link' => Url::fromRoute('entity.responsive_image_style.collection')->toString(),
'link' => $this->urlGenerator->generateFromRoute(
'entity.responsive_image_style.collection'
),
]);
}
else {
$breakpoints = \Drupal::service('breakpoint.manager')->getBreakpointsByGroup($responsive_image_style->getBreakpointGroup());
$breakpoints = $this->breakpointManager->getBreakpointsByGroup($responsive_image_style->getBreakpointGroup());
foreach (array_reverse($responsive_image_style->getKeyedImageStyleMappings()) as $breakpoint_id => $multipliers) {
if (isset($breakpoints[$breakpoint_id])) {
$multipliers = array_reverse($multipliers);
$query = $breakpoints[$breakpoint_id]->getMediaQuery();
if ($query != "") {
$css .= ' @media ' . $query . ' {';
}
foreach ($multipliers as $multiplier => $mapping) {
$multiplier = rtrim($multiplier, "x");
if ($mapping['image_mapping_type'] != 'image_style') {
continue;
}
if ($mapping['image_mapping'] == "_original image_") {
$url = \Drupal::service('file_url_generator')->generateAbsoluteString($file->getFileUri());
} else {
// Use image style URL generation instead of ImageFactory->load()
$image_style = $this->entityTypeManager->getStorage('image_style')->load($mapping['image_mapping']);
$url = $image_style->buildUrl($file->getFileUri());
}
if ($multiplier != 1) {
$css .= ' @media (-webkit-min-device-pixel-ratio: ' . $multiplier . '), (min-resolution: ' . $multiplier * 96 . 'dpi), (min-resolution: ' . $multiplier . 'dppx) {';
}
$css .= $selector . ' {background-image: url(' . $url . ');}';
if ($multiplier != 1) {
$css .= '}';
}
}
if ($query != "") {
$css .= '}';
}
if (isset($breakpoints[$breakpoint_id])) {
$multipliers = array_reverse($multipliers);
$query = $breakpoints[$breakpoint_id]->getMediaQuery();
if ($query != "") {
$css .= ' @media ' . $query . ' {';
}
foreach ($multipliers as $multiplier => $mapping) {
$multiplier = rtrim($multiplier, "x");
if ($mapping['image_mapping_type'] != 'image_style') {
continue;
}
if ($mapping['image_mapping'] == "_original image_") {
$url = $this->fileUrlGenerator->generateAbsoluteString($file->getFileUri());
}
else {
$image_style = $this->imageStyleStorage->load($mapping['image_mapping']);
$url = $image_style->buildUrl($file->getFileUri());
}
if ($multiplier != 1) {
$css .= ' @media (-webkit-min-device-pixel-ratio: ' . $multiplier . '), (min-resolution: ' . $multiplier * 96 . 'dpi), (min-resolution: ' . $multiplier . 'dppx) {';
}
$css .= $selector . ' {background-image: url(' . $url . ');}';
if ($multiplier != 1) {
$css .= '}';
}
}
if ($query != "") {
$css .= '}';
}
}
}
}
}
return $css;
}
......
......@@ -42,7 +42,8 @@ class BgImgItem extends ImageItem {
public function storageSettingsForm(array &$form, FormStateInterface $form_state, $has_data) {
$elements = parent::storageSettingsForm($form, $form_state, $has_data);
// Remove title and alt from the setting form, they are not needed in background images.
// Remove title and alt from the setting form.
// They are not needed in background images.
unset($elements['default_image']['alt']);
unset($elements['default_image']['title']);
......@@ -133,7 +134,7 @@ class BgImgItem extends ImageItem {
*/
public function fieldSettingsForm(array $form, FormStateInterface $form_state) {
$parentElements = parent::fieldSettingsForm($form, $form_state);
// Unset fields from image field that will not be used.
unset($parentElements['alt_field']);
unset($parentElements['alt_field_required']);
......@@ -144,10 +145,10 @@ class BgImgItem extends ImageItem {
unset($parentElements['default_image']['title']);
$elements['css_settings'] = [
'#type' => 'details',
'#title' => $this->t('CSS Settings'),
'#description' => $this->t('Set default CSS properties for the background image.'),
'#open' => FALSE,
'#type' => 'details',
'#title' => $this->t('CSS Settings'),
'#description' => $this->t('Set default CSS properties for the background image.'),
'#open' => FALSE,
];
// Load tokens based on the entity type it is on.
......@@ -158,80 +159,80 @@ class BgImgItem extends ImageItem {
// The CSS selector input field.
$elements['css_settings']['css_selector'] = [
'#type' => 'textfield',
'#title' => $this->t('Selector'),
'#description' => $this->t('CSS Selector for background image.'),
'#default_value' => $css_option_settings['css_selector'],
'#token_types' => $token_types,
'#type' => 'textfield',
'#title' => $this->t('Selector'),
'#description' => $this->t('CSS Selector for background image.'),
'#default_value' => $css_option_settings['css_selector'],
'#token_types' => $token_types,
];
$elements['css_settings']['tokens'] = [
'#theme' => 'token_tree_link',
'#token_types' => $token_types,
'#global_types' => TRUE,
'#show_nested' => FALSE,
'#theme' => 'token_tree_link',
'#token_types' => $token_types,
'#global_types' => TRUE,
'#show_nested' => FALSE,
];
// User ability to select a background repeat option.
$elements['css_settings']['css_repeat'] = [
'#type' => 'radios',
'#title' => $this->t('Repeat Options'),
'#description' => $this->t('Add the css no repeat value to the background image.'),
'#default_value' => $css_option_settings['css_repeat'],
'#options' => [
"inherit" => $this->t("inherit"),
"no-repeat" => $this->t("no-repeat"),
"repeat" => $this->t('repeat'),
],
'#type' => 'radios',
'#title' => $this->t('Repeat Options'),
'#description' => $this->t('Add the css no repeat value to the background image.'),
'#default_value' => $css_option_settings['css_repeat'],
'#options' => [
"inherit" => $this->t("inherit"),
"no-repeat" => $this->t("no-repeat"),
"repeat" => $this->t('repeat'),
],
];
// User the ability to choose background size.
$elements['css_settings']['css_background_size'] = [
'#type' => 'radios',
'#title' => $this->t('Background Size'),
'#description' => $this->t("Add the background size setting you would like for the image, use inherit for default."),
'#default_value' => $css_option_settings['css_background_size'],
'#options' => [
'inherit' => $this->t('inherit'),
'auto' => $this->t('auto'),
'cover' => $this->t('cover'),
'contain' => $this->t('contain'),
'initial' => $this->t('initial'),
],
'#type' => 'radios',
'#title' => $this->t('Background Size'),
'#description' => $this->t("Add the background size setting you would like for the image, use inherit for default."),
'#default_value' => $css_option_settings['css_background_size'],
'#options' => [
'inherit' => $this->t('inherit'),
'auto' => $this->t('auto'),
'cover' => $this->t('cover'),
'contain' => $this->t('contain'),
'initial' => $this->t('initial'),
],
];
// User the ability to set the background position.
$elements['css_settings']['css_background_position'] = [
'#type' => 'radios',
'#title' => $this->t('Background Position'),
'#description' => $this->t('Set a background position'),
'#default_value' => $css_option_settings['css_background_position'],
'#options' => [
"inherit" => $this->t("inherit"),
"left top" => $this->t("left top"),
"left center" => $this->t("left center"),
"left bottom" => $this->t("left bottom"),
"right top" => $this->t("right bottom"),
"right center" => $this->t("right center"),
"right bottom" => $this->t("right bottom"),
"center top" => $this->t("center top"),
"center center" => $this->t("center center"),
"center bottom" => $this->t("center bottom"),
],
'#type' => 'radios',
'#title' => $this->t('Background Position'),
'#description' => $this->t('Set a background position'),
'#default_value' => $css_option_settings['css_background_position'],
'#options' => [
"inherit" => $this->t("inherit"),
"left top" => $this->t("left top"),
"left center" => $this->t("left center"),
"left bottom" => $this->t("left bottom"),
"right top" => $this->t("right bottom"),
"right center" => $this->t("right center"),
"right bottom" => $this->t("right bottom"),
"center top" => $this->t("center top"),
"center center" => $this->t("center center"),
"center bottom" => $this->t("center bottom"),
],
];
// File extensions input to allow dynamic extensions.
$elements['file_extensions'] = [
'#type' => 'textfield',
'#title' => $this->t('Allowed file extensions'),
'#default_value' => $this->getSetting('file_extensions'),
'#description' => $this->t('Separate extensions with a space or comma. Example: "png jpg jpeg svg webp".'),
'#type' => 'textfield',
'#title' => $this->t('Allowed file extensions'),
'#default_value' => $this->getSetting('file_extensions'),
'#description' => $this->t('Separate extensions with a space or comma. Example: "png jpg jpeg svg webp".'),
];
$elements['file_settings'] = [
'#type' => 'details',
'#title' => $this->t("File Settings"),
'#open' => FALSE,
'#type' => 'details',
'#title' => $this->t("File Settings"),
'#open' => FALSE,
] + $parentElements;
return $elements;
......@@ -247,4 +248,5 @@ class BgImgItem extends ImageItem {
$extensions = preg_split('/[\s,]+/', $this->getSetting('file_extensions'));
$this->file_extensions = implode(' ', array_filter($extensions));
}
}
0% Loading or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment