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 / Actions / GetExternalEmbedScriptData.php

GetExternalEmbedScriptData.php in GiveWP – Donation Plugin and Fundraising Platform 4.18.0, at src/DonationForms/Actions/GetExternalEmbedScriptData.php

137 lines 4.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\Actions;
4
5 use Give\DonationForms\Models\DonationForm;
6 use Give\Framework\Routes\Route;
7
8 /**
9 * Data the external embed script reads from window.givewpDonationFormEmbed.
10 * Runs when the script is requested, so the strings are in the site's locale
11 * and the URLs reflect the site's current home URL.
12 *
13 * Everything the script needs to know about the WordPress site travels here
14 * rather than being hardcoded in the bundle: the home URL, the routes the
15 * iframe loads, the form's own page, and the parameters an offsite gateway
16 * return carries. The script only appends per-embed values such as the form
17 * id.
18 *
19 * When the script URL names a form (`?form-id=42`, or the `42` path segment),
20 * the response also carries that form's server-rendered skeleton, keyed by
21 * id, so the embed can draw the form's shape before the form page answers.
22 * Only published forms are included, and the id never selects which form the
23 * embed loads: the element looks up its own `form-id` attribute in the map.
24 *
25 * @since 4.17.0
26 */
27 class GetExternalEmbedScriptData
28 {
29 /**
30 * Upper bound on form ids honored per request, so a long list cannot turn
31 * one script request into many form loads.
32 *
33 * @since 4.17.0
34 */
35 private const MAX_FORMS = 10;
36
37 /**
38 * @since 4.17.0
39 *
40 * @param array $request The query arguments and path id the router matched.
41 */
42 public function __invoke(array $request = []): array
43 {
44 return [
45 'homeUrl' => home_url('/'),
46 'formViewUrl' => esc_url_raw(Route::url('donation-form-view')),
47 'receiptViewUrl' => esc_url_raw(Route::url('donation-confirmation-receipt-view')),
48 'formPageUrl' => (new GenerateDonationFormPageUrl())(),
49 /*
50 * The offsite gateway return flow, as GenerateDonationConfirmationReceiptUrl
51 * builds it: the listener params that must match, and the params carrying
52 * the embed and receipt ids.
53 */
54 'receiptReturn' => [
55 'match' => [
56 'givewp-event' => 'donation-completed',
57 'givewp-listener' => 'show-donation-confirmation-receipt',
58 ],
59 'embedIdParam' => 'givewp-embed-id',
60 'receiptIdParam' => 'givewp-receipt-id',
61 ],
62 'i18n' => [
63 'donate' => __('Donate', 'give'),
64 'loading' => __('Loading', 'give'),
65 'formTitle' => __('Donation Form', 'give'),
66 'openForm' => __('Open donation form', 'give'),
67 'close' => __('Close', 'give'),
68 ],
69 // An object even when empty, so the script always sees a map.
70 'skeletons' => (object)$this->skeletons($this->formIds($request)),
71 ];
72 }
73
74 /**
75 * The form ids the request names: a comma list in `form-id` and the path
76 * segment the router returns as `id`. Anything but a plain positive integer
77 * is dropped, then deduplicated and capped.
78 *
79 * @since 4.17.0
80 *
81 * @return int[]
82 */
83 private function formIds(array $request): array
84 {
85 $ids = [];
86
87 if (isset($request['form-id'])) {
88 $ids = is_array($request['form-id']) ? $request['form-id'] : explode(',', (string)$request['form-id']);
89 }
90
91 if (!empty($request['id'])) {
92 $ids[] = $request['id'];
93 }
94
95 // Only plain positive integers: absint() would read "-42" and "42abc" as 42.
96 $ids = array_filter(array_map('trim', array_map('strval', $ids)), 'ctype_digit');
97 $ids = array_values(array_unique(array_filter(array_map('intval', $ids))));
98
99 return array_slice($ids, 0, self::MAX_FORMS);
100 }
101
102 /**
103 * Skeleton markup by form id for the published forms among the ids. A form
104 * whose design the skeleton cannot sketch gets no entry, and the embed
105 * shows a spinner for it.
106 *
107 * @since 4.17.0
108 *
109 * @param int[] $ids
110 *
111 * @return array<int, string>
112 */
113 private function skeletons(array $ids): array
114 {
115 $renderer = new RenderFormSkeleton();
116 $skeletonData = new GetFormSkeletonData();
117 $skeletons = [];
118
119 foreach ($ids as $id) {
120 /** @var DonationForm|null $form */
121 $form = DonationForm::find($id);
122
123 if (!$form || !$form->status->isPublished()) {
124 continue;
125 }
126
127 $markup = $renderer($skeletonData($form));
128
129 if ($markup) {
130 $skeletons[$id] = $markup;
131 }
132 }
133
134 return $skeletons;
135 }
136 }
137