Code Coverage
 
Lines
Functions and Methods
Classes and Traits
Total
0.00% covered (danger)
0.00%
0 / 97
0.00% covered (danger)
0.00%
0 / 17
CRAP
0.00% covered (danger)
0.00%
0 / 5
Jetpack_Tiled_Gallery_Layout_Rectangular
0.00% covered (danger)
0.00%
0 / 3
0.00% covered (danger)
0.00%
0 / 1
2
0.00% covered (danger)
0.00%
0 / 1
 HTML
0.00% covered (danger)
0.00%
0 / 3
0.00% covered (danger)
0.00%
0 / 1
2
Jetpack_Tiled_Gallery_Layout_Columns
0.00% covered (danger)
0.00%
0 / 2
0.00% covered (danger)
0.00%
0 / 1
2
0.00% covered (danger)
0.00%
0 / 1
 HTML
0.00% covered (danger)
0.00%
0 / 2
0.00% covered (danger)
0.00%
0 / 1
2
Jetpack_Tiled_Gallery_Layout_Rectangle
n/a
0 / 0
n/a
0 / 0
0
n/a
0 / 0
Jetpack_Tiled_Gallery_Grouper
0.00% covered (danger)
0.00%
0 / 62
0.00% covered (danger)
0.00%
0 / 9
870
0.00% covered (danger)
0.00%
0 / 1
 __construct
0.00% covered (danger)
0.00%
0 / 6
0.00% covered (danger)
0.00%
0 / 1
2
 overwrite_shapes
0.00% covered (danger)
0.00%
0 / 2
0.00% covered (danger)
0.00%
0 / 1
6
 get_current_row_size
0.00% covered (danger)
0.00%
0 / 11
0.00% covered (danger)
0.00%
0 / 1
30
 get_images_with_sizes
0.00% covered (danger)
0.00%
0 / 9
0.00% covered (danger)
0.00%
0 / 1
56
 read_row
0.00% covered (danger)
0.00%
0 / 5
0.00% covered (danger)
0.00%
0 / 1
6
 get_grouped_images
0.00% covered (danger)
0.00%
0 / 4
0.00% covered (danger)
0.00%
0 / 1
6
 apply_content_width
0.00% covered (danger)
0.00%
0 / 6
0.00% covered (danger)
0.00%
0 / 1
12
 calculate_group_sizes
0.00% covered (danger)
0.00%
0 / 10
0.00% covered (danger)
0.00%
0 / 1
20
 calculate_image_sizes
0.00% covered (danger)
0.00%
0 / 9
0.00% covered (danger)
0.00%
0 / 1
12
Jetpack_Tiled_Gallery_Row
0.00% covered (danger)
0.00%
0 / 12
0.00% covered (danger)
0.00%
0 / 3
72
0.00% covered (danger)
0.00%
0 / 1
 __construct
0.00% covered (danger)
0.00%
0 / 3
0.00% covered (danger)
0.00%
0 / 1
2
 get_ratio
0.00% covered (danger)
0.00%
0 / 4
0.00% covered (danger)
0.00%
0 / 1
12
 get_weighted_ratio
0.00% covered (danger)
0.00%
0 / 5
0.00% covered (danger)
0.00%
0 / 1
20
Jetpack_Tiled_Gallery_Group
0.00% covered (danger)
0.00%
0 / 13
0.00% covered (danger)
0.00%
0 / 3
56
0.00% covered (danger)
0.00%
0 / 1
 __construct
0.00% covered (danger)
0.00%
0 / 2
0.00% covered (danger)
0.00%
0 / 1
2
 get_ratio
0.00% covered (danger)
0.00%
0 / 7
0.00% covered (danger)
0.00%
0 / 1
20
 items
