PluginProbe
SureDonation – Donation Forms, Fundraising Campaigns & Donor Management / 1.1.0
SureDonation – Donation Forms, Fundraising Campaigns & Donor Management v1.1.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
← All changes | inc/blocks/register.php +256 -10 0.0.1 → 1.1.0 View file →
@@ -6,8 +6,10 @@
6 6 */
7 7
8 8 namespace SureDonation\Inc\Blocks;
9 9
10 +use SureDonation\Inc\Payments\Offline\Offline_Helper;
11 +use SureDonation\Inc\Payments\Payment_Helper;
10 12 use SureDonation\Inc\Payments\Stripe\Stripe_Helper;
11 13 use SureDonation\Inc\Traits\Get_Instance;
12 14
13 15 // Exit if accessed directly.
@@ -28,17 +30,90 @@
28 30 *
29 31 * @since 0.0.1
30 32 */
31 33 public function __construct() {
34 + add_action( 'init', [ $this, 'register_embed_block_script' ], 5 );
32 35 add_action( 'init', [ $this, 'register_blocks' ] );
33 36 add_action( 'enqueue_block_editor_assets', [ $this, 'enqueue_editor_assets' ] );
37 + add_action( 'enqueue_block_editor_assets', [ $this, 'enqueue_campaign_editor_assets' ] );
34 38 add_filter( 'block_categories_all', [ $this, 'register_block_category' ], 10, 2 );
39 + add_filter( 'block_editor_settings_all', [ $this, 'add_campaign_iframe_styles' ], 10, 2 );
35 40 }
36 41
37 42 /**
43 + * Register the donation form embed block editor script.
44 + *
45 + * Runs before register_blocks() so the handle exists when block.json is read.
46 + * Not gated by post type — the embed block should work on all post types.
47 + *
48 + * @return void
49 + * @since 1.0.0
50 + */
51 + public function register_embed_block_script() {
52 + $asset_file = SUREDONATION_DIR . 'assets/build/blocks/donation-form/editor.asset.php';
53 + $asset = file_exists( $asset_file )
54 + ? require $asset_file
55 + : [
56 + 'dependencies' => [],
57 + 'version' => SUREDONATION_VER,
58 + ];
59 +
60 + wp_register_script(
61 + 'suredonation-donation-form-editor',
62 + SUREDONATION_URL . 'assets/build/blocks/donation-form/editor.js',
63 + $asset['dependencies'],
64 + $asset['version'],
65 + true
66 + );
67 +
68 + // Data for the block editor placeholder (logo). The campaign blocks
69 + // bundle defines the same global elsewhere; localizing it here keeps the
70 + // logo available wherever the donation form block is inserted.
71 + wp_localize_script(
72 + 'suredonation-donation-form-editor',
73 + 'suredonationCampaignBlocks',
74 + $this->get_campaign_blocks_data()
75 + );
76 +
77 + wp_register_style(
78 + 'suredonation-donation-form-editor',
79 + SUREDONATION_URL . 'assets/build/blocks/donation-form/editor.css',
80 + [],
81 + $asset['version']
82 + );
83 + }
84 +
85 + /**
86 + * Data localized for the block editor placeholders (logo).
87 + *
88 + * Shared by the donation form embed block and the campaign display blocks,
89 + * both of which expose it on the `suredonationCampaignBlocks` JS global.
90 + *
91 + * `currentPostType` lets a block scope its editor registration to a single
92 + * post type (the Campaign Donate Button registers only on the campaign
93 + * editor). It is read from the current screen, so it is only populated for
94 + * the caller that runs on `enqueue_block_editor_assets` (the campaign editor
95 + * assets); the embed-block caller runs on `init`, where there is no screen,
96 + * so it receives an empty string. That is harmless — the embed block only
97 + * consumes `logoUrl`.
98 + *
99 + * @return array<string, string>
100 + * @since 1.0.0
101 + */
102 + public function get_campaign_blocks_data() {
103 + $screen = function_exists( 'get_current_screen' ) ? get_current_screen() : null;
104 +
105 + return [
106 + 'logoUrl' => esc_url_raw( SUREDONATION_URL . 'images/suredonation-logo.svg' ),
107 + 'currentPostType' => $screen ? (string) $screen->post_type : '',
108 + ];
109 + }
110 +
111 + /**
38 112 * Register custom block category for SureDonation blocks.
39 113 *
40 - * Only adds the category on the donation form editor.
114 + * The field-block category is limited to the donation form editor; the
115 + * campaign display-block category is registered everywhere else.
41 116 *
42 117 * @param array<int, array<string, mixed>> $categories Existing block categories.
43 118 * @param \WP_Block_Editor_Context $context Block editor context.
44 119 * @return array<int, array<string, mixed>> Modified block categories.
@@ -44,19 +119,31 @@
44 119 * @return array<int, array<string, mixed>> Modified block categories.
45 120 * @since 0.0.1
46 121 */
47 122 public function register_block_category( $categories, $context ) {
48 - // Only show category on donation form editor.
49 - if ( ! isset( $context->post ) || 'suredonation_form' !== $context->post->post_type ) {
50 - return $categories;
123 + // Field-block category on the donation form editor.
124 + if ( isset( $context->post ) && 'suredonation_form' === $context->post->post_type ) {
125 + return array_merge(
126 + [
127 + [
128 + 'slug' => 'suredonation',
129 + 'title' => __( 'General Fields', 'suredonation' ),
130 + 'icon' => null,
131 + ],
132 + ],
133 + $categories
134 + );
51 135 }
52 136
53 - // Add SureDonation category at the beginning.
137 + // Campaign display-block category on every other editor — including the
138 + // Site Editor and widget contexts where $context->post is unset — so the
139 + // campaign blocks always group under SureDonation in the inserter. Only
140 + // the donation form editor (handled above) is excluded.
54 141 return array_merge(
55 142 [
56 143 [
57 - 'slug' => 'suredonation',
58 - 'title' => __( 'General Fields', 'suredonation' ),
144 + 'slug' => 'suredonation-campaign',
145 + 'title' => __( 'SureDonation', 'suredonation' ),
59 146 'icon' => null,
60 147 ],
61 148 ],
62 149 $categories
@@ -63,8 +150,128 @@
63 150 );
64 151 }
65 152
66 153 /**
154 + * Enqueue the campaign display blocks editor bundle.
155 + *
156 + * Loads on every block editor so the campaign blocks can be added to any
157 + * page/post/CPT — except the donation form editor, which has its own field
158 + * blocks. On a campaign post the blocks auto-bind to that campaign; elsewhere
159 + * the block inspector exposes a campaign selector.
160 + *
161 + * @return void
162 + * @since 1.0.0
163 + */
164 + public function enqueue_campaign_editor_assets() {
165 + $screen = get_current_screen();
166 +
167 + // Load everywhere except the donation form editor.
168 + if ( ! $screen || 'suredonation_form' === $screen->post_type ) {
169 + return;
170 + }
171 +
172 + $asset_file = SUREDONATION_DIR . 'assets/build/campaign-blocks.asset.php';
173 + $asset = file_exists( $asset_file )
174 + ? require $asset_file
175 + : [
176 + 'dependencies' => [ 'wp-blocks', 'wp-element', 'wp-editor', 'wp-components', 'wp-i18n', 'wp-block-editor', 'wp-data', 'wp-server-side-render' ],
177 + 'version' => SUREDONATION_VER,
178 + ];
179 +
180 + wp_enqueue_script(
181 + 'suredonation-campaign-blocks',
182 + SUREDONATION_URL . 'assets/build/campaign-blocks.js',
183 + $asset['dependencies'],
184 + $asset['version'],
185 + true
186 + );
187 +
188 + wp_set_script_translations( 'suredonation-campaign-blocks', 'suredonation' );
189 +
190 + // Data for the campaign block editor placeholder (logo).
191 + wp_localize_script(
192 + 'suredonation-campaign-blocks',
193 + 'suredonationCampaignBlocks',
194 + $this->get_campaign_blocks_data()
195 + );
196 +
197 + // Style the server-side-rendered block previews in the editor.
198 + $style_file = SUREDONATION_DIR . 'assets/build/blocks/campaign/style-style.css';
199 + $style_version = file_exists( $style_file )
200 + ? (string) filemtime( $style_file )
201 + : SUREDONATION_VER;
202 +
203 + wp_enqueue_style(
204 + 'suredonation-campaign-blocks',
205 + SUREDONATION_URL . 'assets/build/blocks/campaign/style-style.css',
206 + [],
207 + $style_version
208 + );
209 + }
210 +
211 + /**
212 + * Inject the campaign block styles into the editor canvas iframe.
213 + *
214 + * Styles enqueued via enqueue_block_editor_assets load in the editor's outer
215 + * frame only; the block canvas is iframed, so the server-side-rendered campaign
216 + * block previews would otherwise render unstyled. Adding the CSS to the editor
217 + * settings makes WordPress inject it inside the iframe, matching the frontend.
218 + *
219 + * @param array<string, mixed> $settings Block editor settings.
220 + * @param \WP_Block_Editor_Context $context Block editor context.
221 + * @return array<string, mixed> Modified settings.
222 + * @since 1.0.0
223 + */
224 + public function add_campaign_iframe_styles( $settings, $context ) {
225 + // Inject wherever the campaign blocks can be used (everywhere except the
226 + // donation form editor), so their editor previews match the frontend.
227 + if ( ! isset( $context->post ) || 'suredonation_form' === $context->post->post_type ) {
228 + return $settings;
229 + }
230 +
231 + $css = $this->get_campaign_iframe_css();
232 + if ( '' === $css ) {
233 + return $settings;
234 + }
235 +
236 + if ( ! isset( $settings['styles'] ) || ! is_array( $settings['styles'] ) ) {
237 + $settings['styles'] = [];
238 + }
239 +
240 + $settings['styles'][] = [ 'css' => $css ];
241 +
242 + return $settings;
243 + }
244 +
245 + /**
246 + * Read the built campaign stylesheet, cached per request by file mtime so
247 + * the filter (which can run more than once per load) reads from disk at most
248 + * once until the asset changes.
249 + *
250 + * @return string The stylesheet contents, or '' when unavailable.
251 + * @since 1.0.0
252 + */
253 + private function get_campaign_iframe_css() {
254 + static $cached_css = null;
255 + static $cached_mtime = null;
256 +
257 + $style_file = SUREDONATION_DIR . 'assets/build/blocks/campaign/style-style.css';
258 + if ( ! file_exists( $style_file ) ) {
259 + return '';
260 + }
261 +
262 + $mtime = filemtime( $style_file );
263 + if ( null === $cached_css || $cached_mtime !== $mtime ) {
264 + // phpcs:ignore WordPress.WP.AlternativeFunctions.file_get_contents_file_get_contents -- Reading the plugin's own built stylesheet to inline into the editor iframe.
265 + $css = file_get_contents( $style_file );
266 + $cached_css = false === $css ? '' : $css;
267 + $cached_mtime = $mtime;
268 + }
269 +
270 + return $cached_css;
271 + }
272 +
273 + /**
67 274 * Enqueue block editor assets.
68 275 *
69 276 * Only loads on the donation form editor.
70 277 *
@@ -78,26 +285,65 @@
78 285 if ( ! $screen || 'suredonation_form' !== $screen->post_type ) {
79 286 return;
80 287 }
81 288
289 + // Use the asset.php content hash as the version so rebuilds bust the
290 + // browser cache. Falls back to SUREDONATION_VER if the asset file
291 + // is missing.
292 + $blocks_asset_file = SUREDONATION_DIR . 'assets/build/blocks.asset.php';
293 + $blocks_asset = file_exists( $blocks_asset_file )
294 + ? require $blocks_asset_file
295 + : [
296 + 'dependencies' => [ 'wp-blocks', 'wp-element', 'wp-editor', 'wp-components', 'wp-i18n', 'wp-block-editor', 'wp-data' ],
297 + 'version' => SUREDONATION_VER,
298 + ];
299 +
82 300 // Enqueue the blocks script.
83 301 wp_enqueue_script(
84 302 'suredonation-blocks',
85 303 SUREDONATION_URL . 'assets/build/blocks.js',
86 - [ 'wp-blocks', 'wp-element', 'wp-editor', 'wp-components', 'wp-i18n', 'wp-block-editor', 'wp-data' ],
87 - SUREDONATION_VER,
304 + $blocks_asset['dependencies'],
305 + $blocks_asset['version'],
88 306 true
89 307 );
90 308
309 + // Load JS translations for blocks.
310 + wp_set_script_translations( 'suredonation-blocks', 'suredonation' );
311 +
91 312 // Localize script with admin data for blocks.
313 + $global_currency = Payment_Helper::get_currency();
314 +
92 315 wp_localize_script(
93 316 'suredonation-blocks',
94 317 'suredonation_admin',
95 318 [
96 - 'payments' => [
319 + 'payments' => [
97 320 'stripe_connected' => Stripe_Helper::is_stripe_connected(),
98 321 'stripe_connect_url' => Stripe_Helper::get_stripe_connect_url(),
322 + 'settings_url' => admin_url( 'admin.php?page=suredonation#/settings?tab=payments' ),
323 + 'offline_enabled' => Offline_Helper::is_offline_enabled(),
324 + 'gateways' => apply_filters(
325 + 'suredonation_editor_payment_gateways',
326 + [
327 + [
328 + 'value' => 'stripe',
329 + 'label' => __( 'Stripe', 'suredonation' ),
330 + 'supports_recurring' => true,
331 + ],
332 + [
333 + 'value' => 'offline',
334 + 'label' => __( 'Offline Donations', 'suredonation' ),
335 + 'supports_recurring' => false,
336 + ],
337 + ]
338 + ),
99 339 ],
340 + 'fee_recovery' => Payment_Helper::get_fee_recovery_settings(),
341 + 'currency' => $global_currency,
342 + 'currencySymbol' => Payment_Helper::get_currency_symbol( $global_currency ),
343 + // Resolved default validation messages so the editor can show
344 + // them as placeholders on each field's Error Message control.
345 + 'validationMessages' => \SureDonation\Inc\Field_Validation::get_resolved_validation_messages(),
100 346 ]
101 347 );
102 348 }
103 349