PluginProbe
SureDonation – Donation Forms, Fundraising Campaigns & Donor Management / 1.6.0
SureDonation – Donation Forms, Fundraising Campaigns & Donor Management v1.6.0
1.6.0 1.5.1 1.5.0 1.4.0 1.3.0 trunk 0.0.1 1.0.0 1.1.0 1.1.1 1.1.2 1.2.0
suredonation / inc / blocks / image / block.php

block.php in SureDonation – Donation Forms, Fundraising Campaigns & Donor Management 1.6.0, at inc/blocks/image/block.php

161 lines 5.3 KB
No matching file
Up and down to move Enter to open Esc to close
Raw Download Zip
1 <?php
2 /**
3 * PHP render for Image Block.
4 *
5 * A display-only block that renders an image within the donation form
6 * (e.g. an organization logo or cause photo). It carries no submission
7 * value and does not participate in field validation.
8 *
9 * @package SureDonation
10 * @since 1.3.0
11 */
12
13 namespace SureDonation\Inc\Blocks\Image;
14
15 use SureDonation\Inc\Blocks\Base;
16 use SureDonation\Inc\Helper;
17
18 if ( ! defined( 'ABSPATH' ) ) {
19 exit; // Exit if accessed directly.
20 }
21
22 /**
23 * Image Block.
24 *
25 * @since 1.3.0
26 */
27 class Block extends Base {
28 /**
29 * Registered image sizes the block may request.
30 *
31 * @since 1.3.0
32 */
33 private const SIZES = [ 'thumbnail', 'medium', 'large', 'full' ];
34
35 /**
36 * Render the block.
37 *
38 * @param array<string, mixed> $attributes Block attributes.
39 * @param string $content Block content.
40 * @return string
41 * @since 1.3.0
42 */
43 public function render( $attributes, $content = '' ) {
44 unset( $content ); // Unused parameter.
45
46 if ( empty( $attributes ) ) {
47 return '';
48 }
49
50 $image_id = isset( $attributes['imageId'] ) ? absint( Helper::get_string_value( $attributes['imageId'] ) ) : 0;
51 $image_url = isset( $attributes['imageUrl'] ) ? Helper::get_string_value( $attributes['imageUrl'] ) : '';
52 $alt = isset( $attributes['imageAlt'] ) ? Helper::get_string_value( $attributes['imageAlt'] ) : '';
53
54 // Nothing selected — a display block with no image contributes nothing.
55 if ( ! $image_id && '' === $image_url ) {
56 return '';
57 }
58
59 // Restrict the size to the supported set so it can be passed to core safely.
60 $size = isset( $attributes['sizeSlug'] ) ? Helper::get_string_value( $attributes['sizeSlug'] ) : 'full';
61 if ( ! in_array( $size, self::SIZES, true ) ) {
62 $size = 'full';
63 }
64
65 // Restrict alignment to a known set so it can be used safely in a class.
66 $align = isset( $attributes['textAlign'] ) ? Helper::get_string_value( $attributes['textAlign'] ) : 'left';
67 if ( ! in_array( $align, [ 'left', 'center', 'right' ], true ) ) {
68 $align = 'left';
69 }
70
71 // Object fit — applied as a class (CSS carries the property) so no inline
72 // styles pass through kses. Empty means the browser default.
73 $fit = isset( $attributes['objectFit'] ) ? Helper::get_string_value( $attributes['objectFit'] ) : '';
74 if ( ! in_array( $fit, [ 'fill', 'cover', 'contain' ], true ) ) {
75 $fit = '';
76 }
77
78 // Optional fixed dimensions (px) from the editor resize handles /
79 // Dimensions controls. 0 = auto. Emitted as width/height CSS, which
80 // wp_kses passes through safecss_filter_attr.
81 $width_px = isset( $attributes['width'] ) ? max( 0, (int) Helper::get_string_value( $attributes['width'] ) ) : 0;
82 $height_px = isset( $attributes['height'] ) ? max( 0, (int) Helper::get_string_value( $attributes['height'] ) ) : 0;
83 $style = '';
84 if ( $width_px ) {
85 $style .= 'width:' . $width_px . 'px;';
86 }
87 if ( $height_px ) {
88 $style .= 'height:' . $height_px . 'px;';
89 }
90
91 // Prefer the attachment render (correct srcset/sizes/lazy-loading, and it
92 // tracks the file if it was edited/regenerated); fall back to the stored
93 // URL when the attachment no longer resolves (e.g. deleted media).
94 $image_markup = '';
95 if ( $image_id ) {
96 $image_markup = wp_get_attachment_image(
97 $image_id,
98 $size,
99 false,
100 array_filter(
101 [
102 'class' => 'sd-image' . ( $fit ? ' sd-image--fit-' . $fit : '' ),
103 'alt' => $alt,
104 'style' => $style,
105 ],
106 static fn ( $value, $key ) => 'alt' === $key || '' !== $value,
107 ARRAY_FILTER_USE_BOTH
108 )
109 );
110 }
111
112 if ( '' === $image_markup && '' !== $image_url ) {
113 $image_markup = sprintf(
114 '<img class="sd-image%3$s" src="%1$s" alt="%2$s"%4$s loading="lazy" decoding="async" />',
115 esc_url( $image_url ),
116 esc_attr( $alt ),
117 $fit ? esc_attr( ' sd-image--fit-' . $fit ) : '',
118 $style ? ' style="' . esc_attr( $style ) . '"' : ''
119 );
120 }
121
122 if ( '' === $image_markup ) {
123 return '';
124 }
125
126 $wrapper_classes = self::get_display_block_classes( $attributes, 'sd-image-block' );
127
128 // Optional caption, rendered as a semantic figcaption.
129 $caption_markup = '';
130 $caption = isset( $attributes['caption'] ) ? Helper::get_string_value( $attributes['caption'] ) : '';
131 if ( ! empty( $attributes['enableCaption'] ) && '' !== trim( $caption ) ) {
132 // Caption alignment is independent of the image alignment; empty
133 // means it follows the figure (image) alignment.
134 $caption_align = isset( $attributes['captionAlign'] ) ? Helper::get_string_value( $attributes['captionAlign'] ) : '';
135 if ( ! in_array( $caption_align, [ 'left', 'center', 'right' ], true ) ) {
136 $caption_align = '';
137 }
138
139 $caption_markup = sprintf(
140 '<figcaption class="sd-image-caption%2$s">%1$s</figcaption>',
141 esc_html( $caption ),
142 $caption_align ? esc_attr( ' sd-image-caption-align-' . $caption_align ) : ''
143 );
144 }
145
146 $markup = sprintf(
147 '<div class="%1$s"><figure class="sd-image-wrap sd-image-align-%2$s">%3$s%4$s</figure></div>',
148 esc_attr( $wrapper_classes ),
149 esc_attr( $align ),
150 $image_markup,
151 $caption_markup
152 );
153
154 ob_start();
155 // Allow the data: protocol so a lazy-load optimizer's inline SVG
156 // placeholder in src survives kses (the markup is server-generated).
157 echo wp_kses( $markup, self::get_allowed_form_html(), array_merge( wp_allowed_protocols(), [ 'data' ] ) );
158 return (string) ob_get_clean();
159 }
160 }
161