0.00% covered (danger)
0.00%
0 / 4
0.00% covered (danger)
0.00%
0 / 1
6
1<?php // phpcs:ignore WordPress.Files.FileName.InvalidClassFileName
2
3if ( ! defined( 'ABSPATH' ) ) {
4    exit( 0 );
5}
6
7require_once __DIR__ . '/tiled-gallery-layout.php';
8require_once __DIR__ . '/tiled-gallery-shape.php';
9require_once __DIR__ . '/tiled-gallery-item.php';
10
11// phpcs:disable Generic.Files.OneObjectStructurePerFile.MultipleFound
12/**
13 * Tiled gallery rectangular layout.
14 */
15class Jetpack_Tiled_Gallery_Layout_Rectangular extends Jetpack_Tiled_Gallery_Layout {
16
17    /**
18     * The layout type.
19     *
20     * @var string
21     */
22    protected $type = 'rectangular';
23
24    /**
25     * The HTML function.
26     *
27     * @param array $context - the context array, unused.
28     * @return string HTML
29     */
30    public function HTML( $context = array() ) { // phpcs:ignore VariableAnalysis.CodeAnalysis.VariableAnalysis.UnusedVariable
31        $grouper = new Jetpack_Tiled_Gallery_Grouper( $this->attachments );
32        Jetpack_Tiled_Gallery_Shape::reset_last_shape();
33
34        return parent::HTML( array( 'rows' => $grouper->grouped_images ) );
35    }
36}
37
38/**
39 * Tiled gallery layout columns class.
40 */
41class Jetpack_Tiled_Gallery_Layout_Columns extends Jetpack_Tiled_Gallery_Layout {
42
43    /**
44     * The layout type.
45     *
46     * @var string
47     */
48    protected $type = 'rectangular'; // It doesn't need separate template for now
49
50    /**
51     * The HTML function.
52     *
53     * @param array $context - the context array, unused.
54     * @return string HTML
55     */
56    public function HTML( $context = array() ) { // phpcs:ignore VariableAnalysis.CodeAnalysis.VariableAnalysis.UnusedVariable
57        $grouper = new Jetpack_Tiled_Gallery_Grouper( $this->attachments, array( 'Three_Columns', 'Two' ) );
58
59        return parent::HTML( array( 'rows' => $grouper->grouped_images ) );
60    }
61}
62
63/**
64 * Gallery layout rectangle alis.
65 */
66class Jetpack_Tiled_Gallery_Layout_Rectangle extends Jetpack_Tiled_Gallery_Layout_Rectangular {}
67
68/**
69 * Image grouping and HTML generation logic class.
70 */
71class Jetpack_Tiled_Gallery_Grouper {
72
73    /**
74     * The margin.
75     *
76     * @var int
77     */
78    public $margin = 4;
79
80    /**
81     * Shapes array.
82     * This list is ordered. If you put a shape that's likely to occur on top, it will happen all the time.
83     *
84     * @var array
85     */
86    public $shapes = array(
87        'Reverse_Symmetric_Row',
88        'Long_Symmetric_Row',
89        'Symmetric_Row',
90        'One_Three',
91        'Three_One',
92        'One_Two',
93        'Five',
94        'Four',
95        'Three',
96        'Two_One',
97        'Panoramic',
98    );
99
100    /**
101     * Shape of the last row in gallery.
102     *
103     * @var string
104     */
105    public $last_shape = '';
106
107    /**
108     * All images to be displayed.
109     *
110     * @var array
111     */
112    public $images = array();
113
114    /**
115     * Array of tiled gallery rows (groups of images).
116     *
117     * @var array
118     */
119    public $grouped_images = array();
120
121    /**
122     * Constructor function.
123     *
124     * @param object $attachments - the attachments.
125     * @param array  $shapes - the shapes.
126     */
127    public function __construct( $attachments, $shapes = array() ) {
128        $content_width = Jetpack_Tiled_Gallery::get_content_width();
129
130        $this->overwrite_shapes( $shapes );
131        $this->last_shape     = '';
132        $this->images         = $this->get_images_with_sizes( $attachments );
133        $this->grouped_images = $this->get_grouped_images();
134        $this->apply_content_width( $content_width );
135    }
136
137    /**
138     * Overwrite the shapes.
139     *
140     * @param array $shapes - the shapes.
141     */
142    public function overwrite_shapes( $shapes ) {
143        if ( ! empty( $shapes ) ) {
144            $this->shapes = $shapes;
145        }
146    }
147
148    /**
149     * Get the current row size.
150     *
151     * @return array
152     */
153    public function get_current_row_size() {
154        $images_left = is_countable( $this->images ) ? count( $this->images ) : 0;
155        if ( $images_left < 3 ) {
156            return array_fill( 0, $images_left, 1 );
157        }
158
159        foreach ( $this->shapes as $shape_name ) {
160            $class_name = "Jetpack_Tiled_Gallery_$shape_name";
161            $shape      = new $class_name( $this->images );
162            if ( $shape->is_possible() ) {
163                Jetpack_Tiled_Gallery_Shape::set_last_shape( $class_name );
164                return $shape->shape;
165            }
166        }
167
168        Jetpack_Tiled_Gallery_Shape::set_last_shape( 'Two' );
169        return array( 1, 1 );
170    }
171
172    /**
173     * Get images with sizes.
174     *
175     * @param object $attachments - the attachments.
176     *
177     * @return array
178     */
179    public function get_images_with_sizes( $attachments ) {
180        $images_with_sizes = array();
181
182        foreach ( $attachments as $image ) {
183            $meta                = wp_get_attachment_metadata( $image->ID );
184            $image->width_orig   = ( isset( $meta['width'] ) && $meta['width'] > 0 ) ? $meta['width'] : 1;
185            $image->height_orig  = ( isset( $meta['height'] ) && $meta['height'] > 0 ) ? $meta['height'] : 1;
186            $image->ratio        = $image->width_orig / $image->height_orig;
187            $image->ratio        = $image->ratio ? $image->ratio : 1;
188            $images_with_sizes[] = $image;
189        }
190
191        return $images_with_sizes;
192    }
193
194    /**
195     * Get the current row size.
196     *
197     * @return array
198     */
199    public function read_row() {
200        $vector = $this->get_current_row_size();
201
202        $row = array();
203        foreach ( $vector as $group_size ) {
204            $row[] = new Jetpack_Tiled_Gallery_Group( array_splice( $this->images, 0, $group_size ) );
205        }
206
207        return $row;
208    }
209
210    /**
211     * Get grouped images.
212     *
213     * @return array
214     */
215    public function get_grouped_images() {
216        $grouped_images = array();
217
218        while ( ! empty( $this->images ) ) {
219            $grouped_images[] = new Jetpack_Tiled_Gallery_Row( $this->read_row() );
220        }
221
222        return $grouped_images;
223    }
224
225    /**
226     * Apply content width.
227     *
228     * @param int $width - the width.
229     *
230     * @todo split in functions
231     * @todo do not stretch images
232     */
233    public function apply_content_width( $width ) {
234        foreach ( $this->grouped_images as $row ) {
235            $row->width      = $width;
236            $group_count     = is_countable( $row->groups ) ? count( $row->groups ) : 0;
237            $row->raw_height = 1 / $row->ratio * ( $width - $this->margin * ( $group_count - $row->weighted_ratio ) );
238            $row->height     = round( $row->raw_height );
239
240            $this->calculate_group_sizes( $row );
241        }
242    }
243
244    /**
245     * Calculate group sizes.
246     *
247     * @param object $row - the row.
248     */
249    public function calculate_group_sizes( $row ) {
250        // Storing the calculated group heights in an array for rounding them later while preserving their sum
251        // This fixes the rounding error that can lead to a few ugly pixels sticking out in the gallery
252        $group_widths_array = array();
253        foreach ( $row->groups as $group ) {
254            $group->height = $row->height;
255            $image_count   = is_countable( $group->images ) ? count( $group->images ) : 0;
256            // Storing the raw calculations in a separate property to prevent rounding errors from cascading down and for diagnostics
257            $group->raw_width     = ( $row->raw_height - $this->margin * $image_count ) * $group->ratio + $this->margin;
258            $group_widths_array[] = $group->raw_width;
259        }
260        $rounded_group_widths_array = Jetpack_Constrained_Array_Rounding::get_rounded_constrained_array( $group_widths_array, $row->width );
261
262        foreach ( $row->groups as $group ) {
263            $group->width = array_shift( $rounded_group_widths_array );
264            $this->calculate_image_sizes( $group );
265        }
266    }
267
268    /**
269     * Calculate image sizes.
270     *
271     * @param object $group - the group of images.
272     */
273    public function calculate_image_sizes( $group ) {
274        // Storing the calculated image heights in an array for rounding them later while preserving their sum
275        // This fixes the rounding error that can lead to a few ugly pixels sticking out in the gallery
276        $image_heights_array = array();
277        foreach ( $group->images as $image ) {
278            $image->width = $group->width - $this->margin;
279            // Storing the raw calculations in a separate property for diagnostics
280            $image->raw_height     = ( $group->raw_width - $this->margin ) / $image->ratio;
281            $image_heights_array[] = $image->raw_height;
282        }
283
284        $image_height_sum            = $group->height - count( $image_heights_array ) * $this->margin;
285        $rounded_image_heights_array = Jetpack_Constrained_Array_Rounding::get_rounded_constrained_array( $image_heights_array, $image_height_sum );
286
287        foreach ( $group->images as $image ) {
288            $image->height = array_shift( $rounded_image_heights_array );
289        }
290    }
291}
292
293/**
294 * Jetpack tiled row class.
295 */
296class Jetpack_Tiled_Gallery_Row {
297    /**
298     * Groups of images
299     *
300     * @var object[]
301     */
302    public $groups;
303
304    /**
305     * Image ratio.
306     *
307     * @var float
308     */
309    public $ratio;
310
311    /**
312     * Weighted ratio based on all the images.
313     *
314     * @var float
315     */
316    public $weighted_ratio;
317
318    /**
319     * Rounded value of the raw width.
320     *
321     * @var int
322     */
323    public $width;
324
325    /**
326     * Rounded value of the raw height.
327     *
328     * @var int
329     */
330    public $height;
331
332    /**
333     * Raw width of the row.
334     *
335     * @var int
336     */
337    public $raw_width;
338
339    /**
340     * Raw height of the row.
341     *
342     * @var int
343     */
344    public $raw_height;
345
346    /**
347     * Constructor class.
348     *
349     * @param object[] $groups - the group of images.
350     */
351    public function __construct( $groups ) {
352        $this->groups         = $groups;
353        $this->ratio          = $this->get_ratio();
354        $this->weighted_ratio = $this->get_weighted_ratio();
355    }
356
357    /**
358     * Get the ratio.
359     *
360     * @return float
361     */
362    public function get_ratio() {
363        $ratio = 0;
364        foreach ( $this->groups as $group ) {
365            $ratio += $group->ratio;
366        }
367        return $ratio > 0 ? $ratio : 1;
368    }
369
370    /**
371     * Get weighted ratio.
372     *
373     * @return float
374     */
375    public function get_weighted_ratio() {
376        $weighted_ratio = 0;
377        foreach ( $this->groups as $group ) {
378            $image_count     = is_countable( $group->images ) ? count( $group->images ) : 0;
379            $weighted_ratio += $group->ratio * $image_count;
380        }
381        return $weighted_ratio > 0 ? $weighted_ratio : 1;
382    }
383}
384
385/**
386 * Tiled gallery group class.
387 */
388class Jetpack_Tiled_Gallery_Group {
389    /**
390     * Images to be displayed in group.
391     *
392     * @var object[]
393     */
394    public $images;
395
396    /**
397     * Image ratio.
398     *
399     * @var float
400     */
401    public $ratio;
402
403    /**
404     * Rounded value of the raw width.
405     *
406     * @var int
407     */
408    public $width;
409
410    /**
411     * Rounded value of the raw height.
412     *
413     * @var int
414     */
415    public $height;
416
417    /**
418     * Raw width of the group.
419     *
420     * @var int
421     */
422    public $raw_width;
423
424    /**
425     * Raw height of the group.
426     *
427     * @var int
428     */
429    public $raw_height;
430
431    /**
432     * Constructor class.
433     *
434     * @param object[] $images - the images.
435     */
436    public function __construct( $images ) {
437        $this->images = $images;
438        $this->ratio  = $this->get_ratio();
439    }
440
441    /**
442     * Get the ratio.
443     *
444     * @return float
445     */
446    public function get_ratio() {
447        $ratio = 0;
448        foreach ( $this->images as $image ) {
449            if ( $image->ratio ) {
450                $ratio += 1 / $image->ratio;
451            }
452        }
453        if ( ! $ratio ) {
454            return 1;
455        }
456
457        return 1 / $ratio;
458    }
459
460    /**
461     * The items.
462     *
463     * @param string $needs_attachment_link - the attachment link.
464     * @param bool   $grayscale - if the image is in grayscale.
465     *
466     * @return array
467     */
468    public function items( $needs_attachment_link, $grayscale ) {
469        $items = array();
470        foreach ( $this->images as $image ) {
471            $items[] = new Jetpack_Tiled_Gallery_Rectangular_Item( $image, $needs_attachment_link, $grayscale );
472        }
473
474        return $items;
475    }
476}