471 lines
10 KiB
PHP
471 lines
10 KiB
PHP
<?php // phpcs:ignore WordPress.Files.FileName.InvalidClassFileName
|
|
require_once __DIR__ . '/tiled-gallery-layout.php';
|
|
require_once __DIR__ . '/tiled-gallery-shape.php';
|
|
require_once __DIR__ . '/tiled-gallery-item.php';
|
|
|
|
// phpcs:disable Generic.Files.OneObjectStructurePerFile.MultipleFound
|
|
/**
|
|
* Tiled gallery rectangular layout.
|
|
*/
|
|
class Jetpack_Tiled_Gallery_Layout_Rectangular extends Jetpack_Tiled_Gallery_Layout {
|
|
|
|
/**
|
|
* The layout type.
|
|
*
|
|
* @var string
|
|
*/
|
|
protected $type = 'rectangular';
|
|
|
|
/**
|
|
* The HTML function.
|
|
*
|
|
* @param array $context - the context array, unused.
|
|
* @return string HTML
|
|
*/
|
|
public function HTML( $context = array() ) { // phpcs:ignore VariableAnalysis.CodeAnalysis.VariableAnalysis.UnusedVariable
|
|
$grouper = new Jetpack_Tiled_Gallery_Grouper( $this->attachments );
|
|
Jetpack_Tiled_Gallery_Shape::reset_last_shape();
|
|
|
|
return parent::HTML( array( 'rows' => $grouper->grouped_images ) );
|
|
}
|
|
}
|
|
|
|
/**
|
|
* Tiled gallery layout columns class.
|
|
*/
|
|
class Jetpack_Tiled_Gallery_Layout_Columns extends Jetpack_Tiled_Gallery_Layout {
|
|
|
|
/**
|
|
* The layout type.
|
|
*
|
|
* @var string
|
|
*/
|
|
protected $type = 'rectangular'; // It doesn't need separate template for now
|
|
|
|
/**
|
|
* The HTML function.
|
|
*
|
|
* @param array $context - the context array, unused.
|
|
* @return string HTML
|
|
*/
|
|
public function HTML( $context = array() ) { // phpcs:ignore VariableAnalysis.CodeAnalysis.VariableAnalysis.UnusedVariable
|
|
$grouper = new Jetpack_Tiled_Gallery_Grouper( $this->attachments, array( 'Three_Columns', 'Two' ) );
|
|
|
|
return parent::HTML( array( 'rows' => $grouper->grouped_images ) );
|
|
}
|
|
}
|
|
|
|
/**
|
|
* Gallery layout rectangle alis.
|
|
*/
|
|
class Jetpack_Tiled_Gallery_Layout_Rectangle extends Jetpack_Tiled_Gallery_Layout_Rectangular {}
|
|
|
|
/**
|
|
* Image grouping and HTML generation logic class.
|
|
*/
|
|
class Jetpack_Tiled_Gallery_Grouper {
|
|
|
|
/**
|
|
* The margin.
|
|
*
|
|
* @var int
|
|
*/
|
|
public $margin = 4;
|
|
|
|
/**
|
|
* Shapes array.
|
|
* This list is ordered. If you put a shape that's likely to occur on top, it will happen all the time.
|
|
*
|
|
* @var array
|
|
*/
|
|
public $shapes = array(
|
|
'Reverse_Symmetric_Row',
|
|
'Long_Symmetric_Row',
|
|
'Symmetric_Row',
|
|
'One_Three',
|
|
'Three_One',
|
|
'One_Two',
|
|
'Five',
|
|
'Four',
|
|
'Three',
|
|
'Two_One',
|
|
'Panoramic',
|
|
);
|
|
|
|
/**
|
|
* Shape of the last row in gallery.
|
|
*
|
|
* @var string
|
|
*/
|
|
public $last_shape = '';
|
|
|
|
/**
|
|
* All images to be displayed.
|
|
*
|
|
* @var array
|
|
*/
|
|
public $images = array();
|
|
|
|
/**
|
|
* Array of tiled gallery rows (groups of images).
|
|
*
|
|
* @var array
|
|
*/
|
|
public $grouped_images = array();
|
|
|
|
/**
|
|
* Constructor function.
|
|
*
|
|
* @param object $attachments - the attachments.
|
|
* @param array $shapes - the shapes.
|
|
*/
|
|
public function __construct( $attachments, $shapes = array() ) {
|
|
$content_width = Jetpack_Tiled_Gallery::get_content_width();
|
|
|
|
$this->overwrite_shapes( $shapes );
|
|
$this->last_shape = '';
|
|
$this->images = $this->get_images_with_sizes( $attachments );
|
|
$this->grouped_images = $this->get_grouped_images();
|
|
$this->apply_content_width( $content_width );
|
|
}
|
|
|
|
/**
|
|
* Overwrite the shapes.
|
|
*
|
|
* @param array $shapes - the shapes.
|
|
*/
|
|
public function overwrite_shapes( $shapes ) {
|
|
if ( ! empty( $shapes ) ) {
|
|
$this->shapes = $shapes;
|
|
}
|
|
}
|
|
|
|
/**
|
|
* Get the current row size.
|
|
*
|
|
* @return array
|
|
*/
|
|
public function get_current_row_size() {
|
|
$images_left = is_countable( $this->images ) ? count( $this->images ) : 0;
|
|
if ( $images_left < 3 ) {
|
|
return array_fill( 0, $images_left, 1 );
|
|
}
|
|
|
|
foreach ( $this->shapes as $shape_name ) {
|
|
$class_name = "Jetpack_Tiled_Gallery_$shape_name";
|
|
$shape = new $class_name( $this->images );
|
|
if ( $shape->is_possible() ) {
|
|
Jetpack_Tiled_Gallery_Shape::set_last_shape( $class_name );
|
|
return $shape->shape;
|
|
}
|
|
}
|
|
|
|
Jetpack_Tiled_Gallery_Shape::set_last_shape( 'Two' );
|
|
return array( 1, 1 );
|
|
}
|
|
|
|
/**
|
|
* Get images with sizes.
|
|
*
|
|
* @param object $attachments - the attachments.
|
|
*
|
|
* @return array
|
|
*/
|
|
public function get_images_with_sizes( $attachments ) {
|
|
$images_with_sizes = array();
|
|
|
|
foreach ( $attachments as $image ) {
|
|
$meta = wp_get_attachment_metadata( $image->ID );
|
|
$image->width_orig = ( isset( $meta['width'] ) && $meta['width'] > 0 ) ? $meta['width'] : 1;
|
|
$image->height_orig = ( isset( $meta['height'] ) && $meta['height'] > 0 ) ? $meta['height'] : 1;
|
|
$image->ratio = $image->width_orig / $image->height_orig;
|
|
$image->ratio = $image->ratio ? $image->ratio : 1;
|
|
$images_with_sizes[] = $image;
|
|
}
|
|
|
|
return $images_with_sizes;
|
|
}
|
|
|
|
/**
|
|
* Get the current row size.
|
|
*
|
|
* @return array
|
|
*/
|
|
public function read_row() {
|
|
$vector = $this->get_current_row_size();
|
|
|
|
$row = array();
|
|
foreach ( $vector as $group_size ) {
|
|
$row[] = new Jetpack_Tiled_Gallery_Group( array_splice( $this->images, 0, $group_size ) );
|
|
}
|
|
|
|
return $row;
|
|
}
|
|
|
|
/**
|
|
* Get grouped images.
|
|
*
|
|
* @return array
|
|
*/
|
|
public function get_grouped_images() {
|
|
$grouped_images = array();
|
|
|
|
while ( ! empty( $this->images ) ) {
|
|
$grouped_images[] = new Jetpack_Tiled_Gallery_Row( $this->read_row() );
|
|
}
|
|
|
|
return $grouped_images;
|
|
}
|
|
|
|
/**
|
|
* Apply content width.
|
|
*
|
|
* @param int $width - the width.
|
|
*
|
|
* @todo split in functions
|
|
* @todo do not stretch images
|
|
*/
|
|
public function apply_content_width( $width ) {
|
|
foreach ( $this->grouped_images as $row ) {
|
|
$row->width = $width;
|
|
$group_count = is_countable( $row->groups ) ? count( $row->groups ) : 0;
|
|
$row->raw_height = 1 / $row->ratio * ( $width - $this->margin * ( $group_count - $row->weighted_ratio ) );
|
|
$row->height = round( $row->raw_height );
|
|
|
|
$this->calculate_group_sizes( $row );
|
|
}
|
|
}
|
|
|
|
/**
|
|
* Calculate group sizes.
|
|
*
|
|
* @param object $row - the row.
|
|
*/
|
|
public function calculate_group_sizes( $row ) {
|
|
// Storing the calculated group heights in an array for rounding them later while preserving their sum
|
|
// This fixes the rounding error that can lead to a few ugly pixels sticking out in the gallery
|
|
$group_widths_array = array();
|
|
foreach ( $row->groups as $group ) {
|
|
$group->height = $row->height;
|
|
$image_count = is_countable( $group->images ) ? count( $group->images ) : 0;
|
|
// Storing the raw calculations in a separate property to prevent rounding errors from cascading down and for diagnostics
|
|
$group->raw_width = ( $row->raw_height - $this->margin * $image_count ) * $group->ratio + $this->margin;
|
|
$group_widths_array[] = $group->raw_width;
|
|
}
|
|
$rounded_group_widths_array = Jetpack_Constrained_Array_Rounding::get_rounded_constrained_array( $group_widths_array, $row->width );
|
|
|
|
foreach ( $row->groups as $group ) {
|
|
$group->width = array_shift( $rounded_group_widths_array );
|
|
$this->calculate_image_sizes( $group );
|
|
}
|
|
}
|
|
|
|
/**
|
|
* Calculate image sizes.
|
|
*
|
|
* @param object $group - the group of images.
|
|
*/
|
|
public function calculate_image_sizes( $group ) {
|
|
// Storing the calculated image heights in an array for rounding them later while preserving their sum
|
|
// This fixes the rounding error that can lead to a few ugly pixels sticking out in the gallery
|
|
$image_heights_array = array();
|
|
foreach ( $group->images as $image ) {
|
|
$image->width = $group->width - $this->margin;
|
|
// Storing the raw calculations in a separate property for diagnostics
|
|
$image->raw_height = ( $group->raw_width - $this->margin ) / $image->ratio;
|
|
$image_heights_array[] = $image->raw_height;
|
|
}
|
|
|
|
$image_height_sum = $group->height - count( $image_heights_array ) * $this->margin;
|
|
$rounded_image_heights_array = Jetpack_Constrained_Array_Rounding::get_rounded_constrained_array( $image_heights_array, $image_height_sum );
|
|
|
|
foreach ( $group->images as $image ) {
|
|
$image->height = array_shift( $rounded_image_heights_array );
|
|
}
|
|
}
|
|
}
|
|
|
|
/**
|
|
* Jetpack tiled row class.
|
|
*/
|
|
class Jetpack_Tiled_Gallery_Row {
|
|
/**
|
|
* Groups of images
|
|
*
|
|
* @var object[]
|
|
*/
|
|
public $groups;
|
|
|
|
/**
|
|
* Image ratio.
|
|
*
|
|
* @var float
|
|
*/
|
|
public $ratio;
|
|
|
|
/**
|
|
* Weighted ratio based on all the images.
|
|
*
|
|
* @var float
|
|
*/
|
|
public $weighted_ratio;
|
|
|
|
/**
|
|
* Rounded value of the raw width.
|
|
*
|
|
* @var int
|
|
*/
|
|
public $width;
|
|
|
|
/**
|
|
* Rounded value of the raw height.
|
|
*
|
|
* @var int
|
|
*/
|
|
public $height;
|
|
|
|
/**
|
|
* Raw width of the row.
|
|
*
|
|
* @var int
|
|
*/
|
|
public $raw_width;
|
|
|
|
/**
|
|
* Raw height of the row.
|
|
*
|
|
* @var int
|
|
*/
|
|
public $raw_height;
|
|
|
|
/**
|
|
* Constructor class.
|
|
*
|
|
* @param object[] $groups - the group of images.
|
|
*/
|
|
public function __construct( $groups ) {
|
|
$this->groups = $groups;
|
|
$this->ratio = $this->get_ratio();
|
|
$this->weighted_ratio = $this->get_weighted_ratio();
|
|
}
|
|
|
|
/**
|
|
* Get the ratio.
|
|
*
|
|
* @return float
|
|
*/
|
|
public function get_ratio() {
|
|
$ratio = 0;
|
|
foreach ( $this->groups as $group ) {
|
|
$ratio += $group->ratio;
|
|
}
|
|
return $ratio > 0 ? $ratio : 1;
|
|
}
|
|
|
|
/**
|
|
* Get weighted ratio.
|
|
*
|
|
* @return float
|
|
*/
|
|
public function get_weighted_ratio() {
|
|
$weighted_ratio = 0;
|
|
foreach ( $this->groups as $group ) {
|
|
$image_count = is_countable( $group->images ) ? count( $group->images ) : 0;
|
|
$weighted_ratio += $group->ratio * $image_count;
|
|
}
|
|
return $weighted_ratio > 0 ? $weighted_ratio : 1;
|
|
}
|
|
}
|
|
|
|
/**
|
|
* Tiled gallery group class.
|
|
*/
|
|
class Jetpack_Tiled_Gallery_Group {
|
|
/**
|
|
* Images to be displayed in group.
|
|
*
|
|
* @var object[]
|
|
*/
|
|
public $images;
|
|
|
|
/**
|
|
* Image ratio.
|
|
*
|
|
* @var float
|
|
*/
|
|
public $ratio;
|
|
|
|
/**
|
|
* Rounded value of the raw width.
|
|
*
|
|
* @var int
|
|
*/
|
|
public $width;
|
|
|
|
/**
|
|
* Rounded value of the raw height.
|
|
*
|
|
* @var int
|
|
*/
|
|
public $height;
|
|
|
|
/**
|
|
* Raw width of the group.
|
|
*
|
|
* @var int
|
|
*/
|
|
public $raw_width;
|
|
|
|
/**
|
|
* Raw height of the group.
|
|
*
|
|
* @var int
|
|
*/
|
|
public $raw_height;
|
|
|
|
/**
|
|
* Constructor class.
|
|
*
|
|
* @param object[] $images - the images.
|
|
*/
|
|
public function __construct( $images ) {
|
|
$this->images = $images;
|
|
$this->ratio = $this->get_ratio();
|
|
}
|
|
|
|
/**
|
|
* Get the ratio.
|
|
*
|
|
* @return float
|
|
*/
|
|
public function get_ratio() {
|
|
$ratio = 0;
|
|
foreach ( $this->images as $image ) {
|
|
if ( $image->ratio ) {
|
|
$ratio += 1 / $image->ratio;
|
|
}
|
|
}
|
|
if ( ! $ratio ) {
|
|
return 1;
|
|
}
|
|
|
|
return 1 / $ratio;
|
|
}
|
|
|
|
/**
|
|
* The items.
|
|
*
|
|
* @param string $needs_attachment_link - the attachment link.
|
|
* @param bool $grayscale - if the image is in grayscale.
|
|
*
|
|
* @return array
|
|
*/
|
|
public function items( $needs_attachment_link, $grayscale ) {
|
|
$items = array();
|
|
foreach ( $this->images as $image ) {
|
|
$items[] = new Jetpack_Tiled_Gallery_Rectangular_Item( $image, $needs_attachment_link, $grayscale );
|
|
}
|
|
|
|
return $items;
|
|
}
|
|
}
|