PluginProbe
SureDonation – Donation Forms, Fundraising Campaigns & Donor Management / 1.6.0
SureDonation – Donation Forms, Fundraising Campaigns & Donor Management v1.6.0
1.6.1 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 / elementor / widgets / donation-form-widget.php

donation-form-widget.php in SureDonation – Donation Forms, Fundraising Campaigns & Donor Management 1.6.0, at inc/page-builders/elementor/widgets/donation-form-widget.php

220 lines 6.1 KB
No matching file
Up and down to move Enter to open Esc to close
Raw Download Zip
1 <?php
2 /**
3 * Elementor widget: Donation Form.
4 *
5 * @package SureDonation
6 * @since 1.2.0
7 */
8
9 namespace SureDonation\Inc\Page_Builders\Elementor\Widgets;
10
11 use Elementor\Controls_Manager;
12 use SureDonation\Inc\Campaigns\Campaign_Cpt;
13 use SureDonation\Inc\Page_Builders\Elementor\Base_Widget;
14 use SureDonation\Inc\Page_Builders\Page_Builders;
15
16 if ( ! defined( 'ABSPATH' ) ) {
17 exit; // Exit if accessed directly.
18 }
19
20 /**
21 * Donation_Form_Widget class.
22 *
23 * @since 1.2.0
24 */
25 class Donation_Form_Widget extends Base_Widget {
26 /**
27 * {@inheritDoc}
28 */
29 public function get_name() {
30 return 'suredonation-donation-form';
31 }
32
33 /**
34 * {@inheritDoc}
35 */
36 public function get_title() {
37 return esc_html__( 'Donation Form', 'suredonation' );
38 }
39
40 /**
41 * {@inheritDoc}
42 */
43 public function get_icon() {
44 return 'eicon-form-horizontal';
45 }
46
47 /**
48 * The donation form uses its own style handle, not the campaign blocks one.
49 *
50 * @since 1.2.0
51 * @return array<int, string>
52 */
53 public function get_style_depends() {
54 return [ 'suredonation-donation-form' ];
55 }
56
57 /**
58 * Declare the form frontend script so Elementor enqueues it whenever the
59 * widget is present (the block render's own enqueue + localization still
60 * runs and remains the non-Elementor fallback).
61 *
62 * @since 1.2.0
63 * @return array<int, string>
64 */
65 public function get_script_depends() {
66 return [ 'suredonation-form-frontend' ];
67 }
68
69 /**
70 * {@inheritDoc}
71 */
72 protected function block_name() {
73 return 'suredonation/donation-form';
74 }
75
76 /**
77 * Register the widget controls.
78 *
79 * @since 1.2.0
80 * @return void
81 */
82 protected function register_controls() {
83 $this->start_controls_section(
84 'content',
85 [ 'label' => esc_html__( 'Donation Form', 'suredonation' ) ]
86 );
87
88 // Mirrors the Gutenberg donation-form block inspector, which exposes only a
89 // campaign selector and a form selector (the form's own display options are
90 // configured in the form editor, not on the embed).
91 $this->add_campaign_control();
92
93 // Elementor (free) has no dependent/AJAX dropdown, so we reproduce the
94 // block's campaign-scoped form list by registering one form control per
95 // campaign and gating each on the campaign selection — exactly one is ever
96 // visible. A campaign-less fallback lists every form (the widget can be
97 // placed without a campaign, e.g. on a campaign page where it inherits the
98 // current one). The resolved value is read back in resolve_form_id().
99 $this->add_control(
100 'form_id',
101 [
102 'label' => esc_html__( 'Donation form', 'suredonation' ),
103 'type' => Controls_Manager::SELECT2,
104 'label_block' => true,
105 'options' => Page_Builders::get_donation_form_options(),
106 'default' => '',
107 'condition' => [ 'campaign_id' => '' ],
108 ]
109 );
110
111 foreach ( Page_Builders::get_campaign_options() as $campaign_id => $campaign_label ) {
112 $campaign_id = absint( $campaign_id );
113 if ( ! $campaign_id ) {
114 continue; // Skip the leading "Select a campaign" placeholder entry.
115 }
116
117 // Pre-select the campaign's default form, matching how the Gutenberg
118 // block auto-selects it once a campaign is chosen.
119 $default_form_id = Campaign_Cpt::get_default_form_id( $campaign_id );
120
121 $this->add_control(
122 'form_id_' . $campaign_id,
123 [
124 'label' => esc_html__( 'Donation form', 'suredonation' ),
125 'type' => Controls_Manager::SELECT2,
126 'label_block' => true,
127 'options' => Page_Builders::get_campaign_form_options( $campaign_id ),
128 'default' => $default_form_id ? (string) $default_form_id : '',
129 'condition' => [ 'campaign_id' => (string) $campaign_id ],
130 ]
131 );
132 }
133
134 // Mirrors the Gutenberg block's "Edit Form" link: the fields, amounts and
135 // payment methods live in the form editor, not on the embed. No condition
136 // is attached because the selected form lives in one of N campaign-scoped
137 // controls (see above) — Elementor conditions cannot express "whichever
138 // one is active", so the handler resolves it and no-ops when unset.
139 $this->add_control(
140 'edit_form',
141 [
142 'label' => esc_html__( 'Edit Form', 'suredonation' ),
143 'separator' => 'before',
144 'type' => Controls_Manager::BUTTON,
145 'text' => esc_html__( 'Edit', 'suredonation' ),
146 'event' => 'suredonation:form:edit',
147 ]
148 );
149
150 $this->end_controls_section();
151 }
152
153 /**
154 * Render the donation form block. Unlike the campaign-context widgets this
155 * gates on a selected form (a campaign is optional).
156 *
157 * @since 1.2.0
158 * @return void
159 */
160 protected function render() {
161 $settings = $this->get_settings_for_display();
162 $form_id = $this->resolve_form_id( $settings );
163
164 if ( ! $form_id ) {
165 if ( $this->is_edit_mode() ) {
166 $this->render_placeholder( esc_html__( 'Select a donation form to display.', 'suredonation' ) );
167 }
168 return;
169 }
170
171 $form = get_post( $form_id );
172 if ( ! $form instanceof \WP_Post || 'publish' !== $form->post_status ) {
173 if ( $this->is_edit_mode() ) {
174 $this->render_placeholder( esc_html__( 'The selected donation form is unavailable.', 'suredonation' ) );
175 }
176 return;
177 }
178
179 $this->echo_block( $this->get_block_attrs( $settings ) );
180 }
181
182 /**
183 * Map the widget settings to the block attributes.
184 *
185 * @since 1.2.0
186 * @param array<string, mixed> $settings Widget settings.
187 * @return array<string, mixed>
188 */
189 protected function get_block_attrs( $settings ) {
190 $attrs = [
191 'formId' => $this->resolve_form_id( $settings ),
192 ];
193
194 $campaign_id = $this->setting_int( $settings, 'campaign_id' );
195 if ( $campaign_id ) {
196 $attrs['campaignId'] = $campaign_id;
197 }
198
199 return $attrs;
200 }
201
202 /**
203 * Resolve the selected form ID from the campaign-scoped control.
204 *
205 * The form selector is split into one control per campaign (`form_id_{id}`)
206 * plus a campaign-less fallback (`form_id`); only the control matching the
207 * current campaign selection holds the chosen value.
208 *
209 * @since 1.2.0
210 * @param array<string, mixed> $settings Widget settings.
211 * @return int
212 */
213 protected function resolve_form_id( $settings ) {
214 $campaign_id = $this->setting_int( $settings, 'campaign_id' );
215 $control_key = $campaign_id ? 'form_id_' . $campaign_id : 'form_id';
216
217 return $this->setting_int( $settings, $control_key );
218 }
219 }
220