diff --git a/.tugboat/config.yml b/.tugboat/config.yml deleted file mode 100644 index b403657a27682c9d949e30d548a1a511b5c68d5f..0000000000000000000000000000000000000000 --- a/.tugboat/config.yml +++ /dev/null @@ -1,51 +0,0 @@ -services: - php: - image: q0rban/tugboat-drupal:9.4 - default: true - http: false - depends: mysql - commands: - update: | - set -eux - # Check out a branch using the unique Tugboat ID for this repository, to - # ensure we don't clobber an existing branch. - git checkout -b $TUGBOAT_REPO_ID - # Composer is hungry. You need a Tugboat project with a pretty sizeable - # chunk of memory. - export COMPOSER_MEMORY_LIMIT=-1 - # This is an environment variable we added in the Dockerfile that - # provides the path to Drupal composer root (not the web root). - cd $DRUPAL_COMPOSER_ROOT - # We configure the Drupal project to use the checkout of the module as a - # Composer package repository. - composer config repositories.tugboat vcs $TUGBOAT_ROOT - # Now we can require this module, specifing the branch name we created - # above that uses the $TUGBOAT_REPO_ID environment variable. - composer require drupal/photoswipe:dev-$TUGBOAT_REPO_ID - # Install Drupal on the site. - vendor/bin/drush \ - --yes \ - --db-url=mysql://tugboat:tugboat@mysql:3306/tugboat \ - --site-name="Live preview for ${TUGBOAT_PREVIEW_NAME}" \ - --account-pass=admin \ - site:install standard - # Set up the files directory permissions. - mkdir -p $DRUPAL_DOCROOT/sites/default/files - chgrp -R www-data $DRUPAL_DOCROOT/sites/default/files - chmod 2775 $DRUPAL_DOCROOT/sites/default/files - chmod -R g+w $DRUPAL_DOCROOT/sites/default/files - # Enable the module. - vendor/bin/drush --yes pm:enable photoswipe - build: | - set -eux - # Delete and re-check out this branch in case this is built from a Base Preview. - git branch -D $TUGBOAT_REPO_ID && git checkout -b $TUGBOAT_REPO_ID || true - export COMPOSER_MEMORY_LIMIT=-1 - cd $DRUPAL_COMPOSER_ROOT - composer install --optimize-autoloader - # Update this module, including all dependencies. - composer update drupal/photoswipe --with-all-dependencies - vendor/bin/drush --yes updb - vendor/bin/drush cache:rebuild - mysql: - image: tugboatqa/mariadb diff --git a/README.md b/README.md index 6e1fefee2f429ca7c094fe45dbaeaffe17f9d0a6..f8219cd80367860904fb335b2c3cbb34e5b6c0ad 100644 --- a/README.md +++ b/README.md @@ -14,20 +14,20 @@ browsing features (in particular swiping to the next picture)! - Require the module, e.g. via composer: "composer require drupal/photoswipe" - Install the module -- Download the "PhotoSwipe-4.1.3" zip file -- Unzip and place the contents of the unzipped "PhotoSwipe-4.1.3" folder +- Download the "PhotoSwipe-5.3.1" zip file +- Unzip and place the contents of the unzipped "PhotoSwipe-5.3.1" folder into "library/photoswipe" folder so that the folder structure is: "library/photoswipe/dist/photoswipe.js" - Check the status report for errors -### Alternative composer installation +### Alternative composer installation (recommended) - Require the module, e.g. via composer: "composer require drupal/photoswipe" - Install the module - Enable usage of third-party libraries using composer, see [here](https://www.drupal.org/docs/develop/using-composer/manage-dependencies#third-party-libraries) for an explanation. - Require the photoswipe library using -"composer require bower-asset/photoswipe:^4" +`composer require bower-asset/photoswipe:^5.3` - Check your status report Then simply configure your image fields to use photoswipe as their field display diff --git a/config/install/photoswipe.settings.yml b/config/install/photoswipe.settings.yml index d986d6c702954dd6d01ed0f1593bfdade05be94a..3141d7023965aaf4e80214ad7a46581f9a6b56eb 100644 --- a/config/install/photoswipe.settings.yml +++ b/config/install/photoswipe.settings.yml @@ -1,28 +1,21 @@ photoswipe_always_load_non_admin: false +enable_cdn: false # @see http://photoswipe.com/documentation/options.html options: -# index: 0 showAnimationDuration: 333 hideAnimationDuration: 333 - showHideOpacity: FALSE bgOpacity: 1 spacing: 0.12 allowPanToNext: TRUE - maxSpreadZoom: 2 + maxZoomLevel: 2 loop: TRUE pinchToClose: TRUE - closeOnScroll: TRUE closeOnVerticalDrag: TRUE - mouseUsed: FALSE escKey: TRUE arrowKeys: TRUE - history: TRUE -# galleryUID: 1 -# galleryPIDs: FALSE errorMsg: '<div class="pswp__error-msg"><a href="%url%" target="_blank">The image</a> could not be loaded.</div>' preload: - 1 - 1 mainClass: NULL - focus: TRUE modal: TRUE diff --git a/config/schema/photoswipe.schema.yml b/config/schema/photoswipe.schema.yml index 4bbc728e7a7411792448341ec0bc2ff535a25933..b7e1d90c997dfdced52988f4b0cadcd78408f15e 100644 --- a/config/schema/photoswipe.schema.yml +++ b/config/schema/photoswipe.schema.yml @@ -4,20 +4,19 @@ photoswipe.settings: mapping: photoswipe_always_load_non_admin: type: boolean + enable_cdn: + label: 'Indicates if CDN is enabled.' + type: boolean options: type: mapping label: Options mapping: -# index: integer showAnimationDuration: type: integer label: 'Show Animation Duration' hideAnimationDuration: type: integer label: 'Hide Animation Duration' - showHideOpacity: - type: boolean - label: 'Show Hide Opacity' bgOpacity: type: float label: 'Background Opacity' @@ -27,35 +26,24 @@ photoswipe.settings: allowPanToNext: type: boolean label: 'Allow Pan to Next' - maxSpreadZoom: + maxZoomLevel: type: integer - label: 'Max Spread Zoom' + label: 'Max Zoom Level' loop: type: boolean label: 'Loop' pinchToClose: type: boolean label: 'Pinch to Close' - closeOnScroll: - type: boolean - label: 'Close on Scroll' closeOnVerticalDrag: type: boolean label: 'Close on Vertical Drag' - mouseUsed: - type: boolean - label: 'Mouse Used' escKey: type: boolean label: 'Escape Key' arrowKeys: type: boolean label: 'Arrow Keys' - history: - type: boolean - label: 'History' - # galleryUID: Integer - # galleryPIDs: Boolean errorMsg: type: string label: 'Error Message' @@ -67,9 +55,6 @@ photoswipe.settings: mainClass: type: string label: 'Main Class' - focus: - type: boolean - label: 'Focus' modal: type: boolean label: 'Modal' diff --git a/drupalci.yml b/drupalci.yml new file mode 100644 index 0000000000000000000000000000000000000000..80262bdb61d812fd7e7e80aa67bfe10150516b4c --- /dev/null +++ b/drupalci.yml @@ -0,0 +1,40 @@ +# https://www.drupal.org/drupalorg/docs/drupal-ci/customizing-drupalci-testing +_phpunit_testgroups_to_execute: &testgroups + testgroups: '--all' + +build: + assessment: + testing: + container_command: + # Install photoswipe library locally. + commands: > + cd ${SOURCE_DIR}; \ + sudo -u www-data composer config --no-plugins allow-plugins.oomphinc/composer-installers-extender true; \ + sudo -u www-data composer require oomphinc/composer-installers-extender; \ + sudo -u www-data composer config --json "extra.installer-paths.web/libraries/{\$name}" '["type:drupal-library", "type:npm-asset", "type:bower-asset"]'; \ + sudo -u www-data composer config repositories.assets '{ "type": "composer", "url": "https://asset-packagist.org" }'; \ + sudo -u www-data composer require "bower-asset/photoswipe:5.3.7"; \ + sudo -u www-data composer require "npm-asset/photoswipe-dynamic-caption-plugin:1.2" + run_tests.kernel: + types: 'PHPUnit-Kernel' + suppress-deprecations: false + halt-on-fail: false + <<: *testgroups + run_tests.functional: + types: 'PHPUnit-Functional' + suppress-deprecations: false + halt-on-fail: false + <<: *testgroups + run_tests.build: + # Limit concurrency due to disk space concerns. + concurrency: 15 + types: 'PHPUnit-Build' + suppress-deprecations: false + halt-on-fail: false + <<: *testgroups + run_tests.javascript: + concurrency: 15 + types: 'PHPUnit-FunctionalJavascript' + suppress-deprecations: false + halt-on-fail: false + <<: *testgroups diff --git a/js/photoswipe.jquery.js b/js/photoswipe.jquery.js deleted file mode 100644 index 7c1b66684e91264f49e14e35972bfa1e78319852..0000000000000000000000000000000000000000 --- a/js/photoswipe.jquery.js +++ /dev/null @@ -1,175 +0,0 @@ -(function ($, Drupal, PhotoSwipe, PhotoSwipeUI_Default) { - Drupal.behaviors.photoswipe = { - /** - * PhotoSwipe Options, coming from Drupal.settings. - */ - photoSwipeOptions: {}, - /** - * Instantiated galleries. - */ - galleries: [], - /** - * Load PhotoSwipe once page is ready - */ - attach: function (context, settings) { - this.photoSwipeOptions = settings.photoswipe ? settings.photoswipe.options : {}; - - // First ensure all photoswipe photos are in a photoswipe-gallery wrapper: - var $imagesWithoutGalleries = $('a.photoswipe', context).filter(function (elem) { - return !$(this).parents('.photoswipe-gallery').length; - }); - if ($imagesWithoutGalleries.length) { - // We have no galleries just individual images. - $imagesWithoutGalleries.each(function (index) { - $imageLink = $(this); - // Add the wrapper and indicate that it's an automatic fallback: - $imageLink.wrap('<span class="photoswipe-gallery photoswipe-gallery--fallback-wrapper"></span>'); - }); - } - - var $galleries = $('.photoswipe-gallery', context); - if ($galleries.length) { - // if body haven't special container for show photoswipe gallery append it. - if (settings.photoswipe && 'container' in settings.photoswipe && !$('.pswp').length) { - $('body').append(settings.photoswipe.container); - } - - // loop through all gallery elements and bind events - $(once('photoswipe', $galleries)).each(function (index) { - var $gallery = $(this); - $gallery.attr('data-pswp-uid', index + 1); - // Definitely prevent doble event binding on AJAX - $gallery.off('click', Drupal.behaviors.photoswipe.onThumbnailsClick); - $gallery.on('click', Drupal.behaviors.photoswipe.onThumbnailsClick); - }); - } - - // Parse URL and open gallery if it contains #&pid=3&gid=1 - var hashData = this.parseHash(); - if (hashData.pid > 0 && hashData.gid > 0) { - this.openPhotoSwipe(hashData.pid - 1, $($galleries[hashData.gid - 1])); - } - }, - /** - * Triggers when user clicks on thumbnail. - * - * Code taken from http://photoswipe.com/documentation/getting-started.html - * and adjusted accordingly. - */ - onThumbnailsClick: function (e) { - e = e || window.event; - var $clickedGallery = $(this); - var eTarget = e.target || e.srcElement; - var $eTarget = $(eTarget); - - // find root element of slide - var $clickedListItem = $eTarget.closest('.photoswipe'); - if (!$clickedListItem) { - return; - } - - // get the index of the clicked element - var index = $clickedGallery.find('.photoswipe').index($clickedListItem); - if (index >= 0) { - e.preventDefault ? e.preventDefault() : e.returnValue = false; - // open PhotoSwipe if valid index found - Drupal.behaviors.photoswipe.openPhotoSwipe(index, $clickedGallery); - // Only prevent default when clicking on a photoswipe image. - return false; - } - }, - /** - * Code taken from http://photoswipe.com/documentation/getting-started.html - * and adjusted accordingly. - */ - openPhotoSwipe: function (index, galleryElement, options) { - var pswpContainer = $('.pswp')[0]; - if (!pswpContainer) { - throw "The photoswipe container is required, but missing on this page. Can not open photoswipe."; - } - var items = []; - options = options || Drupal.behaviors.photoswipe.photoSwipeOptions; - - var images = galleryElement.find('a.photoswipe'); - images.each(function (index) { - var $image = $(this); - var size = $image.data('size') ? $image.data('size').split('x') : ['', '']; - items.push( - { - src: $image.attr('href'), - w: size[0], - h: size[1], - title: $image.data('overlay-title'), - msrc: $image.find('img').attr('src') - } - ); - }) - - // define options - options.index = index; - // define gallery index (for URL) - options.galleryUID = galleryElement.data('pswp-uid'); - - // Add zoom animation function: - options.getThumbBoundsFn = function (index) { - var tn = galleryElement.find('a.photoswipe:eq(' + index + ') img'); - if (tn.length == 0) { - tn = galleryElement.find('a.photoswipe:eq(0) img'); - if (tn.length == 0) { - // Return undefined if still null, see https://www.drupal.org/project/photoswipe/issues/3023442 - return undefined; - } - } - var tw = tn.width(); - var tpos = tn.offset(); - return { x: tpos.left, y: tpos.top, w: tw }; - } - - // Ensures we have items (.photoswipe element) before initializing - // PhotoSwipe so to make PhotoSwipe get along with Blazy, Slick, etc. - if (items.length > 0) { - // Pass data to PhotoSwipe and initialize it - var gallery = new PhotoSwipe(pswpContainer, PhotoSwipeUI_Default, items, options); - gallery.init(); - this.galleries.push(gallery); - } - }, - /** - * Parse picture index and gallery index from URL (#&pid=1&gid=2) - * - * Code taken from http://photoswipe.com/documentation/getting-started.html - * and adjusted accordingly. - */ - parseHash: function () { - var hash = window.location.hash.substring(1), - params = {}; - - if (hash.length < 5) { - return params; - } - - var vars = hash.split('&'); - for (var i = 0; i < vars.length; i++) { - if (!vars[i]) { - continue; - } - var pair = vars[i].split('='); - if (pair.length < 2) { - continue; - } - params[pair[0]] = pair[1]; - } - - if (params.gid) { - params.gid = parseInt(params.gid, 10); - } - - if (!params.hasOwnProperty('pid')) { - return params; - } - params.pid = parseInt(params.pid, 10); - - return params; - } - }; -})(jQuery, Drupal, PhotoSwipe, PhotoSwipeUI_Default); diff --git a/js/photoswipe.js b/js/photoswipe.js new file mode 100644 index 0000000000000000000000000000000000000000..f50472ae61bb7d9e6dab845e8eae2adea9685147 --- /dev/null +++ b/js/photoswipe.js @@ -0,0 +1,38 @@ +(function (Drupal, PhotoSwipeLightbox) { + /** + * Initialises photoswipe galleries. + * + * @type {Drupal~behavior} + */ + Drupal.behaviors.photoswipe = { + + /** + * Initialize photoswipe galleries. + */ + attach: function (context, settings) { + once('photoswipe', '.photoswipe-gallery', context).forEach((gallery) => { + const lightbox = new PhotoSwipeLightbox({ + // Select the gallery. + gallerySelector: '.photoswipe-gallery', + // Elements within gallerySelector (slides). + childSelector: 'a', + // Include PhotoSwipe Core + pswpModule: PhotoSwipe, + ...settings?.photoswipe?.options || {} + }); + + // Adds ability to react on photoswipe initialization. + const event = new CustomEvent('photoswipeLightboxBuild', { + detail: { + lightbox, + } + }); + + gallery.dispatchEvent(event); + + // Initialize. + lightbox.init(); + }); + }, + }; +})(Drupal, PhotoSwipeLightbox); diff --git a/js/prepare-galleries.js b/js/prepare-galleries.js new file mode 100644 index 0000000000000000000000000000000000000000..7977cb389d9712b7a72252ca475b22ebb8ed369d --- /dev/null +++ b/js/prepare-galleries.js @@ -0,0 +1,20 @@ +(function (Drupal) { + /** + * Adds wrapper for images without it. + * + * @type {Drupal~behavior} + */ + Drupal.behaviors.photoswipePrepareGalleries = { + + /** + * Ensure all photoswipe photos are in a photoswipe-gallery wrapper. + */ + attach: function (context) { + once('photoswipePrepareGalleries', 'a.photoswipe', context).forEach(element => { + if (!element.closest('.photoswipe-gallery')) { + element.outerHTML = `<span class="photoswipe-gallery photoswipe-gallery--fallback-wrapper">${element.outerHTML}</span>`; + } + }) + }, + }; +})(Drupal); diff --git a/modules/photoswipe_caption/README.md b/modules/photoswipe_caption/README.md new file mode 100644 index 0000000000000000000000000000000000000000..eb321cdf6f34196370698352f880001a0166647d --- /dev/null +++ b/modules/photoswipe_caption/README.md @@ -0,0 +1,27 @@ +# Provides integration with photoswipe caption plugin. +Starting from [v5](https://photoswipe.com/caption/) of photoswipe there is separate plugin for captions. + +# Installation + +## (optional) Dependencies installation + +This is optional step because we already provide CDN libraries integration, so it should work without local installation. + +### Composer installation (recommended) + +- Enable usage of third-party libraries using composer, see + [here](https://www.drupal.org/docs/develop/using-composer/manage-dependencies#third-party-libraries) for an explanation. +- Install caption library using following composer command: <br> + `composer require "npm-asset/photoswipe-dynamic-caption-plugin:^1.2"` +- Check your status report + +### Manual Installation + +- Clone https://github.com/dimsemenov/photoswipe-dynamic-caption-plugin repository into libraries folder. +- Check the status report for errors + +### Configuration. + +The module has predefined hardcoded [configuration](./config/install/photoswipe_caption.settings.yml). There are two possible ways of altering configuration: +1. (recommended) Using `hook_photoswipe_js_options_alter` simply put custom option in `$settings['captionOptions']`. Check `photoswipe_caption_photoswipe_js_options_alter` for details. +2. Override manually configuration file and import it. diff --git a/modules/photoswipe_caption/config/install/photoswipe_caption.settings.yml b/modules/photoswipe_caption/config/install/photoswipe_caption.settings.yml new file mode 100644 index 0000000000000000000000000000000000000000..a66457ef1e714fdb5127baa946df33131ad98901 --- /dev/null +++ b/modules/photoswipe_caption/config/install/photoswipe_caption.settings.yml @@ -0,0 +1,6 @@ +options: + type: 'auto' + mobileLayoutBreakpoint: 600 + horizontalEdgeThreshold: 20 + mobileCaptionOverlapRatio: 0.3 + verticallyCenterImage: false diff --git a/modules/photoswipe_caption/config/schema/photoswipe_caption.schema.yml b/modules/photoswipe_caption/config/schema/photoswipe_caption.schema.yml new file mode 100644 index 0000000000000000000000000000000000000000..912331ce043fd1c4fa578349fc9f2dbc2a8f2a41 --- /dev/null +++ b/modules/photoswipe_caption/config/schema/photoswipe_caption.schema.yml @@ -0,0 +1,23 @@ +photoswipe_caption.settings: + type: config_object + label: Settings + mapping: + options: + type: mapping + label: Caption options + mapping: + type: + type: string + label: 'Type' + mobileLayoutBreakpoint: + type: integer + label: 'Maximum window width at which mobile layout should be used' + horizontalEdgeThreshold: + type: integer + label: 'Horizontal edge threshold' + mobileCaptionOverlapRatio: + type: float + label: 'Mobile caption overlap ratio' + verticallyCenterImage: + type: boolean + label: 'Vertically center image' diff --git a/modules/photoswipe_caption/js/photoswipe_caption.js b/modules/photoswipe_caption/js/photoswipe_caption.js new file mode 100644 index 0000000000000000000000000000000000000000..503b4e9004d7abb12f7775d98613b7d35869d4a0 --- /dev/null +++ b/modules/photoswipe_caption/js/photoswipe_caption.js @@ -0,0 +1,33 @@ +(function (Drupal, PhotoSwipeDynamicCaption) { + /** + * Adds caption plugin to the photoswipe. + * + * @type {Drupal~behavior} + */ + Drupal.behaviors.photoswipeCaption = { + + /** + * Adds caption plugin to the photoswipe. + */ + attach: function (context, settings) { + const captionOptions = settings?.photoswipe?.options?.captionOptions || {}; + // Remove caption related options from photoswipe options. + delete settings?.photoswipe?.options?.captionOptions; + + // Attaches caption plugin. + once('photoswipeCaption', '.photoswipe-gallery', context).forEach(gallery => { + gallery.addEventListener('photoswipeLightboxBuild', e => { + const lightbox = e.detail.lightbox; + + new PhotoSwipeDynamicCaption(lightbox, { + captionContent: (slide) => { + return slide.data.element.getAttribute('data-overlay-title'); + }, + ...captionOptions, + }); + + }); + }) + }, + }; +})(Drupal, PhotoSwipeDynamicCaption); diff --git a/modules/photoswipe_caption/photoswipe_caption.info.yml b/modules/photoswipe_caption/photoswipe_caption.info.yml new file mode 100644 index 0000000000000000000000000000000000000000..d0eba54b2a9208c77b625d6201114bf3d0a6ba83 --- /dev/null +++ b/modules/photoswipe_caption/photoswipe_caption.info.yml @@ -0,0 +1,7 @@ +name: PhotoSwipe Caption +description: 'Addon with photoswipe Caption plugin' +core_version_requirement: ^9.3 || ^10 +type: module +package: Media +dependencies: + - photoswipe:photoswipe diff --git a/modules/photoswipe_caption/photoswipe_caption.install b/modules/photoswipe_caption/photoswipe_caption.install new file mode 100644 index 0000000000000000000000000000000000000000..012832577eb4d84cc1fe1849bf54853c1f1101f1 --- /dev/null +++ b/modules/photoswipe_caption/photoswipe_caption.install @@ -0,0 +1,94 @@ +<?php + +/** + * @file + * Install, uninstall and update hooks for Photswipe module. + */ + +use Drupal\Core\Link; + +/** + * Implements hook_requirements(). + */ +function photoswipe_caption_requirements($phase) { + $requirements = []; + // If we are not in runtime phase, there is nothing to do. So bail out early. + if ($phase !== 'runtime') { + return []; + } + + $is_cdn_enabled = \Drupal::config('photoswipe.settings')->get('enable_cdn'); + $library_file_finder = \Drupal::service('library.libraries_directory_file_finder'); + $library_discovery = \Drupal::service('library.discovery'); + + // Init. + $library_definition = $library_discovery->getLibraryByName('photoswipe_caption', 'photoswipe_caption.cdn'); + + // We only care about major version. + $version_required = 1; + + $library_req = REQUIREMENT_OK; + $help_text = t(' + <h6> Composer installation (recommended) </h6> + +<p> + - Enable usage of third-party libraries using composer, see [here](https://www.drupal.org/docs/develop/using-composer/manage-dependencies#third-party-libraries) for an explanation. </br> + - Install caption library using following composer command: `composer require "npm-asset/photoswipe-dynamic-caption-plugin:^1.2"` </br> + - Check your status report +</p> + + <h6> Manual Installation </h6> + - Clone https://github.com/dimsemenov/photoswipe-dynamic-caption-plugin repository into libraries folder. </br> + - Check the status report for errors </br> +</p> +'); + + if (!$is_cdn_enabled) { + $library_req = REQUIREMENT_ERROR; + $message = t('<strong>Photoswipe library not found, and is CDN is disabled!</strong>'); + $description = t('You can either enable CDN fetching in configuration (here is @link) and library will be fetched automatically or install it locally. Here is instruction:<br>@helptext', + [ + '@helptext' => $help_text, + '@link' => Link::createFromRoute(t('link'), 'photoswipe.admin_settings')->toString(), + ] + ); + } + // Library from CDN. Show a warning. + elseif (!$library_file_finder->find('photoswipe-dynamic-caption-plugin')) { + $library_version = $library_definition['version']; + $library_req = REQUIREMENT_WARNING; + $message = t('Missing local library. CDN version: @version', ['@version' => $library_version]); + $description = t('Library not found in the "libraries" directory. + You are using the library from the fallback CDN defined in libraries.yml, + but local libraries are preferred over CDN. @helptext', ['@helptext' => $help_text]); + } + elseif (!$library_file_finder->find('photoswipe-dynamic-caption-plugin/package.json')) { + $library_req = REQUIREMENT_ERROR; + $message = t('<strong>Photoswipe caption library found, but missing photoswipe.json detected!</strong>'); + $description = t('Local library folder found, but library seems to be corrupted, please require the photoswipe caption library correctly!', ['@helptext' => $help_text]); + } + else { + $photoswipe_json_content = file_get_contents($library_file_finder->find('photoswipe-dynamic-caption-plugin/package.json')); + $photoswipe_json = json_decode($photoswipe_json_content, TRUE); + $library_version = $photoswipe_json['version']; + // We only care about major version. + [$major] = explode('.', $library_version); + if ((int) $major !== $version_required) { + $library_req = REQUIREMENT_ERROR; + $message = t('Current version supports ^@version.x: Please install appropriate version', [ + '@version' => $version_required, + ]); + $description = t('<strong>You need to install a compatible version!</strong><br><br>@helptext', ['@helptext' => $help_text]); + } + } + + // Requirements. + $requirements['photoswipe_caption'] = [ + 'title' => t('Photoswipe Caption plugin'), + 'severity' => $library_req, + 'value' => $message ?: $version_required, + 'description' => $description ?: '', + ]; + + return $requirements; +} diff --git a/modules/photoswipe_caption/photoswipe_caption.libraries.yml b/modules/photoswipe_caption/photoswipe_caption.libraries.yml new file mode 100644 index 0000000000000000000000000000000000000000..0d213a1d066fcc654f81763db4c2cfbcc74e96e9 --- /dev/null +++ b/modules/photoswipe_caption/photoswipe_caption.libraries.yml @@ -0,0 +1,30 @@ +photoswipe_caption.cdn: + remote: https://github.com/dimsemenov/PhotoSwipe/archive/v5.3.7.zip + version: 1.2.7 + license: + name: MIT + gpl-compatible: false + css: + component: + //unpkg.com/photoswipe-dynamic-caption-plugin/photoswipe-dynamic-caption-plugin.css: { external: true } + js: + //unpkg.com/photoswipe-dynamic-caption-plugin@1.2.7/dist/photoswipe-dynamic-caption-plugin.umd.min.js: { external: true } + +photoswipe_caption.local: + version: VERSION + license: + name: MIT + gpl-compatible: false + css: + component: + /libraries/photoswipe-dynamic-caption-plugin/photoswipe-dynamic-caption-plugin.css: { } + js: + /libraries/photoswipe-dynamic-caption-plugin/dist/photoswipe-dynamic-caption-plugin.umd.min.js: { minified: true } + +photoswipe_caption.init: + js: + js/photoswipe_caption.js: { } + dependencies: + - core/drupal + - core/once + - core/drupalSettings diff --git a/modules/photoswipe_caption/photoswipe_caption.module b/modules/photoswipe_caption/photoswipe_caption.module new file mode 100644 index 0000000000000000000000000000000000000000..11c4d4c6fe8fdcd9483ac212691ce250076a5eca --- /dev/null +++ b/modules/photoswipe_caption/photoswipe_caption.module @@ -0,0 +1,46 @@ +<?php + +/** + * @file + * Container photoswipe_caption hooks. + */ + +/** + * Implements hook_library_info_alter(). + */ +function photoswipe_caption_library_info_alter(&$libraries, $module) { + switch ($module) { + // We need this because we want react on event that is triggered when + // photoswipe is initialized. + case 'photoswipe': + $libraries['photoswipe.init']['dependencies'][] = 'photoswipe_caption/photoswipe_caption.init'; + return; + + // If local library is provided take it, otherwise check if CDN is + // enabled and if so get library from CDN. + case 'photoswipe_caption': + $library_file_finder = \Drupal::service('library.libraries_directory_file_finder'); + $is_local = (bool) $library_file_finder->find('photoswipe-dynamic-caption-plugin'); + + $is_cnd_enabled = \Drupal::config('enable_cdn')->get('enable_cdn'); + + $dependency = match(TRUE) { + $is_local => 'photoswipe_caption/photoswipe_caption.local', + $is_cnd_enabled => 'photoswipe_caption/photoswipe_caption.cdn', + default => NULL, + }; + + if ($dependency !== NULL) { + $libraries['photoswipe_caption.init']['dependencies'][] = $dependency; + } + } +} + +/** + * Implements hook_photoswipe_js_options_alter(). + */ +function photoswipe_caption_photoswipe_js_options_alter(array &$settings) { + $options = $settings['captionOptions'] ?? []; + // Make sure that users can override options. + $settings['captionOptions'] = $options + \Drupal::config('photoswipe_caption.settings')->get('options'); +} diff --git a/modules/photoswipe_caption/tests/FunctionalJavascript/CaptionTest.php b/modules/photoswipe_caption/tests/FunctionalJavascript/CaptionTest.php new file mode 100644 index 0000000000000000000000000000000000000000..811edbcb9fd469b2ea9baab03ef5d34d9c9107e4 --- /dev/null +++ b/modules/photoswipe_caption/tests/FunctionalJavascript/CaptionTest.php @@ -0,0 +1,54 @@ +<?php + +namespace Drupal\Tests\photoswipe\FunctionalJavascript; + +/** + * Tests photoswipe caption module. + * + * @group photoswipe + */ +class CaptionTest extends PhotoswipeTestBase { + + /** + * {@inheritdoc} + */ + protected static $modules = [ + 'test_page_test', + 'file', + 'image', + 'node', + 'field_ui', + 'photoswipe', + 'photoswipe_caption', + ]; + + /** + * Tests if caption is visible. + */ + public function testPhotoswipeFieldFormatterOnNodeDisplay() { + $session = $this->assertSession(); + $page = $this->getSession()->getPage(); + + $this->createImageField('field_test', 'node', 'article', [ + 'uri_scheme' => 'public', + 'required' => 'true', + ], ['alt_field_required' => 1]); + $this->drupalGet('node/add/article'); + $page->fillField('title[0][value]', 'My test content'); + $this->assertNotEmpty($image_upload_field = $page->find('css', '#edit-field-test-0-upload')); + $image_upload_field->attachFile($this->container->get('file_system')->realpath($this->getTestFiles('image')[0]->uri)); + $session->waitForElementVisible('css', '.image-preview'); + + $alt_text = 'Alt text'; + $page->fillField('Alternative text', $alt_text); + $page->pressButton('edit-submit'); + $this->drupalGet('/node/1'); + + $session->waitForElement('css', '.photoswipe-gallery.photoswipe-gallery--fallback-wrapper'); + // Open the photoswipe layer. + $this->getSession()->getPage()->find('css', 'a[href*="image-test.png"].photoswipe')->click(); + $session->waitForElementVisible('css', '.pswp'); + $session->elementTextEquals('css', '.pswp__dynamic-caption', $alt_text); + } + +} diff --git a/photoswipe.install b/photoswipe.install index 80374b60d15bb4821029fb3572469a47f2952321..9cd6ee4727897a0b0e9e4fad65607aa00b2f9914 100644 --- a/photoswipe.install +++ b/photoswipe.install @@ -5,6 +5,8 @@ * Install, uninstall and update hooks for Photswipe module. */ +use Drupal\Core\Link; + /** * Implements hook_requirements(). */ @@ -15,6 +17,7 @@ function photoswipe_requirements($phase) { return []; } + $is_cdn_enabled = \Drupal::config('photoswipe.settings')->get('enable_cdn'); /** @var \Drupal\Core\Asset\LibrariesDirectoryFileFinder $library_file_finder */ $library_file_finder = \Drupal::service('library.libraries_directory_file_finder'); /** @var \Drupal\Core\Asset\LibraryDiscoveryInterface $library_discovery */ @@ -23,7 +26,7 @@ function photoswipe_requirements($phase) { $assets_manager = \Drupal::service('photoswipe.assets_manager'); // Init. - $library_definition = $library_discovery->getLibraryByName('photoswipe', 'photoswipe'); + $library_definition = $library_discovery->getLibraryByName('photoswipe', 'photoswipe.cdn'); $min_req_version = $assets_manager->photoswipeMinPluginVersion; $max_req_version = $assets_manager->photoswipeMaxPluginVersion; $library_req = REQUIREMENT_OK; @@ -36,8 +39,19 @@ function photoswipe_requirements($phase) { '@url' => $library_definition['remote'], ]); - // Library from CDN. Show a warning. - if (!$library_file_finder->find('photoswipe')) { + $is_locally_installed = $library_file_finder->find('photoswipe'); + + if (!$is_cdn_enabled && !$is_locally_installed) { + $library_req = REQUIREMENT_ERROR; + $message = t('<strong>Photoswipe library not found, and is CDN is disabled!</strong>'); + $description = t('You can either enable CDN fetching in configuration (here is @link) and library will be fetched automatically or install it locally. Here is instruction:<br>@helptext', + [ + '@helptext' => $help_text, + '@link' => Link::createFromRoute(t('link'), 'photoswipe.admin_settings')->toString(), + ] + ); + } + elseif (!$is_locally_installed) { $library_version = $library_definition['version']; $library_req = REQUIREMENT_WARNING; $message = t('Missing local library. CDN version: @version', ['@version' => $library_version]); @@ -45,7 +59,7 @@ function photoswipe_requirements($phase) { You are using the library from the fallback CDN defined in libraries.yml, but local libraries are preferred over CDN. @helptext', ['@helptext' => $help_text]); } - elseif (!file_exists($library_file_finder->find('photoswipe/photoswipe.json'))) { + elseif (!file_exists($library_file_finder->find('photoswipe/package.json'))) { $library_req = REQUIREMENT_ERROR; $message = t('<strong>Photoswipe library found, but missing photoswipe.json detected!</strong>'); $description = t('Local library folder found, but library seems to be corrupted, please require the photoswipe library correctly!<br><br>@helptext', ['@helptext' => $help_text]); @@ -53,7 +67,7 @@ function photoswipe_requirements($phase) { // Library detected and local. Check version requirements. else { // We get the json content as an array here: - $photoswipe_json_content = file_get_contents(DRUPAL_ROOT . '/libraries/photoswipe/photoswipe.json'); + $photoswipe_json_content = file_get_contents(DRUPAL_ROOT . '/libraries/photoswipe/package.json'); $photoswipe_json = json_decode($photoswipe_json_content, TRUE); // If the photswipe.json is not empty get version and check if the // installed version does not match version min requirements: @@ -112,3 +126,23 @@ function photoswipe_update_8314() { ->clear('form_id') ->save(); } + +/** + * Removes obsolete configuration options, and enables caption module. + */ +function photoswipe_update_9003() { + $config = \Drupal::configFactory()->getEditable('photoswipe.settings'); + + $config + ->set('enable_cdn', TRUE) + ->clear('showHideOpacity') + ->clear('closeOnScroll') + ->clear('mouseUsed') + ->clear('history') + ->clear('focus') + ->set('maxZoomLevel', $config->get('maxSpreadZoom')) + ->clear('maxSpreadZoom') + ->save(); + + \Drupal::service('module_installer')->install(['photoswipe_caption']); +} diff --git a/photoswipe.libraries.yml b/photoswipe.libraries.yml index b1999224c071a1fafbc8aa642a5c9fc21e079225..f62aa952bc6ed3de9caa9b09492fe21703d4c3d0 100644 --- a/photoswipe.libraries.yml +++ b/photoswipe.libraries.yml @@ -1,39 +1,44 @@ -photoswipe: - remote: https://github.com/dimsemenov/PhotoSwipe/archive/v4.1.3.zip - version: 4.1.3 +photoswipe.cdn: + remote: https://github.com/dimsemenov/PhotoSwipe/archive/v5.3.7.zip + version: 5.3.7 license: name: MIT gpl-compatible: false css: component: - //cdnjs.cloudflare.com/ajax/libs/photoswipe/4.1.3/photoswipe.css: {} - //cdnjs.cloudflare.com/ajax/libs/photoswipe/4.1.3/default-skin/default-skin.css: {} + //cdnjs.cloudflare.com/ajax/libs/photoswipe/5.3.7/photoswipe.min.css: { external: true } js: - //cdnjs.cloudflare.com/ajax/libs/photoswipe/4.1.3/photoswipe.min.js: { minified: true } - //cdnjs.cloudflare.com/ajax/libs/photoswipe/4.1.3/photoswipe-ui-default.min.js: { minified: true } + //cdnjs.cloudflare.com/ajax/libs/photoswipe/5.3.7/umd/photoswipe-lightbox.umd.min.js: { external: true } + //cdnjs.cloudflare.com/ajax/libs/photoswipe/5.3.7/umd/photoswipe.umd.min.js: { external: true } -# Development Version -# Currently unused, see https://www.drupal.org/project/photoswipe/issues/3345238 -photoswipe.dev: - remote: https://github.com/dimsemenov/PhotoSwipe/archive/v4.1.3.zip - version: 4.1.3 +photoswipe.local: + version: VERSION license: name: MIT gpl-compatible: false css: component: - //cdnjs.cloudflare.com/ajax/libs/photoswipe/4.1.3/photoswipe.css: {} - //cdnjs.cloudflare.com/ajax/libs/photoswipe/4.1.3/default-skin/default-skin.css: {} + /libraries/photoswipe/dist/photoswipe.css: {} js: - //cdnjs.cloudflare.com/ajax/libs/photoswipe/4.1.3/photoswipe.js: {} - //cdnjs.cloudflare.com/ajax/libs/photoswipe/4.1.3/photoswipe-ui-default.js: {} + /libraries/photoswipe/dist/umd/photoswipe.umd.min.js: { minified: true } + /libraries/photoswipe/dist/umd/photoswipe-lightbox.umd.min.js: { minified: true } photoswipe.init: js: - js/photoswipe.jquery.js: {} + js/photoswipe.js: { } dependencies: - - core/jquery + - photoswipe/prepare_galleries - core/drupal - core/once - core/drupalSettings - - photoswipe/photoswipe + +# We want to separate preparing galleries logic from photoswipe initialization +# script, because in the new version we've introduced separate module for the +# caption plugin. And this ensures that preparation of galleries logic will not be +# copy pasted, and we will not need to maintain two separate places. +prepare_galleries: + js: + js/prepare-galleries.js: { } + dependencies: + - core/drupal + - core/once diff --git a/photoswipe.module b/photoswipe.module index 934ff4b02231bb571a3897f2d02845779e93d26c..d9dbac761c310d9a7b22b2333c6e8b609a1cda8f 100644 --- a/photoswipe.module +++ b/photoswipe.module @@ -9,6 +9,8 @@ use Drupal\Core\Routing\RouteMatchInterface; /** * Implements hook_libraries_info(). + * + * @todo Investigate if this hook is still needed. */ function photoswipe_libraries_info() { $libraries['photoswipe'] = [ @@ -16,6 +18,7 @@ function photoswipe_libraries_info() { 'vendor url' => 'https://github.com/dimsemenov/PhotoSwipe', 'download url' => 'https://github.com/dimsemenov/PhotoSwipe/archive/master.zip', 'version arguments' => [ + // Probably the path should be changed. 'file' => 'dist/photoswipe.min.js', // PhotoSwipe - v4.1.1 - 2015-12-24. 'pattern' => '/v([\d.]+)/', @@ -50,9 +53,6 @@ function photoswipe_theme() { 'template' => 'photoswipe-image-formatter', 'file' => 'photoswipe.theme.inc', ], - 'photoswipe_container' => [ - 'variables' => [], - ], ]; } @@ -86,87 +86,28 @@ function photoswipe_page_attachments(array &$attachments) { /** * Implements hook_library_info_alter(). + * + * If local library is provided take it, otherwise check if CDN is + * enabled and if so get library from CDN. */ function photoswipe_library_info_alter(&$libraries, $module) { - if ($module == 'photoswipe') { - // In case that the libraries are included locally, use those instead of the - // CDN. - // @see https://www.drupal.org/node/3099614 - $library_file_finder = \Drupal::service('library.libraries_directory_file_finder'); - $current_libraries = [ - 'photoswipe' => [ - 'js' => [ - 'photoswipe/dist/photoswipe.min.js', - 'photoswipe/dist/photoswipe-ui-default.min.js', - ], - 'css' => [ - 'photoswipe/dist/photoswipe.css', - 'photoswipe/dist/default-skin/default-skin.css', - ], - ], - 'photoswipe.dev' => [ - 'js' => [ - 'photoswipe/dist/photoswipe.js', - 'photoswipe/dist/photoswipe-ui-default.js', - ], - 'css' => [ - 'photoswipe/dist/photoswipe.css', - 'photoswipe/dist/default-skin/default-skin.css', - ], - ], - ]; - $is_local = (bool) $library_file_finder->find('photoswipe'); - if ($is_local) { - $photoswipe_json_content = file_get_contents(DRUPAL_ROOT . '/libraries/photoswipe/photoswipe.json'); - $photoswipe_json = json_decode($photoswipe_json_content, TRUE); - // If package.json is empty return and use cdn instead: - if (empty($photoswipe_json)) { - return; - } - foreach ($current_libraries as $current_library_id => $current_library_type) { - // We also update the version to match the local library. - if (isset($libraries[$current_library_id]['version'])) { - $version = $photoswipe_json['version']; - $libraries[$current_library_id]['version'] = $photoswipe_json_content ? $version : $libraries[$current_library_id]['version']; - } + if ($module !== 'photoswipe') { + return; + } + + $library_file_finder = \Drupal::service('library.libraries_directory_file_finder'); + $is_local = (bool) $library_file_finder->find('photoswipe'); - if (isset($libraries[$current_library_id])) { - foreach ($current_library_type as $library_type_id => $current_library_files) { + $is_cnd_enabled = \Drupal::config('photoswipe.settings')->get('enable_cdn'); - // @todo it needs to be refactored. - if ($library_file_finder->find('photoswipe/dist/photoswipe.min.js')) { - if ($library_type_id === 'css') { - $libraries[$current_library_id][$library_type_id]['component'] = []; - } - else { - $libraries[$current_library_id][$library_type_id] = []; - } - } + $dependency = match(TRUE) { + $is_local => 'photoswipe/photoswipe.local', + $is_cnd_enabled => 'photoswipe/photoswipe.cdn', + default => NULL, + }; - foreach ($current_library_files as $current_library_file) { - $path = $library_file_finder->find($current_library_file); - if ($path) { - if ($library_type_id === 'css') { - $libraries[$current_library_id][$library_type_id]['component'] = array_merge( - [ - '/' . $path => [], - ], $libraries[$current_library_id][$library_type_id]['component']); - } - else { - $libraries[$current_library_id][$library_type_id] = array_merge( - [ - '/' . $path => - ($current_library_id === 'photoswipe.dev') - ? [] - : ['minified' => TRUE], - ], $libraries[$current_library_id][$library_type_id]); - } - } - } - } - } - } - } + if ($dependency !== NULL) { + $libraries['photoswipe.init']['dependencies'][] = $dependency; } } diff --git a/src/Form/PhotoswipeAdminSettings.php b/src/Form/PhotoswipeAdminSettings.php index 0ef27ea6957ecd3b989d9619b0b4ebdf3365cd97..778fed22164a951c7455940b2c3c9002d7b786f7 100644 --- a/src/Form/PhotoswipeAdminSettings.php +++ b/src/Form/PhotoswipeAdminSettings.php @@ -4,7 +4,6 @@ namespace Drupal\photoswipe\Form; use Drupal\Core\Form\ConfigFormBase; use Drupal\Core\Form\FormStateInterface; -use Drupal\Core\Render\Element; /** * {@inheritdoc} @@ -18,11 +17,27 @@ class PhotoswipeAdminSettings extends ConfigFormBase { return 'photoswipe_admin_settings'; } - /** + /** * {@inheritdoc} */ - protected function getEditableConfigNames() { - return ['photoswipe.settings']; + public function buildForm(array $form, FormStateInterface $form_state) { + $config = $this->configFactory->get('photoswipe.settings'); + + $form['enable_cdn'] = [ + '#type' => 'checkbox', + '#title' => $this->t('Loads PhotoSwipe library from CDN.'), + '#default_value' => $config->get('enable_cdn'), + '#description' => $this->t('Make sure to check if you can use CDN, because it can be not legally compliant. Check article 28 GDPR'), + ]; + + $form['photoswipe_always_load_non_admin'] = [ + '#type' => 'checkbox', + '#title' => $this->t('Load PhotoSwipe on all non-admin pages'), + '#default_value' => $config->get('photoswipe_always_load_non_admin'), + '#description' => $this->t('Useful if you want to use photoswipe elsewhere by just adding the <code>.photoswipe</code> CSS class.'), + ]; + + return parent::buildForm($form, $form_state); } /** @@ -30,8 +45,9 @@ class PhotoswipeAdminSettings extends ConfigFormBase { */ public function submitForm(array &$form, FormStateInterface $form_state) { $this->config('photoswipe.settings') - ->set('photoswipe_always_load_non_admin', $form_state->getValue('photoswipe_always_load_non_admin')) - ->save(); + ->set('photoswipe_always_load_non_admin', $form_state->getValue('photoswipe_always_load_non_admin')) + ->set('enable_cdn', $form_state->getValue('enable_cdn')) + ->save(); parent::submitForm($form, $form_state); } @@ -39,15 +55,8 @@ class PhotoswipeAdminSettings extends ConfigFormBase { /** * {@inheritdoc} */ - public function buildForm(array $form, FormStateInterface $form_state) { - $form['photoswipe_always_load_non_admin'] = [ - '#type' => 'checkbox', - '#title' => $this->t('Load PhotoSwipe on all non-admin pages'), - '#default_value' => $this->configFactory->get('photoswipe.settings')->get('photoswipe_always_load_non_admin'), - '#description' => $this->t('Useful if you want to use photoswipe elsewhere by just adding the <code>.photoswipe</code> CSS class.'), - ]; - - return parent::buildForm($form, $form_state); + protected function getEditableConfigNames() { + return ['photoswipe.settings']; } } diff --git a/src/PhotoswipeAssetsManager.php b/src/PhotoswipeAssetsManager.php index 6198a59768d81d73af019ff041b6527b3ef453a0..f8f09c63856aedd4cbf1f07512b2f291bab0b6cf 100644 --- a/src/PhotoswipeAssetsManager.php +++ b/src/PhotoswipeAssetsManager.php @@ -17,14 +17,14 @@ class PhotoswipeAssetsManager implements PhotoswipeAssetsManagerInterface { * * @var string */ - public $photoswipeMinPluginVersion = '4.0.0'; + public $photoswipeMinPluginVersion = '5.2.1'; /** * The maximum PhotoSwipe version we support. * * @var string */ - public $photoswipeMaxPluginVersion = '4.1.3'; + public $photoswipeMaxPluginVersion = '5.3.7'; /** * Whether the assets were attached somewhere in this request or not. @@ -99,15 +99,13 @@ class PhotoswipeAssetsManager implements PhotoswipeAssetsManagerInterface { // Add photoswipe js settings. $options = $this->config->get('options'); + // Allow other modules to alter / extend the options to pass to photoswipe // JavaScript. $this->moduleHandler->alter('photoswipe_js_options', $options); $this->themeManager->alter('photoswipe_js_options', $options); $element['#attached']['drupalSettings']['photoswipe']['options'] = $options; - // Add photoswipe container with class="pswp". - $template = ["#theme" => 'photoswipe_container']; - $element['#attached']['drupalSettings']['photoswipe']['container'] = $this->renderer->renderPlain($template); $this->attached = TRUE; } diff --git a/src/PhotoswipePreprocessProcessor.php b/src/PhotoswipePreprocessProcessor.php index f6a93ec80a752f903e98779a4320fd277591e579..155def282f925d480585d45d77071d10b9294c5d 100644 --- a/src/PhotoswipePreprocessProcessor.php +++ b/src/PhotoswipePreprocessProcessor.php @@ -124,7 +124,8 @@ class PhotoswipePreprocessProcessor implements ContainerInjectionInterface { $variables['image'] = $image; $variables['path'] = $this->getPath(); $variables['attributes']['class'][] = 'photoswipe'; - $variables['attributes']['data-size'] = $this->imageDTO->getWidth() . 'x' . $this->imageDTO->getHeight(); + $variables['attributes']['data-pswp-width'] = $this->imageDTO->getWidth(); + $variables['attributes']['data-pswp-height'] = $this->imageDTO->getHeight(); $variables['attributes']['data-overlay-title'] = $this->getCaption(); if (isset($image['#style_name']) && $image['#style_name'] === 'hide') { // Do not display if hidden is selected: diff --git a/templates/photoswipe-container.html.twig b/templates/photoswipe-container.html.twig deleted file mode 100644 index 18e4fe2edaca9028689d69275b689b6aa407b2d2..0000000000000000000000000000000000000000 --- a/templates/photoswipe-container.html.twig +++ /dev/null @@ -1,78 +0,0 @@ -{# Root element of PhotoSwipe. Must have class pswp. #} -<div class="pswp" tabindex="-1" role="dialog" aria-hidden="true"> - - {# - Background of PhotoSwipe. - It's a separate element as animating opacity is faster than rgba(). - #} - <div class="pswp__bg"></div> - - {# Slides wrapper with overflow:hidden. #} - <div class="pswp__scroll-wrap"> - - {# - Container that holds slides. - PhotoSwipe keeps only 3 of them in the DOM to save memory. - Don't modify these 3 pswp__item elements, data is added later on. - #} - - <div class="pswp__container"> - <div class="pswp__item"></div> - <div class="pswp__item"></div> - <div class="pswp__item"></div> - </div> - - {# - Default (PhotoSwipeUI_Default) interface on top of sliding area. - Can be changed. - #} - <div class="pswp__ui pswp__ui--hidden"> - - <div class="pswp__top-bar"> - - {# Controls are self-explanatory. Order can be changed. #} - - <div class="pswp__counter"></div> - - <button class="pswp__button pswp__button--close" title="{{ 'Close (Esc)'|t }}"></button> - - <button class="pswp__button pswp__button--share" title="{{ 'Share'|t }}"></button> - - <button class="pswp__button pswp__button--fs" title="{{ 'Toggle fullscreen'|t }}"></button> - - <button class="pswp__button pswp__button--zoom" title="{{ 'Zoom in/out'|t }}"></button> - - {# - Preloader demo http://codepen.io/dimsemenov/pen/yyBWoR - Element will get class pswp__preloader--active when preloader is - running. - #} - - <div class="pswp__preloader"> - <div class="pswp__preloader__icn"> - <div class="pswp__preloader__cut"> - <div class="pswp__preloader__donut"></div> - </div> - </div> - </div> - </div> - - <div class="pswp__share-modal pswp__share-modal--hidden pswp__single-tap"> - <div class="pswp__share-tooltip"></div> - </div> - - <button class="pswp__button pswp__button--arrow--left" title="{{ 'Previous (arrow left)'|t }}"> - </button> - - <button class="pswp__button pswp__button--arrow--right" title="{{ 'Next (arrow right)'|t }}"> - </button> - - <div class="pswp__caption"> - <div class="pswp__caption__center"></div> - </div> - - </div> - - </div> - -</div> diff --git a/tests/modules/photoswipe_cdn_test/photoswipe_cdn_test.info.yml b/tests/modules/photoswipe_cdn_test/photoswipe_cdn_test.info.yml new file mode 100644 index 0000000000000000000000000000000000000000..f6f98555ef96a09c91cf6bacc4df03fe588c74d8 --- /dev/null +++ b/tests/modules/photoswipe_cdn_test/photoswipe_cdn_test.info.yml @@ -0,0 +1,5 @@ +name: 'Photoswipe cdn test' +description: 'Adds ability to test CDN.' +type: module +package: Testing +core_version_requirement: ^9.3 || ^10 diff --git a/tests/modules/photoswipe_cdn_test/src/LibrariesDirectoryFileFinder.php b/tests/modules/photoswipe_cdn_test/src/LibrariesDirectoryFileFinder.php new file mode 100644 index 0000000000000000000000000000000000000000..6d9108221fa2a784ec64eec4e5ecbeb98eb0a90b --- /dev/null +++ b/tests/modules/photoswipe_cdn_test/src/LibrariesDirectoryFileFinder.php @@ -0,0 +1,25 @@ +<?php + +// @phpcs:ignoreFile + +namespace Drupal\photoswipe_cdn_test; + +use Drupal\Core\Asset\LibrariesDirectoryFileFinder as CoreLibrariesDirectoryFileFinder; + +/** + * Wraps cores finder to provide mock functionality. + */ +class LibrariesDirectoryFileFinder extends CoreLibrariesDirectoryFileFinder { + + /** + * Adds ability to mock situation when library locally is missing. + */ + public function find($path) { + if ($path === 'photoswipe' && \Drupal::config('photoswipe.settings')->get('enable_cdn')) { + return FALSE; + } + + return parent::find($path); + } + +} diff --git a/tests/modules/photoswipe_cdn_test/src/PhotoswipeCdnTestServiceProvider.php b/tests/modules/photoswipe_cdn_test/src/PhotoswipeCdnTestServiceProvider.php new file mode 100644 index 0000000000000000000000000000000000000000..0c81900ca83327cccd64e034540d3739082f108f --- /dev/null +++ b/tests/modules/photoswipe_cdn_test/src/PhotoswipeCdnTestServiceProvider.php @@ -0,0 +1,23 @@ +<?php + +namespace Drupal\photoswipe_cdn_test; + +use Drupal\Core\DependencyInjection\ContainerBuilder; +use Drupal\Core\DependencyInjection\ServiceProviderBase; + +/** + * Alter order receipt subscriber. + */ +class PhotoswipeCdnTestServiceProvider extends ServiceProviderBase { + + /** + * {@inheritDoc} + */ + public function alter(ContainerBuilder $container) { + if ($container->hasDefinition('library.libraries_directory_file_finder')) { + $definition = $container->getDefinition('library.libraries_directory_file_finder'); + $definition->setClass(LibrariesDirectoryFileFinder::class); + } + } + +} diff --git a/tests/src/Functional/GeneralPhotoswipeTest.php b/tests/src/Functional/GeneralPhotoswipeTest.php index 6cb0d8711a7d66f3413b62c0327d4e2657443e32..6e9f6e804e5aaeb425112c76232f04f7f40358eb 100644 --- a/tests/src/Functional/GeneralPhotoswipeTest.php +++ b/tests/src/Functional/GeneralPhotoswipeTest.php @@ -90,7 +90,7 @@ class GeneralPhotoswipeTest extends BrowserTestBase { // (The library shouldn't be loaded in the front page): $this->drupalGet('<front>'); $session->statusCodeEquals(200); - $session->elementNotExists('css', 'link[href*="//cdnjs.cloudflare.com/ajax/libs/photoswipe/4.1.3/photoswipe.css"]'); + $session->elementNotExists('css', 'link[href*="//cdnjs.cloudflare.com/ajax/libs/photoswipe/5.2.2/photoswipe.min.css"]'); // Go to the settings page and enable loading on non admin pages: $this->drupalGet('/admin/config/media/photoswipe'); $session->statusCodeEquals(200); @@ -99,7 +99,7 @@ class GeneralPhotoswipeTest extends BrowserTestBase { // Go to the front page again and check if the css file is loaded // (The library shouldn't be loaded in the front page): $this->drupalGet('<front>'); - $session->elementNotExists('css', 'link[href*="//cdnjs.cloudflare.com/ajax/libs/photoswipe/4.1.3/photoswipe.css"]'); + $session->elementNotExists('css', 'link[href*="//cdnjs.cloudflare.com/ajax/libs/photoswipe/5.2.2/photoswipe.min.css"]'); $session->statusCodeEquals(200); } @@ -120,7 +120,7 @@ class GeneralPhotoswipeTest extends BrowserTestBase { if ($library_path !== FALSE) { // Library installed in libraries dir :) // So we get library version from photoswipe.json file. - $package_json_content = file_get_contents(DRUPAL_ROOT . '/libraries/photoswipe/photoswipe.json'); + $package_json_content = file_get_contents(DRUPAL_ROOT . '/libraries/photoswipe/package.json'); $package_json = json_decode($package_json_content, FALSE); $installed_version = $package_json->version; } diff --git a/tests/src/FunctionalJavascript/ImageFileTest.php b/tests/src/FunctionalJavascript/ImageFileTest.php index f93290ddea806bc79a095b369a7d1c2001f401f1..ee474d96d7fe48ac08e91a783d3ada32f93c8390 100644 --- a/tests/src/FunctionalJavascript/ImageFileTest.php +++ b/tests/src/FunctionalJavascript/ImageFileTest.php @@ -2,9 +2,6 @@ namespace Drupal\Tests\photoswipe\FunctionalJavascript; -use Drupal\field\Entity\FieldConfig; -use Drupal\field\Entity\FieldStorageConfig; -use Drupal\FunctionalJavascriptTests\WebDriverTestBase; use Drupal\Tests\TestFileCreationTrait; /** @@ -12,7 +9,7 @@ use Drupal\Tests\TestFileCreationTrait; * * @group photoswipe */ -class ImageFileTest extends WebDriverTestBase { +class ImageFileTest extends PhotoswipeTestBase { use TestFileCreationTrait; /** @@ -27,112 +24,14 @@ class ImageFileTest extends WebDriverTestBase { 'node', 'field_ui', 'photoswipe', + 'photoswipe_cdn_test', ]; - /** - * A user with admin permissions. - * - * @var \Drupal\Core\Session\AccountInterface - */ - protected $adminUser; - - /** - * A user with authenticated permissions. - * - * @var \Drupal\Core\Session\AccountInterface - */ - protected $user; - /** * {@inheritdoc} */ protected $defaultTheme = 'stark'; - /** - * {@inheritdoc} - */ - protected function setUp(): void { - parent::setUp(); - - $this->publicFilesDirectory = 'public://'; - $this->config('system.site')->set('page.front', '/test-page')->save(); - - $this->user = $this->drupalCreateUser([]); - $this->adminUser = $this->drupalCreateUser([]); - $this->adminUser->addRole($this->createAdminRole('admin', 'admin')); - $this->adminUser->save(); - $this->drupalLogin($this->adminUser); - - $this->drupalCreateContentType(['type' => 'article', 'name' => 'Article']); - } - - /** - * Create a new image field. - * - * Create a new image field. - * Modified Version of Drupal\Tests\image\Kernel\ImageFieldCreationTrait - * "createImageField" function. - * - * @param string $name - * The name of the new field (all lowercase), exclude the "field_" prefix. - * @param string $entity_type_id - * The entity type that this field will be added to. - * @param string $bundle_id - * The entity type bundle that this field will be added to. - * @param array $storage_settings - * (optional) A list of field storage settings that will be added to the - * defaults. - * @param array $field_settings - * (optional) A list of instance settings that will be added to the instance - * defaults. - * @param array $widget_settings - * (optional) Widget settings to be added to the widget defaults. - * @param array $formatter_settings - * (optional) Formatter settings to be added to the formatter defaults. - * @param string $formatter_type - * (optional) The formatter type, defaults to 'photoswipe_field_formatter'. - * @param string $description - * (optional) A description for the field. Defaults to ''. - */ - protected function createImageField($name, $entity_type_id = 'node', $bundle_id = 'article', array $storage_settings = [], array $field_settings = [], array $widget_settings = [], array $formatter_settings = [], $formatter_type = 'photoswipe_field_formatter', $description = '') { - FieldStorageConfig::create([ - 'field_name' => $name, - 'entity_type' => $entity_type_id, - 'type' => 'image', - 'settings' => $storage_settings, - 'cardinality' => !empty($storage_settings['cardinality']) ? $storage_settings['cardinality'] : 1, - ])->save(); - - $field_config = FieldConfig::create([ - 'field_name' => $name, - 'label' => $name, - 'entity_type' => $entity_type_id, - 'bundle' => $bundle_id, - 'required' => !empty($field_settings['required']), - 'settings' => $field_settings, - 'description' => $description, - ]); - $field_config->save(); - - /** @var \Drupal\Core\Entity\EntityDisplayRepositoryInterface $display_repository */ - $display_repository = \Drupal::service('entity_display.repository'); - $display_repository->getFormDisplay($entity_type_id, $bundle_id) - ->setComponent($name, [ - 'type' => 'image_image', - 'settings' => $widget_settings, - ]) - ->save(); - - $display_repository->getViewDisplay($entity_type_id, $bundle_id) - ->setComponent($name, [ - 'type' => $formatter_type, - 'settings' => $formatter_settings, - ]) - ->save(); - - return $field_config; - } - // /** // * Tests if the Photoswipe field formatter settings exist. // */ @@ -169,6 +68,64 @@ class ImageFileTest extends WebDriverTestBase { // $session->pageTextContains('Your settings have been saved.'); // } + /** + * Tests situation when local library is missing and cdn is enabled. + */ + public function testCdnLibrary() { + // We install library locally during drupal_ci build. Because of this + // photoswipe_cdn_test module provides ability to mock situation when CDN + // is enabled. + // @see \Drupal\photoswipe_cdn_test\LibrariesDirectoryFileFinder::find + \Drupal::configFactory()->getEditable('photoswipe.settings')->set('enable_cdn', TRUE)->save(); + $session = $this->assertSession(); + $page = $this->getSession()->getPage(); + + $field_settings = ['alt_field_required' => 1]; + $this->createImageField('field_test', 'node', 'article', [ + 'uri_scheme' => 'public', + 'required' => 'true', + ], $field_settings); + // Create the node with a test file uploaded: + $this->drupalGet('node/add/article'); + $title = 'My test content'; + $page->fillField('title[0][value]', $title); + $this->assertNotEmpty($image_upload_field = $page->find('css', '#edit-field-test-0-upload')); + $image = $this->getTestFiles('image')[0]; + $image_upload_field->attachFile($this->container->get('file_system')->realpath($image->uri)); + $session->waitForElementVisible('css', '.image-preview'); + $session->pageTextContains('Alternative text'); + $page->fillField('Alternative text', 'Alt text'); + $page->pressButton('edit-submit'); + $session->pageTextContains("Article {$title} has been created."); + $this->drupalGet('/node/1'); + $this->validateCdnLibraries($session); + // Check if the fallback wrapper is loaded with the correct + // classes and attributes: + // Wait for the JavaScript to initialize the fallback wrapper: + $session->waitForElement('css', '.photoswipe-gallery.photoswipe-gallery--fallback-wrapper'); + $session->elementExists('css', '.photoswipe-gallery'); + $session->elementExists('css', '.photoswipe-gallery.photoswipe-gallery--fallback-wrapper'); + // Check if the anker element is set with the correct classes, wrappers and + // attributes: + $session->elementExists('css', 'a[href*="image-test.png"].photoswipe'); + $session->elementExists('css', '.photoswipe-gallery.photoswipe-gallery--fallback-wrapper > a[href*="image-test.png"].photoswipe'); + $session->elementAttributeExists('css', 'a[href*="image-test.png"].photoswipe', 'data-pswp-width'); + $session->elementAttributeContains('css', 'a[href*="image-test.png"].photoswipe', 'data-overlay-title', 'Alt text'); + // Check if the image is loaded with the correct defaults and wrappers: + $session->elementExists('css', 'img[src*="image-test.png"]'); + $session->elementExists('css', 'a[href*="image-test.png"].photoswipe > img[src*="image-test.png"]'); + $session->elementExists('css', '.photoswipe-gallery.photoswipe-gallery--fallback-wrapper > a[href*="image-test.png"].photoswipe > img[src*="image-test.png"]'); + // Uploaded pictures are not broken during testing, but only on later + // inspection. See https://www.drupal.org/project/drupal/issues/3272192. + $session->elementAttributeContains('css', 'img[src*="image-test.png"]', 'width', '40'); + $session->elementAttributeContains('css', 'img[src*="image-test.png"]', 'height', '20'); + $this->getSession()->getPage()->find('css', 'a[href*="image-test.png"].photoswipe')->click(); + $session->waitForElementVisible('css', '.pswp'); + + // Disable cdn. + \Drupal::configFactory()->getEditable('photoswipe.settings')->set('enable_cdn', FALSE)->save(); + } + /** * Tests the photoswipe formatter on node display. */ @@ -195,23 +152,17 @@ class ImageFileTest extends WebDriverTestBase { $session->pageTextContains("Article {$title} has been created."); $this->drupalGet('/node/1'); // $this->getSession()->wait(5000, "document.readyState === 'complete'"); - // Check if all necessary js and css files are loaded: - $session->elementExists('css', 'link[href*="//cdnjs.cloudflare.com/ajax/libs/photoswipe/4.1.3/photoswipe.css"]'); - $session->elementExists('css', 'link[href*="//cdnjs.cloudflare.com/ajax/libs/photoswipe/4.1.3/default-skin/default-skin.css"]'); - $session->elementExists('css', 'script[src*="//cdnjs.cloudflare.com/ajax/libs/photoswipe/4.1.3/photoswipe.min.js"]'); - $session->elementExists('css', 'script[src*="//cdnjs.cloudflare.com/ajax/libs/photoswipe/4.1.3/photoswipe-ui-default.min.js"]'); // Check if the fallback wrapper is loaded with the correct // classes and attributes: // Wait for the JavaScript to initialize the fallback wrapper: $session->waitForElement('css', '.photoswipe-gallery.photoswipe-gallery--fallback-wrapper'); $session->elementExists('css', '.photoswipe-gallery'); $session->elementExists('css', '.photoswipe-gallery.photoswipe-gallery--fallback-wrapper'); - $session->elementAttributeExists('css', '.photoswipe-gallery.photoswipe-gallery--fallback-wrapper', 'data-pswp-uid'); // Check if the anker element is set with the correct classes, wrappers and // attributes: $session->elementExists('css', 'a[href*="image-test.png"].photoswipe'); $session->elementExists('css', '.photoswipe-gallery.photoswipe-gallery--fallback-wrapper > a[href*="image-test.png"].photoswipe'); - $session->elementAttributeExists('css', 'a[href*="image-test.png"].photoswipe', 'data-size'); + $session->elementAttributeExists('css', 'a[href*="image-test.png"].photoswipe', 'data-pswp-width'); $session->elementAttributeContains('css', 'a[href*="image-test.png"].photoswipe', 'data-overlay-title', 'Alt text'); // Check if the image is loaded with the correct defaults and wrappers: $session->elementExists('css', 'img[src*="image-test.png"]'); @@ -317,23 +268,17 @@ class ImageFileTest extends WebDriverTestBase { $page->pressButton('edit-submit'); $session->pageTextContains("Article {$title} has been created."); $this->drupalGet('/node/1'); - // Check if all necessary js and css files are loaded: - $session->elementExists('css', 'link[href*="//cdnjs.cloudflare.com/ajax/libs/photoswipe/4.1.3/photoswipe.css"]'); - $session->elementExists('css', 'link[href*="//cdnjs.cloudflare.com/ajax/libs/photoswipe/4.1.3/default-skin/default-skin.css"]'); - $session->elementExists('css', 'script[src*="//cdnjs.cloudflare.com/ajax/libs/photoswipe/4.1.3/photoswipe.min.js"]'); - $session->elementExists('css', 'script[src*="//cdnjs.cloudflare.com/ajax/libs/photoswipe/4.1.3/photoswipe-ui-default.min.js"]'); // Check if the fallback wrapper is loaded with the correct // classes and attributes: // Wait for the JavaScript to initialize the fallback wrapper: $session->waitForElement('css', '.photoswipe-gallery.photoswipe-gallery--fallback-wrapper'); $session->elementExists('css', '.photoswipe-gallery'); $session->elementExists('css', '.photoswipe-gallery.photoswipe-gallery--fallback-wrapper'); - $session->elementAttributeExists('css', '.photoswipe-gallery.photoswipe-gallery--fallback-wrapper', 'data-pswp-uid'); // Check if the anker element is set with the correct classes, wrappers and // attributes: $session->elementExists('css', 'a[href*="image-test.png"].photoswipe'); $session->elementExists('css', '.photoswipe-gallery.photoswipe-gallery--fallback-wrapper > a[href*="image-test.png"].photoswipe'); - $session->elementAttributeExists('css', 'a[href*="image-test.png"].photoswipe', 'data-size'); + $session->elementAttributeExists('css', 'a[href*="image-test.png"].photoswipe', 'data-pswp-width'); // Check if the image is loaded with the correct defaults and wrappers: $session->elementExists('css', 'img[src*="image-test.png"]'); $session->elementExists('css', 'a[href*="image-test.png"].photoswipe > img[src*="image-test.png"]'); @@ -344,7 +289,7 @@ class ImageFileTest extends WebDriverTestBase { // attributes for the second picture: $session->elementExists('css', 'a[href*="image-test_0.png"].photoswipe'); $session->elementExists('css', '.photoswipe-gallery.photoswipe-gallery--fallback-wrapper > a[href*="image-test_0.png"].photoswipe'); - $session->elementAttributeExists('css', 'a[href*="image-test_0.png"].photoswipe', 'data-size'); + $session->elementAttributeExists('css', 'a[href*="image-test_0.png"].photoswipe', 'data-pswp-width'); // Check if the image is loaded with the correct defaults and wrappers for // the second picture: $session->elementExists('css', 'img[src*="image-test_0.png"]'); @@ -354,7 +299,6 @@ class ImageFileTest extends WebDriverTestBase { // inspection. See https://www.drupal.org/project/drupal/issues/3272192. $session->elementAttributeContains('css', 'img[src*="image-test_0.png"]', 'width', '40'); $session->elementAttributeContains('css', 'img[src*="image-test_0.png"]', 'height', '20'); - // @todo Check the photoswipe functionalities here. } /** @@ -386,11 +330,6 @@ class ImageFileTest extends WebDriverTestBase { $page->pressButton('edit-submit'); $session->pageTextContains("Article {$title} has been created."); $this->drupalGet('/node/1'); - // Check if all necessary js and css files are loaded: - $session->elementExists('css', 'link[href*="//cdnjs.cloudflare.com/ajax/libs/photoswipe/4.1.3/photoswipe.css"]'); - $session->elementExists('css', 'link[href*="//cdnjs.cloudflare.com/ajax/libs/photoswipe/4.1.3/default-skin/default-skin.css"]'); - $session->elementExists('css', 'script[src*="//cdnjs.cloudflare.com/ajax/libs/photoswipe/4.1.3/photoswipe.min.js"]'); - $session->elementExists('css', 'script[src*="//cdnjs.cloudflare.com/ajax/libs/photoswipe/4.1.3/photoswipe-ui-default.min.js"]'); // Check if the fallback wrapper is loaded with the correct // classes and attributes: $session->elementExists('css', '.photoswipe-gallery'); @@ -398,13 +337,12 @@ class ImageFileTest extends WebDriverTestBase { $session->elementNotExists('css', 'div.photoswipe-gallery--fallback-wrapper'); // Check, that there is no fallback wrapper span: $session->elementNotExists('css', '.photoswipe-gallery--fallback-wrapper'); - $session->elementAttributeExists('css', 'div.photoswipe-gallery', 'data-pswp-uid'); // Check if the anker element is set with the correct classes, wrappers and // attributes for the first picture: $session->elementExists('css', 'a[href*="image-test.png"].photoswipe'); $session->elementExists('css', '.photoswipe-gallery div > a[href*="image-test.png"].photoswipe'); - $session->elementAttributeExists('css', 'a[href*="image-test.png"].photoswipe', 'data-size'); + $session->elementAttributeExists('css', 'a[href*="image-test.png"].photoswipe', 'data-pswp-width'); // Check if the image is loaded with the correct defaults and wrappers for // the first picture: $session->elementExists('css', 'img[src*="image-test.png"]'); @@ -416,7 +354,7 @@ class ImageFileTest extends WebDriverTestBase { // attributes for the second picture: $session->elementExists('css', 'a[href*="image-test_0.png"].photoswipe'); $session->elementExists('css', '.photoswipe-gallery div> a[href*="image-test_0.png"].photoswipe'); - $session->elementAttributeExists('css', 'a[href*="image-test_0.png"].photoswipe', 'data-size'); + $session->elementAttributeExists('css', 'a[href*="image-test_0.png"].photoswipe', 'data-pswp-width'); // Check if the image is loaded with the correct defaults and wrappers for // the second picture: $session->elementExists('css', 'img[src*="image-test_0.png"]'); diff --git a/tests/src/FunctionalJavascript/MediaReferenceTest.php b/tests/src/FunctionalJavascript/MediaReferenceTest.php index f97d727c0670d615c00bfdae940e87bee61207fc..4e88b5e4d30531d0a9de5283fca1754b920e77de 100644 --- a/tests/src/FunctionalJavascript/MediaReferenceTest.php +++ b/tests/src/FunctionalJavascript/MediaReferenceTest.php @@ -2,7 +2,6 @@ namespace Drupal\Tests\photoswipe\FunctionalJavascript; -use Drupal\FunctionalJavascriptTests\WebDriverTestBase; use Drupal\Tests\field\Traits\EntityReferenceTestTrait; use Drupal\Tests\media\Traits\MediaTypeCreationTrait; use Drupal\Tests\TestFileCreationTrait; @@ -12,7 +11,7 @@ use Drupal\Tests\TestFileCreationTrait; * * @group photoswipe */ -class MediaReferenceTest extends WebDriverTestBase { +class MediaReferenceTest extends PhotoswipeTestBase { use TestFileCreationTrait, EntityReferenceTestTrait, MediaTypeCreationTrait; /** @@ -30,43 +29,11 @@ class MediaReferenceTest extends WebDriverTestBase { 'photoswipe', ]; - /** - * A user with admin permissions. - * - * @var \Drupal\Core\Session\AccountInterface - */ - protected $adminUser; - - /** - * A user with authenticated permissions. - * - * @var \Drupal\Core\Session\AccountInterface - */ - protected $user; - /** * {@inheritdoc} */ protected $defaultTheme = 'stark'; - /** - * {@inheritdoc} - */ - protected function setUp(): void { - parent::setUp(); - - $this->publicFilesDirectory = 'public://'; - $this->config('system.site')->set('page.front', '/test-page')->save(); - - $this->user = $this->drupalCreateUser([]); - $this->adminUser = $this->drupalCreateUser([]); - $this->adminUser->addRole($this->createAdminRole('admin', 'admin')); - $this->adminUser->save(); - $this->drupalLogin($this->adminUser); - - $this->drupalCreateContentType(['type' => 'article', 'name' => 'Article']); - } - /** * Helper function to create a media image. */ @@ -170,11 +137,6 @@ class MediaReferenceTest extends WebDriverTestBase { $session->pageTextContains("Article {$title} has been created."); $this->getSession()->wait(5000, 'typeof window.jQuery == "function"'); $this->drupalGet('/node/1'); - // // Check if all necessary js and css files are loaded: - $session->elementExists('css', 'link[href*="//cdnjs.cloudflare.com/ajax/libs/photoswipe/4.1.3/photoswipe.css"]'); - $session->elementExists('css', 'link[href*="//cdnjs.cloudflare.com/ajax/libs/photoswipe/4.1.3/default-skin/default-skin.css"]'); - $session->elementExists('css', 'script[src*="//cdnjs.cloudflare.com/ajax/libs/photoswipe/4.1.3/photoswipe.min.js"]'); - $session->elementExists('css', 'script[src*="//cdnjs.cloudflare.com/ajax/libs/photoswipe/4.1.3/photoswipe-ui-default.min.js"]'); // // Check if the fallback wrapper is loaded with the correct // // classes and attributes: // Wait for the JavaScript to initialize the fallback wrapper: @@ -182,12 +144,11 @@ class MediaReferenceTest extends WebDriverTestBase { $session->waitForElement('css', '.photoswipe-gallery.photoswipe-gallery--fallback-wrapper'); $session->elementExists('css', '.photoswipe-gallery'); $session->elementExists('css', '.photoswipe-gallery.photoswipe-gallery--fallback-wrapper'); - $session->elementAttributeExists('css', '.photoswipe-gallery.photoswipe-gallery--fallback-wrapper', 'data-pswp-uid'); // Check if the anker element is set with the correct classes, wrappers and // attributes: $session->elementExists('css', 'a[href*="image-test.png"].photoswipe'); $session->elementExists('css', '.photoswipe-gallery.photoswipe-gallery--fallback-wrapper > a[href*="image-test.png"].photoswipe'); - $session->elementAttributeExists('css', 'a[href*="image-test.png"].photoswipe', 'data-size'); + $session->elementAttributeExists('css', 'a[href*="image-test.png"].photoswipe', 'data-pswp-width'); $session->elementAttributeContains('css', 'a[href*="image-test.png"].photoswipe', 'data-overlay-title', 'Alt text'); // Check if the image is loaded with the correct defaults and wrappers: $session->elementExists('css', 'img[src*="image-test.png"]'); @@ -408,23 +369,17 @@ class MediaReferenceTest extends WebDriverTestBase { $page->pressButton('edit-submit'); $session->pageTextContains("Article {$title} has been created."); $this->drupalGet('/node/1'); - // Check if all necessary js and css files are loaded: - $session->elementExists('css', 'link[href*="//cdnjs.cloudflare.com/ajax/libs/photoswipe/4.1.3/photoswipe.css"]'); - $session->elementExists('css', 'link[href*="//cdnjs.cloudflare.com/ajax/libs/photoswipe/4.1.3/default-skin/default-skin.css"]'); - $session->elementExists('css', 'script[src*="//cdnjs.cloudflare.com/ajax/libs/photoswipe/4.1.3/photoswipe.min.js"]'); - $session->elementExists('css', 'script[src*="//cdnjs.cloudflare.com/ajax/libs/photoswipe/4.1.3/photoswipe-ui-default.min.js"]'); // Check if the fallback wrapper is loaded with the correct // classes and attributes: // Wait for the JavaScript to initialize the fallback wrapper: $session->waitForElement('css', '.photoswipe-gallery.photoswipe-gallery--fallback-wrapper'); $session->elementExists('css', '.photoswipe-gallery'); $session->elementExists('css', '.photoswipe-gallery.photoswipe-gallery--fallback-wrapper'); - $session->elementAttributeExists('css', '.photoswipe-gallery.photoswipe-gallery--fallback-wrapper', 'data-pswp-uid'); // Check if the anker element is set with the correct classes, wrappers and // attributes: $session->elementExists('css', 'a[href*="image-test.png"].photoswipe'); $session->elementExists('css', '.photoswipe-gallery.photoswipe-gallery--fallback-wrapper > a[href*="image-test.png"].photoswipe'); - $session->elementAttributeExists('css', 'a[href*="image-test.png"].photoswipe', 'data-size'); + $session->elementAttributeExists('css', 'a[href*="image-test.png"].photoswipe', 'data-pswp-width'); $session->elementAttributeContains('css', 'a[href*="image-test.png"].photoswipe', 'data-overlay-title', 'Alt text'); // Check if the image is loaded with the correct defaults and wrappers: $session->elementExists('css', 'img[src*="image-test.png"]'); @@ -476,11 +431,6 @@ class MediaReferenceTest extends WebDriverTestBase { $page->fillField('media_image (value 2)', 'image-test.png'); $page->pressButton('edit-submit'); $this->drupalGet('/node/1'); - // Check if all necessary js and css files are loaded: - $session->elementExists('css', 'link[href*="//cdnjs.cloudflare.com/ajax/libs/photoswipe/4.1.3/photoswipe.css"]'); - $session->elementExists('css', 'link[href*="//cdnjs.cloudflare.com/ajax/libs/photoswipe/4.1.3/default-skin/default-skin.css"]'); - $session->elementExists('css', 'script[src*="//cdnjs.cloudflare.com/ajax/libs/photoswipe/4.1.3/photoswipe.min.js"]'); - $session->elementExists('css', 'script[src*="//cdnjs.cloudflare.com/ajax/libs/photoswipe/4.1.3/photoswipe-ui-default.min.js"]'); // Check if the fallback wrapper is loaded with the correct // classes and attributes: $session->elementExists('css', 'div.photoswipe-gallery'); @@ -488,13 +438,12 @@ class MediaReferenceTest extends WebDriverTestBase { $session->elementNotExists('css', 'div.photoswipe-gallery--fallback-wrapper'); // Check, that there is no fallback wrapper span: $session->elementNotExists('css', '.photoswipe-gallery--fallback-wrapper'); - $session->elementAttributeExists('css', 'div.photoswipe-gallery', 'data-pswp-uid'); // Check if the anker element is set with the correct classes, wrappers and // attributes for the first picture: $session->elementExists('css', 'a[href*="image-test.png"].photoswipe'); $session->elementExists('css', 'div.photoswipe-gallery div > a[href*="image-test.png"].photoswipe'); - $session->elementAttributeExists('css', 'a[href*="image-test.png"].photoswipe', 'data-size'); + $session->elementAttributeExists('css', 'a[href*="image-test.png"].photoswipe', 'data-pswp-width'); // Check if the image is loaded with the correct defaults and wrappers for // the first picture: $session->elementExists('css', 'img[src*="image-test.png"]'); diff --git a/tests/src/FunctionalJavascript/PhotoswipeTestBase.php b/tests/src/FunctionalJavascript/PhotoswipeTestBase.php new file mode 100644 index 0000000000000000000000000000000000000000..c3aebab48029f832060be52bf4cf30b72a0f0c64 --- /dev/null +++ b/tests/src/FunctionalJavascript/PhotoswipeTestBase.php @@ -0,0 +1,129 @@ +<?php + +namespace Drupal\Tests\photoswipe\FunctionalJavascript; + +use Drupal\field\Entity\FieldConfig; +use Drupal\field\Entity\FieldStorageConfig; +use Drupal\FunctionalJavascriptTests\WebDriverTestBase; + +/** + * Tests the photoswipe display setting on an image file. + * + * @group photoswipe + */ +abstract class PhotoswipeTestBase extends WebDriverTestBase { + + /** + * A user with admin permissions. + * + * @var \Drupal\Core\Session\AccountInterface + */ + protected $adminUser; + + /** + * A user with authenticated permissions. + * + * @var \Drupal\Core\Session\AccountInterface + */ + protected $user; + + /** + * {@inheritdoc} + */ + protected $defaultTheme = 'stark'; + + /** + * {@inheritdoc} + */ + protected function setUp(): void { + parent::setUp(); + + $this->publicFilesDirectory = 'public://'; + $this->config('system.site')->set('page.front', '/test-page')->save(); + + $this->user = $this->drupalCreateUser([]); + $this->adminUser = $this->drupalCreateUser([]); + $this->adminUser->addRole($this->createAdminRole('admin', 'admin')); + $this->adminUser->save(); + $this->drupalLogin($this->adminUser); + + $this->drupalCreateContentType(['type' => 'article', 'name' => 'Article']); + } + + /** + * Validates if cdn libraries are loaded properly. + */ + protected function validateCdnLibraries($session): void { + $session->elementExists('css', 'link[href*="//cdnjs.cloudflare.com/ajax/libs/photoswipe/5.3.7/photoswipe.min.css"]'); + $session->elementExists('css', 'script[src*="//cdnjs.cloudflare.com/ajax/libs/photoswipe/5.3.7/umd/photoswipe-lightbox.umd.min.js"]'); + $session->elementExists('css', 'script[src*="//cdnjs.cloudflare.com/ajax/libs/photoswipe/5.3.7/umd/photoswipe.umd.min.js"]'); + } + + /** + * Create a new image field. + * + * Create a new image field. + * Modified Version of Drupal\Tests\image\Kernel\ImageFieldCreationTrait + * "createImageField" function. + * + * @param string $name + * The name of the new field (all lowercase), exclude the "field_" prefix. + * @param string $entity_type_id + * The entity type that this field will be added to. + * @param string $bundle_id + * The entity type bundle that this field will be added to. + * @param array $storage_settings + * (optional) A list of field storage settings that will be added to the + * defaults. + * @param array $field_settings + * (optional) A list of instance settings that will be added to the instance + * defaults. + * @param array $widget_settings + * (optional) Widget settings to be added to the widget defaults. + * @param array $formatter_settings + * (optional) Formatter settings to be added to the formatter defaults. + * @param string $formatter_type + * (optional) The formatter type, defaults to 'photoswipe_field_formatter'. + * @param string $description + * (optional) A description for the field. Defaults to ''. + */ + protected function createImageField($name, $entity_type_id = 'node', $bundle_id = 'article', array $storage_settings = [], array $field_settings = [], array $widget_settings = [], array $formatter_settings = [], $formatter_type = 'photoswipe_field_formatter', $description = '') { + FieldStorageConfig::create([ + 'field_name' => $name, + 'entity_type' => $entity_type_id, + 'type' => 'image', + 'settings' => $storage_settings, + 'cardinality' => !empty($storage_settings['cardinality']) ? $storage_settings['cardinality'] : 1, + ])->save(); + + $field_config = FieldConfig::create([ + 'field_name' => $name, + 'label' => $name, + 'entity_type' => $entity_type_id, + 'bundle' => $bundle_id, + 'required' => !empty($field_settings['required']), + 'settings' => $field_settings, + 'description' => $description, + ]); + $field_config->save(); + + /** @var \Drupal\Core\Entity\EntityDisplayRepositoryInterface $display_repository */ + $display_repository = \Drupal::service('entity_display.repository'); + $display_repository->getFormDisplay($entity_type_id, $bundle_id) + ->setComponent($name, [ + 'type' => 'image_image', + 'settings' => $widget_settings, + ]) + ->save(); + + $display_repository->getViewDisplay($entity_type_id, $bundle_id) + ->setComponent($name, [ + 'type' => $formatter_type, + 'settings' => $formatter_settings, + ]) + ->save(); + + return $field_config; + } + +}