Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Enable captions on Gallery shortcodes #3659

Merged
merged 50 commits into from
Nov 26, 2019
Merged
Show file tree
Hide file tree
Changes from 21 commits
Commits
Show all changes
50 commits
Select commit Hold shift + click to select a range
1b34cef
Enable captions on Gallery shortcodes
kienstra Oct 29, 2019
dde1e46
Rename a $images to $images_and_captions for clarity
kienstra Oct 29, 2019
a48d974
Address a PHPCS issue with array destructuring
kienstra Oct 29, 2019
5c7334b
Rename get_carousel_dimensions() to get_dimensions()
kienstra Oct 29, 2019
641e008
Make the $dom property protected, improve a DocBlock
kienstra Oct 29, 2019
cbd925b
Add the parameter name to the @param tag
kienstra Oct 29, 2019
5e07516
Fix a typo in 'associative'
kienstra Oct 29, 2019
93246e8
Use <amp-lightbox-gallery> for lightboxes
kienstra Oct 29, 2019
08404be
Exit if ! $images, before running count( $images )
kienstra Oct 29, 2019
0caa844
Merge branch 'develop' into add/gallery-shortcode-captions
kienstra Oct 29, 2019
2c32f41
Merge branch 'develop' into add/gallery-shortcode-captions
kienstra Nov 7, 2019
22ae686
Merge branch 'develop' of github.com:ampproject/amp-wp into add/galle…
westonruter Nov 11, 2019
82b428a
Change @since tag from 1.4.1 to 1.5.0
kienstra Nov 11, 2019
d3ba063
Commit Alain's classes to represent and collect images
kienstra Nov 11, 2019
93aa3ea
Account for 0.0 or 0 width or height in dimensions function
kienstra Nov 11, 2019
6ba9bdb
Fix phpcs issues that caused a failed Travis build
kienstra Nov 11, 2019
2ed1653
Update return tag, as it no longer returns null
kienstra Nov 11, 2019
5794193
Move the image list classes to an AMP namespace in amp/
kienstra Nov 15, 2019
78b0c75
Might revert: try adding composer dump-autoload to .travis.yml
kienstra Nov 15, 2019
3125261
Add use statements to the top of some files
kienstra Nov 15, 2019
67c7590
Revert edit to .travis.yml, try another approach
kienstra Nov 15, 2019
692d14b
Move the AMP_Carousel class to the AMP namespace
kienstra Nov 15, 2019
8eb54a8
Add internal tag to class Carousel, move tags up in other classes
kienstra Nov 15, 2019
07cfc97
Align param tag descriptions, pass '' instead of null
kienstra Nov 15, 2019
c0a5e05
Merge branch 'develop' into add/gallery-shortcode-captions
kienstra Nov 15, 2019
7e206ef
Move new classes to src/component directory, per discussion
kienstra Nov 19, 2019
3f0ee52
Import classes, preventing need for the \ operator
kienstra Nov 19, 2019
2b4a98f
In Carousel, accept Image_List in constructor
kienstra Nov 19, 2019
284b328
Remove parameter from Carousel::get_dimensions()
kienstra Nov 19, 2019
d7fdbd2
Change directory to Component, make classes PascalCase
kienstra Nov 19, 2019
be2b4e2
Correct covers and var tags
kienstra Nov 19, 2019
12c6d26
Remove the Image class, and simply use a DOMElement
kienstra Nov 21, 2019
951cd3f
Add a rule to enforce PascalCase file names in src/*
kienstra Nov 21, 2019
12f062e
Merge branch 'develop' into add/gallery-shortcode-captions
kienstra Nov 21, 2019
92a764e
Rename ImageList to DOMElementList
kienstra Nov 22, 2019
7b603ea
Commit Weston's suggestion to change the package to Amp\AmpWP
kienstra Nov 22, 2019
305e471
Change other package names
kienstra Nov 22, 2019
8de2340
Revert cloning at least for now, remove test for immutability
kienstra Nov 23, 2019
3cdd86f
Clone the DOMElementList in add(), and return the clone
kienstra Nov 24, 2019
097d1b8
Update the DocBlock of DOMElementList::add()
kienstra Nov 24, 2019
873c41a
Edit DocBlocks, include correcting var tag
kienstra Nov 24, 2019
38df209
Make $elements propert private again
kienstra Nov 25, 2019
f48d09b
Commit Alain's suggestion to make the Carousel class final
kienstra Nov 25, 2019
5a8749c
Update src/Component/Carousel.php
kienstra Nov 25, 2019
0355530
Commit Alain's suggestion to make `$images` private
kienstra Nov 25, 2019
450f9cd
In Carousel, rename $images to $slides
kienstra Nov 25, 2019
0ae904e
Also rename images to slides in Test_Carousel
kienstra Nov 25, 2019
4ac1d25
Remove optimize-autoloader from composer.json config, will apply this…
kienstra Nov 25, 2019
478f71e
Make get_dimensions() private instead of public
kienstra Nov 25, 2019
c7d5d6e
Add the -o flag to composer install for production build processes
kienstra Nov 26, 2019
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
6 changes: 6 additions & 0 deletions composer.json
Original file line number Diff line number Diff line change
Expand Up @@ -33,6 +33,7 @@
"ext-zip": "Enables the use of ZipArchive to export AMP Stories."
},
"config": {
"optimize-autoloader": true,
Copy link
Contributor Author

@kienstra kienstra Nov 15, 2019

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This ensures that the classmaps for the files in src/ are regenerated with composer install. Otherwise, I think it's necessary to run composer install -o.

Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This should be removed, and a corresponding change should be made to the build process instead.

If an optimized autoloader is forced, then you'll have to constantly rebuild the plugin on filesystem changes even during development.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Sure, it's removed in 4ac1d25. Next, I'll apply in in the build processes.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

c7d5d6e adds the -o flag to composer install only for production build processes and when creating a pre-release.

Maybe it should should also be added to .travis.yml, but I thought the optimization wouldn't be worth the trouble in debugging if the build is cached:

The performance gains are not worth the trouble in a development setting.

"platform": {
"php": "5.4"
},
Expand All @@ -44,5 +45,10 @@
"PHP-CSS-Parser: Fix parsing CSS selectors which contain commas <https://github.com/sabberworm/PHP-CSS-Parser/pull/138>": "https://github.com/sabberworm/PHP-CSS-Parser/commit/fa139f65c5b098ae652c970b25e6eb03fc495eb4.diff"
}
}
},
"autoload": {
"psr-4": {
"AMP\\": "includes/amp/"
}
}
}
44 changes: 44 additions & 0 deletions includes/amp/class-captioned-image.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,44 @@
<?php
/**
* Class Captioned_Image
*
* @package AMP
*/

