PluginProbe
GiveWP – Donation Plugin and Fundraising Platform / 4.18.0
GiveWP – Donation Plugin and Fundraising Platform v4.18.0
4.18.0 4.17.0 4.16.9 4.16.8.1 4.16.8 4.16.7.2 4.16.7.1 4.16.7 4.16.6.1 4.16.6 4.16.5.1 4.16.5 4.16.4 4.16.3 4.16.2 4.16.1 4.16.0 4.15.5 4.15.4 4.15.3 4.15.2 4.15.1 4.15.0 2.3.0 2.3.1 All 257 releases
give / src / DonationForms / Blocks / DonationFormBlock / Controllers / BlockRenderController.php

BlockRenderController.php in GiveWP – Donation Plugin and Fundraising Platform 4.18.0, at src/DonationForms/Blocks/DonationFormBlock/Controllers/BlockRenderController.php

185 lines 6.6 KB
No matching file
Up and down to move Enter to open Esc to close
Raw Download Zip
1 <?php
2
3 namespace Give\DonationForms\Blocks\DonationFormBlock\Controllers;
4
5 use Give\DonationForms\Actions\GenerateDonationConfirmationReceiptViewRouteUrl;
6 use Give\DonationForms\Actions\GenerateDonationFormPageUrl;
7 use Give\DonationForms\Actions\GenerateDonationFormViewRouteUrl;
8 use Give\DonationForms\Actions\GetFormSkeletonData;
9 use Give\DonationForms\Actions\RenderFormSkeleton;
10 use Give\DonationForms\Blocks\DonationFormBlock\DataTransferObjects\BlockAttributes;
11 use Give\DonationForms\DataTransferObjects\DonationConfirmationReceiptViewRouteData;
12 use Give\DonationForms\Models\DonationForm;
13 use Give\Framework\EnqueueScript;
14 use Give\Framework\Routes\RouteListener;
15 use Give\Helpers\Language;
16
17 class BlockRenderController
18 {
19 /**
20 * @since 4.1.0
21 */
22 protected static int $embedInstance = 0;
23
24 /**
25 * @since 4.17.0 print a server-rendered skeleton of the form inside the root so it paints before any script runs.
26 * @since 4.17.0 Build the form page URL through GenerateDonationFormPageUrl, shared with the external embed.
27 * @since 4.14.5 add escaping to the output.
28 * @since 4.7.0 detach check for gutenberg editor to make this more reusable
29 * @since 4.1.0 updated with embed ID instance fallback when block ID is not set.
30 * @since 3.22.0 Add locale support
31 * @since 3.2.0 include form url for new tab format.
32 * @since 3.0.0
33 *
34 * @return string|null
35 */
36 public function render(array $attributes)
37 {
38 static::$embedInstance++;
39
40 $blockAttributes = BlockAttributes::fromArray($attributes);
41
42 if (!$blockAttributes->formId) {
43 return null;
44 }
45
46 $this->loadEmbedScript();
47
48 /** @var DonationForm $donationForm */
49 $donationForm = DonationForm::find($blockAttributes->formId);
50
51 $embedId = $blockAttributes->blockId ?? 'givewp-embed-' . static::$embedInstance;
52
53 $locale = Language::getLocale();
54 $viewUrl = $this->getViewUrl($donationForm, $embedId);
55 $formUrl = (new GenerateDonationFormPageUrl())($blockAttributes->formId);
56 $formViewUrl = $this->getFormViewUrl($donationForm);
57 $colorSettings = $donationForm->getColorSettings();
58 // The app treats every format it does not know as on-page, so the skeleton follows the same rule.
59 $isOnPage = !in_array($blockAttributes->formFormat, ['modal', 'reveal', 'newTab'], true);
60 $skeleton = $isOnPage ? $this->renderSkeleton($donationForm) : '';
61
62 /**
63 * Note: iframe-resizer uses querySelectorAll so using a data attribute makes the most sense to target.
64 * It will also generate a dynamic ID - so when we have multiple embeds on a page there will be no conflict.
65 */
66 return sprintf(
67 "<div class='root-data-givewp-embed' data-form-locale='%s' data-form-url='%s' data-form-view-url='%s' data-src='%s' data-givewp-embed-id='%s' data-form-format='%s' data-open-form-button='%s' style='--givewp-primary-color: %s; --givewp-secondary-color: %s;'>%s</div>",
68 esc_attr($locale),
69 esc_attr($formUrl),
70 esc_attr($formViewUrl),
71 esc_attr($viewUrl),
72 esc_attr($embedId),
73 esc_attr($blockAttributes->formFormat),
74 esc_attr($blockAttributes->openFormButton),
75 esc_attr($colorSettings['primaryColor']),
76 esc_attr($colorSettings['secondaryColor']),
77 $skeleton
78 );
79 }
80
81 /**
82 * The skeleton and its styles go inside the root so they paint as the page parses, before the
83 * block's script or footer stylesheet arrives. The embed app reads them back out of the root
84 * and keeps showing them until the form's handshake. An empty string means the design is one
85 * the skeleton cannot sketch, and the app shows a spinner.
86 *
87 * @since 4.17.0
88 */
89 private function renderSkeleton(DonationForm $donationForm): string
90 {
91 $renderer = new RenderFormSkeleton();
92 $markup = $renderer((new GetFormSkeletonData())($donationForm));
93
94 if (!$markup) {
95 return '';
96 }
97
98 return '<style class="givewp-embed-skeleton-styles">' . $renderer->css() . '</style>' . $markup;
99 }
100
101 /**
102 * Return early if we're still inside the editor to avoid server side effects
103 *
104 * @since 4.7.0
105 *
106 * @return boolean
107 */
108 public function isGutenbergEditor(): bool
109 {
110 return !empty($_REQUEST['post']) || !empty($_REQUEST['action']) || !empty($_REQUEST['_locale']);
111 }
112
113 /**
114 * If the page loads with our receipt route listener args then we need to render the receipt.
115 *
116 * @since 3.0.0
117 */
118 protected function shouldDisplayDonationConfirmationReceipt(string $embedId): bool
119 {
120 $routeListener = new RouteListener(
121 'donation-completed',
122 'show-donation-confirmation-receipt'
123 );
124
125 return $routeListener->isValid($_GET, function ($request) use ($embedId) {
126 $isset = isset($request['givewp-embed-id'], $request['givewp-receipt-id']);
127
128 return $isset && $request['givewp-embed-id'] === $embedId && DonationConfirmationReceiptViewRouteData::isReceiptIdValid(
129 $request['givewp-receipt-id']
130 );
131 });
132 }
133
134 /**
135 * Get the iframe URL.
136 * This could either be the donation form view or the donation confirmation receipt view.
137 *
138 * @since 3.0.0
139 */
140 private function getViewUrl(DonationForm $donationForm, string $embedId): string
141 {
142 if ($this->shouldDisplayDonationConfirmationReceipt($embedId)) {
143 $receiptId = give_clean($_GET['givewp-receipt-id']);
144
145 return (new GenerateDonationConfirmationReceiptViewRouteUrl())($receiptId);
146 }
147
148 return $this->getFormViewUrl($donationForm);
149 }
150
151 /**
152 * @since 3.4.0
153 */
154 private function getFormViewUrl(DonationForm $donationForm): string
155 {
156 return (new GenerateDonationFormViewRouteUrl())($donationForm->id);
157 }
158
159 /**
160 *
161 * Load embed givewp script to resize iframe
162 * @see https://github.com/davidjbradshaw/iframe-resizer
163 *
164 * @since 3.0.0
165 */
166 protected function loadEmbedScript()
167 {
168 (new EnqueueScript(
169 'givewp-donation-form-embed-app',
170 'build/donationFormBlockApp.js',
171 GIVE_PLUGIN_DIR,
172 GIVE_PLUGIN_URL,
173 'give'
174 ))
175 ->dependencies(['jquery'])
176 ->loadInFooter()
177 ->enqueue();
178
179 wp_enqueue_style(
180 'givewp-donation-form-embed-app',
181 GIVE_PLUGIN_URL . 'build/donationFormBlockApp.css'
182 );
183 }
184 }
185