PluginProbe
SureDonation – Donation Forms, Fundraising Campaigns & Donor Management / 1.2.0
SureDonation – Donation Forms, Fundraising Campaigns & Donor Management v1.2.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 / page-builders / bricks / base-element.php

base-element.php in SureDonation – Donation Forms, Fundraising Campaigns & Donor Management 1.2.0, at inc/page-builders/bricks/base-element.php

196 lines 6.0 KB
No matching file
Up and down to move Enter to open Esc to close
Raw Download Zip
1 <?php
2 /**
3 * Base Bricks element.
4 *
5 * Shared plumbing for SureDonation's Bricks elements: the element category, the
6 * campaign selector control, and a render() that emits the matching SureDonation
7 * block's server-side output (so the element stays 1:1 with Gutenberg).
8 *
9 * Only ever loaded through \Bricks\Elements::register_element() behind a
10 * class_exists( '\Bricks\Elements' ) gate — never reference element classes
11 * from generic plugin code (the \Bricks\Element parent won't exist).
12 *
13 * @package SureDonation
14 * @since 1.2.0
15 */
16
17 namespace SureDonation\Inc\Page_Builders\Bricks;
18
19 use SureDonation\Inc\Campaigns\Campaign_Page;
20 use SureDonation\Inc\Helper;
21 use SureDonation\Inc\Page_Builders\Page_Builders;
22
23 if ( ! defined( 'ABSPATH' ) ) {
24 exit; // Exit if accessed directly.
25 }
26
27 /**
28 * Base_Element class.
29 *
30 * @since 1.2.0
31 */
32 abstract class Base_Element extends \Bricks\Element {
33 /**
34 * Element category — every SureDonation element lives under one category.
35 *
36 * @since 1.2.0
37 * @var string
38 */
39 public $category = Service_Provider::CATEGORY;
40
41 /**
42 * Default keywords; subclasses may extend.
43 *
44 * @since 1.2.0
45 * @return array<int, string>
46 */
47 public function get_keywords() {
48 return [ 'suredonation', 'donation', 'campaign' ];
49 }
50
51 /**
52 * Load the campaign block styles on the front end and in the builder canvas.
53 * The block render enqueues the same handle itself; this covers the builder,
54 * where the element markup is rendered before that enqueue can take effect.
55 *
56 * @since 1.2.0
57 * @return void
58 */
59 public function enqueue_scripts() {
60 wp_enqueue_style( 'suredonation-campaign-blocks' );
61 }
62
63 /**
64 * Render the element by emitting the matching block's server-side output.
65 *
66 * @since 1.2.0
67 * @return void
68 */
69 public function render() {
70 $settings = $this->settings;
71 $resolved = Campaign_Page::resolve_campaign_id(
72 [ 'campaignId' => $this->setting_int( $settings, 'campaignId' ) ]
73 );
74
75 if ( ! $resolved ) {
76 // Builder-only info box; on the front end this renders nothing,
77 // matching the block's empty output (self-gated on is_frontend).
78 $this->render_element_placeholder(
79 [
80 'icon-class' => $this->icon,
81 'description' => esc_html__( 'Select a campaign, or place this element on a campaign page.', 'suredonation' ),
82 ]
83 );
84 return;
85 }
86
87 $attrs = $this->get_block_attrs( $settings );
88 $attrs['campaignId'] = $resolved;
89
90 echo '<div ' . $this->render_attributes( '_root' ) . '>'; // phpcs:ignore WordPress.Security.EscapeOutput.OutputNotEscaped -- Bricks root attributes are escaped by the builder.
91
92 // render_block() runs the block's registered render_callback, producing the
93 // exact same (already-escaped) markup as the Gutenberg block.
94 echo render_block( // phpcs:ignore WordPress.Security.EscapeOutput.OutputNotEscaped -- Block render output is escaped in the block's render callback.
95 [
96 'blockName' => $this->block_name(),
97 'attrs' => $attrs,
98 'innerBlocks' => [],
99 'innerHTML' => '',
100 'innerContent' => [],
101 ]
102 );
103
104 echo '</div>';
105 }
106
107 /**
108 * The SureDonation block this element renders (e.g. `suredonation/campaign-stats`).
109 *
110 * @since 1.2.0
111 * @return string
112 */
113 abstract protected function block_name();
114
115 /**
116 * Map the element settings to the block's attributes (camelCase, matching
117 * the block's Gutenberg attributes).
118 *
119 * @since 1.2.0
120 * @param array<string, mixed> $settings Element settings.
121 * @return array<string, mixed>
122 */
123 abstract protected function get_block_attrs( $settings );
124
125 /**
126 * Add the shared "Campaign" selector control (published campaigns).
127 *
128 * @since 1.2.0
129 * @return void
130 */
131 protected function add_campaign_control() {
132 $options = Page_Builders::get_campaign_options();
133 unset( $options[''] ); // Bricks selects use 'placeholder', not an empty option.
134
135 $this->controls['campaignId'] = [
136 'tab' => 'content',
137 'label' => esc_html__( 'Campaign', 'suredonation' ),
138 'type' => 'select',
139 'options' => $options,
140 'searchable' => true,
141 'clearable' => true,
142 'placeholder' => esc_html__( 'Select a campaign', 'suredonation' ),
143 'description' => esc_html__( 'Leave empty to use the current campaign when placed on a campaign page.', 'suredonation' ),
144 ];
145 }
146
147 /**
148 * Read a setting as a string (settings values are mixed).
149 *
150 * @since 1.2.0
151 * @param array<string, mixed> $settings Element settings.
152 * @param string $key Setting key.
153 * @param string $fallback Fallback when empty/unset.
154 * @return string
155 */
156 protected function setting_string( $settings, $key, $fallback = '' ) {
157 if ( ! isset( $settings[ $key ] ) || '' === $settings[ $key ] ) {
158 return $fallback;
159 }
160 return Helper::get_string_value( $settings[ $key ] );
161 }
162
163 /**
164 * Read a setting as a non-negative integer.
165 *
166 * @since 1.2.0
167 * @param array<string, mixed> $settings Element settings.
168 * @param string $key Setting key.
169 * @param int $fallback Fallback when unset.
170 * @return int
171 */
172 protected function setting_int( $settings, $key, $fallback = 0 ) {
173 return isset( $settings[ $key ] ) ? absint( Helper::get_string_value( $settings[ $key ] ) ) : $fallback;
174 }
175
176 /**
177 * Read a Bricks checkbox setting as a boolean. Bricks stores `true` when
178 * checked and omits the key when unchecked — and it NEVER seeds a control's
179 * 'default' into settings, so absence always reads as false.
180 *
181 * Contract: this helper is safe only for controls whose Gutenberg block
182 * default is false. A default-true block option MUST be modeled as an
183 * inverted, default-off control (e.g. hideProgressBar → ! setting_bool()),
184 * otherwise an untouched element passes an explicit false to render_block()
185 * and flips the block.json default (which only fills MISSING attributes).
186 *
187 * @since 1.2.0
188 * @param array<string, mixed> $settings Element settings.
189 * @param string $key Setting key.
190 * @return bool
191 */
192 protected function setting_bool( $settings, $key ) {
193 return isset( $settings[ $key ] ) && false !== $settings[ $key ];
194 }
195 }
196