namespace AMP;
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

We should try to keep the AMP namespace structured from the start, to not end up with an ever-growing flat list of objects in the namespace folder. Once we start really going down the OOP route, we'll more separate classes with less code in each, so we need to plan ahead.

The root namespace should be reserved for the most fundamental interfaces/building blocks, and then have a few meaningful subnamespaces for the rest of the classes.

What we might need so far (just a first thought, really):

- AMP
    - Administration
    - Component
    - EmbedHandler
    - Sanitizer
    - Validation
    - Widget

Do we want to add a placeholder namespace, like Utility here ?

Copy link
Contributor Author

@kienstra kienstra Nov 19, 2019

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Good idea, the current directory to namespace mapping is:

src/component : Amp\AmpWP\Component

How does that look?


/**
* Class Captioned_Image
*
* @since 1.5.0
* @internal
*/
final class Captioned_Image extends Image implements Has_Caption {

/**
* The caption text.
*
* @var string
*/
private $caption;

/**
* Constructs the class.
*
* @param \DOMElement $image_node The image node.
* @param string $caption The caption text.
*/
public function __construct( \DOMElement $image_node, $caption ) {
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I suggest always importing all classes, even the non-namespaced ones. This will not only get rid of the \ in front of them, make it more readable, but also will add a clear list of external dependencies at the top of each class:

use DOMElement;

This list of dependencies is very valuable later down the road for debugging and refactoring.

Suggested change
public function __construct( \DOMElement $image_node, $caption ) {
public function __construct( DOMElement $image_node, $caption ) {

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Thanks, 3f0ee52 imports the classes.

parent::__construct( $image_node );
$this->caption = $caption;
}

/**
* Gets the caption text.
*
* @return string The caption text.
*/
public function get_caption() {
return $this->caption;
}
}
23 changes: 23 additions & 0 deletions includes/amp/class-has-caption.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,23 @@
<?php
/**
* Interface Has_Caption
*
* @package AMP
*/

namespace AMP;

/**
* Interface Has_Caption
*
* @since 1.5.0
* @internal
*/
interface Has_Caption {
/**
* Gets the caption.
*
* @return string The caption text.
*/
public function get_caption();
}
57 changes: 57 additions & 0 deletions includes/amp/class-image-list.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,57 @@
<?php
/**
* Class Image_List
*
* @package AMP
*/

namespace AMP;

/**
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Again, I suggest importing all external dependencies, as that makes it very clear what to watch out for later when refactoring or diagnosing bugs.

Suggested change
/**
use ArrayIterator;
use Countable;
use DOMElement;
use IteratorAggregate;
/**

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Ah, good idea. 3f0ee52 imports the classes.

Your commit above looks good, but I moved the files to src/component/ earlier. I should have committed that suggestion first 😄

* Class Image_List
*
* @since 1.5.0
* @internal
*/
final class Image_List implements \IteratorAggregate, \Countable {

/**
* The captioned images.
*
* @var Captioned_Image[]
*/
private $elements = [];

/**
* Adds an image to the list.
*
* @param \DOMElement $image_node The image to add.
* @param string $caption The caption to add.
* @return self
*/
public function add( \DOMElement $image_node, $caption = '' ) {
$this->elements[] = empty( $caption ) ? new Image( $image_node ) : new Captioned_Image( $image_node, $caption );
return $this;
}

/**
* Gets an iterator with the elements.
*
* This together with the IteratorAggregate turns the object into a "Traversable",
* so you can just foreach over it and receive its elements in the correct type.
*
* @return \ArrayIterator An iterator with the elements.
*/
public function getIterator() {
return new \ArrayIterator( $this->elements );
}

/**
* Gets the count of the images.
*
* @return int The number of images.
*/
public function count() {
return count( $this->elements );
}
}
42 changes: 42 additions & 0 deletions includes/amp/class-image.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,42 @@
<?php
/**
* Class Image
*
* @package AMP
*/

namespace AMP;

/**
* Class Image
*
* @since 1.5.0
* @internal
*/
class Image {

/**
* The image node.
*
* @var \DOMElement
*/
protected $image_node;

/**
* Constructs the class.
*
* @param \DOMElement $image_node The image node.
*/
public function __construct( \DOMElement $image_node ) {
$this->image_node = $image_node;
}

/**
* Gets the image.
*
* @return \DOMElement
*/
public function get_image_node() {
return $this->image_node;
}
}
1 change: 1 addition & 0 deletions includes/class-amp-autoloader.php
Original file line number Diff line number Diff line change
Expand Up @@ -96,6 +96,7 @@ class AMP_Autoloader {
'AMP_Content' => 'includes/templates/class-amp-content',
'AMP_Content_Sanitizer' => 'includes/templates/class-amp-content-sanitizer',
'AMP_Post_Template' => 'includes/templates/class-amp-post-template',
'AMP_Carousel' => 'includes/utils/class-amp-carousel',
'AMP_DOM_Utils' => 'includes/utils/class-amp-dom-utils',
'AMP_HTML_Utils' => 'includes/utils/class-amp-html-utils',
'AMP_Image_Dimension_Extractor' => 'includes/utils/class-amp-image-dimension-extractor',
Expand Down
67 changes: 23 additions & 44 deletions includes/embeds/class-amp-gallery-embed.php
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,8 @@
* @package AMP
*/

use AMP\Image_List;

/**
* Class AMP_Gallery_Embed_Handler
*
Expand Down Expand Up @@ -129,25 +131,14 @@ public function shortcode( $attr ) {
'width' => $width,
'height' => $height,
'alt' => trim( wp_strip_all_tags( get_post_meta( $attachment_id, '_wp_attachment_image_alt', true ) ) ), // Logic from wp_get_attachment_image().
'id' => $attachment_id,
];
}

$args = [
'images' => $urls,
'images' => $urls,
'lightbox' => ! empty( $atts['lightbox'] ),
];
if ( ! empty( $atts['lightbox'] ) ) {
$args['lightbox'] = true;
$lightbox_tag = AMP_HTML_Utils::build_tag(
'amp-image-lightbox',
[
'id' => AMP_Base_Sanitizer::AMP_IMAGE_LIGHTBOX_ID,
'layout' => 'nodisplay',
'data-close-button-aria-label' => __( 'Close', 'amp' ),
]
);
/* We need to add lightbox tag, too. @todo Could there be a better alternative for this? */
return $this->render( $args ) . $lightbox_tag;
}
Copy link
Contributor Author

@kienstra kienstra Oct 29, 2019

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This is now using amp-lightbox-gallery as recommended by amphtml, so all that's needed is a lightbox attribute on the <amp-img> or <amp-carousel>. This plugin automatically adds the amp-lightbox-gallery component script.


return $this->render( $args );
}
Expand Down Expand Up @@ -211,6 +202,7 @@ public function maybe_override_gallery( $html, $attributes ) {
* @return string Rendered.
*/
public function render( $args ) {
$dom = new DOMDocument();
$this->did_convert_elements = true;

$args = wp_parse_args(
Expand All @@ -224,11 +216,7 @@ public function render( $args ) {
return '';
}

$max_aspect_ratio = 0;
$carousel_width = 0;
$carousel_height = 0;

$images = [];
$images = new Image_List();
foreach ( $args['images'] as $props ) {
$image_atts = [
'src' => $props['url'],
Expand All @@ -241,47 +229,38 @@ public function render( $args ) {
$image_atts['srcset'] = $props['srcset'];
}

$this_aspect_ratio = $props['width'] / $props['height'];
if ( $this_aspect_ratio > $max_aspect_ratio ) {
$max_aspect_ratio = $this_aspect_ratio;
$carousel_width = $props['width'];
$carousel_height = $props['height'];
}

if ( ! empty( $args['lightbox'] ) ) {
$image_atts['lightbox'] = '';
$image_atts['on'] = 'tap:' . AMP_Img_Sanitizer::AMP_IMAGE_LIGHTBOX_ID;
$image_atts['role'] = 'button';
$image_atts['tabindex'] = 0;
}
$image = AMP_HTML_Utils::build_tag(
$image = AMP_DOM_Utils::create_node(
$dom,
'amp-img',
$image_atts
);

if ( ! empty( $props['href'] ) ) {
$image = AMP_HTML_Utils::build_tag(
$previous_image = $image;
$image = AMP_DOM_Utils::create_node(
$dom,
'a',
[
'href' => $props['href'],
],
$image
]
);
$image->appendChild( $previous_image );
}

$images[] = $image;
$caption = isset( $props['id'] ) ? wp_get_attachment_caption( $props['id'] ) : '';
$images->add( $image, $caption );
}

return AMP_HTML_Utils::build_tag(
'amp-carousel',
[
'width' => $carousel_width,
'height' => $carousel_height,
'type' => 'slides',
'layout' => 'responsive',
],
implode( PHP_EOL, $images )
);
$amp_carousel = new AMP_Carousel( $dom );
$carousel_node = $amp_carousel->create_and_get( $images );

// Prevent an error in get_content_from_dom_node() when it calls $node->parentNode->insertBefore().
$dom->appendChild( $carousel_node );

return AMP_DOM_Utils::get_content_from_dom_node( $dom, $carousel_node );
}

/**
Expand Down
Loading