PluginProbe
WPFunnels – Funnel Builder for WooCommerce with Checkout & One Click Upsell / 3.13.1
WPFunnels – Funnel Builder for WooCommerce with Checkout & One Click Upsell v3.13.1
3.13.1 3.13.0 3.12.13 3.12.12 3.12.11 3.12.10 3.12.9 3.12.8 3.12.7 3.12.6 3.12.5 3.12.4 3.12.3 3.12.1 3.12.2 3.12.0 3.11.1 3.11.0 3.10.9 3.10.8 3.10.7 3.10.6 2.8.16 2.8.17 2.8.18 All 259 releases
wpfunnels / includes / core / MCP / Support / ElementorLayoutBuilder.php

ElementorLayoutBuilder.php in WPFunnels – Funnel Builder for WooCommerce with Checkout & One Click Upsell 3.13.1, at includes/core/MCP/Support/ElementorLayoutBuilder.php

271 lines 7.2 KB
No matching file
Up and down to move Enter to open Esc to close
Raw Download Zip
1 <?php
2 /**
3 * ElementorLayoutBuilder — assembles Elementor `_elementor_data` node trees.
4 *
5 * Pure array assembly, no WordPress I/O. Every public factory returns a node
6 * shaped the way Elementor's editor expects it, so the caller only has to
7 * write the result to `_elementor_data` (see PageContentTools::writeElementorTree()).
8 *
9 * @package WPFunnels\MCP\Support
10 * @since 3.13.0
11 */
12
13 namespace WPFunnels\MCP\Support;
14
15 defined( 'ABSPATH' ) || exit;
16
17 /**
18 * Class ElementorLayoutBuilder
19 */
20 class ElementorLayoutBuilder {
21
22 /**
23 * Ids already handed out in the current build, to guarantee uniqueness.
24 *
25 * @var array
26 */
27 private static $used_ids = [];
28
29 /**
30 * Reset id tracking. Call once at the start of building a tree.
31 *
32 * @return void
33 */
34 public static function reset() {
35 self::$used_ids = [];
36 }
37
38 /**
39 * Unique 7-char id, Elementor's own node id format.
40 *
41 * @return string
42 */
43 public static function newId() {
44 do {
45 $id = substr( bin2hex( random_bytes( 4 ) ), 0, 7 );
46 } while ( isset( self::$used_ids[ $id ] ) );
47
48 self::$used_ids[ $id ] = true;
49
50 return $id;
51 }
52
53 /**
54 * A section node.
55 *
56 * @param array $columns Column nodes.
57 * @param array $settings Section settings.
58 * @return array
59 */
60 public static function section( $columns, $settings = [] ) {
61 return [
62 'id' => self::newId(),
63 'elType' => 'section',
64 'settings' => $settings,
65 'elements' => $columns,
66 'isInner' => false,
67 ];
68 }
69
70 /**
71 * A column node, full-width by default.
72 *
73 * @param array $widgets Widget nodes.
74 * @param array $settings Column settings.
75 * @return array
76 */
77 public static function column( $widgets, $settings = [] ) {
78 return [
79 'id' => self::newId(),
80 'elType' => 'column',
81 'settings' => array_merge( [ '_column_size' => 100 ], $settings ),
82 'elements' => $widgets,
83 ];
84 }
85
86 /**
87 * A widget node.
88 *
89 * @param string $widget_type Elementor widget slug (its `get_name()`).
90 * @param array $settings Widget settings.
91 * @return array
92 */
93 public static function widget( $widget_type, $settings = [] ) {
94 return [
95 'id' => self::newId(),
96 'elType' => 'widget',
97 'widgetType' => $widget_type,
98 'settings' => $settings,
99 'elements' => [],
100 ];
101 }
102
103 /**
104 * Convenience: wrap a single widget in its own full-width section/column.
105 *
106 * @param array $widget Widget node.
107 * @return array Section node.
108 */
109 public static function sectionFor( $widget ) {
110 return self::section( [ self::column( [ $widget ] ) ] );
111 }
112
113 /**
114 * Core `heading` widget.
115 *
116 * @param string $text Heading text.
117 * @param string $size Header tag (h1-h6).
118 * @return array
119 */
120 public static function headingWidget( $text, $size = 'h2' ) {
121 return self::widget(
122 'heading',
123 [
124 'title' => $text,
125 'header_size' => $size,
126 ]
127 );
128 }
129
130 /**
131 * Core `text-editor` widget. Accepts HTML.
132 *
133 * @param string $html Editor content.
134 * @return array
135 */
136 public static function textWidget( $html ) {
137 return self::widget( 'text-editor', [ 'editor' => $html ] );
138 }
139
140 /**
141 * `<ul>` rendering of a benefits list, as a text-editor widget.
142 *
143 * @param array $benefits Benefit strings.
144 * @return array|null Null when there is nothing to render.
145 */
146 public static function benefitsWidget( $benefits ) {
147 if ( empty( $benefits ) ) {
148 return null;
149 }
150
151 $items = implode(
152 '',
153 array_map(
154 static function ( $benefit ) {
155 return '<li>' . esc_html( $benefit ) . '</li>';
156 },
157 $benefits
158 )
159 );
160
161 return self::textWidget( '<ul>' . $items . '</ul>' );
162 }
163
164 /**
165 * `wpfnl-optin-form` widget.
166 *
167 * @param array $args Optional overrides: cta_text, collect_name, primary_color.
168 * @return array
169 */
170 public static function optinWidget( $args = [] ) {
171 $settings = [
172 'btn_text' => isset( $args['cta_text'] ) ? $args['cta_text'] : 'Get Started',
173 'first_name' => empty( $args['collect_name'] ) ? '' : 'yes',
174 'first_name_label' => 'First Name',
175 'email_label' => 'Email',
176 'acceptance_checkbox' => '',
177 ];
178
179 if ( ! empty( $args['primary_color'] ) ) {
180 $settings['btn_bg_color'] = $args['primary_color'];
181 }
182
183 return self::widget( 'wpfnl-optin-form', $settings );
184 }
185
186 /**
187 * `wpfnl-checkout` widget.
188 *
189 * @param array $args Optional overrides: cta_text, subheadline, layout, primary_color.
190 * @return array
191 */
192 public static function checkoutWidget( $args = [] ) {
193 $settings = [
194 'checkout_layout' => isset( $args['layout'] ) ? $args['layout'] : 'wpfnl-col-2',
195 'place_order_btn_text' => isset( $args['cta_text'] ) ? $args['cta_text'] : 'Place Order',
196 'place_order_sub_text' => isset( $args['subheadline'] ) ? $args['subheadline'] : '',
197 ];
198
199 if ( ! empty( $args['primary_color'] ) ) {
200 $settings['order_button_bg_color'] = $args['primary_color'];
201 }
202
203 return self::widget( 'wpfnl-checkout', $settings );
204 }
205
206 /**
207 * `wpfnl-offer` widget (one instance — call twice for accept + reject).
208 *
209 * @param array $args offer_type (accept|reject), text, subtitle, primary_color.
210 * @return array
211 */
212 public static function offerWidget( $args ) {
213 $settings = [
214 'offer_button_type' => isset( $args['offer_button_type'] ) ? $args['offer_button_type'] : 'upsell',
215 'offer_type' => isset( $args['offer_type'] ) ? $args['offer_type'] : 'accept',
216 'text' => isset( $args['text'] ) ? $args['text'] : 'Accept Offer',
217 ];
218
219 if ( ! empty( $args['subtitle'] ) ) {
220 $settings['enable_subtitle'] = 'yes';
221 $settings['subtitle_text'] = $args['subtitle'];
222 }
223
224 if ( ! empty( $args['primary_color'] ) ) {
225 $settings['background_color'] = $args['primary_color'];
226 }
227
228 return self::widget( 'wpfnl-offer', $settings );
229 }
230
231 /**
232 * `wpfnl-next-step` widget.
233 *
234 * @param array $args cta_text, button_type_selector, primary_color.
235 * @return array
236 */
237 public static function nextStepWidget( $args = [] ) {
238 $settings = [
239 'button_type_selector' => isset( $args['button_type_selector'] ) ? $args['button_type_selector'] : 'checkout',
240 'text' => isset( $args['cta_text'] ) ? $args['cta_text'] : 'Go Next',
241 ];
242
243 if ( ! empty( $args['primary_color'] ) ) {
244 $settings['background_color'] = $args['primary_color'];
245 }
246
247 return self::widget( 'wpfnl-next-step', $settings );
248 }
249
250 /**
251 * `wpfnl-order-bump` widget. Cosmetic defaults only — the settings
252 * `wpfunnels/upsert-order-bump` writes to `order-bump-settings` postmeta
253 * are the source of truth and resync this widget's fields separately.
254 *
255 * @param array $args layout, checkbox_label, header, detail, product_id.
256 * @return array
257 */
258 public static function orderBumpWidget( $args = [] ) {
259 return self::widget(
260 'wpfnl-order-bump',
261 [
262 'order_bump_layout' => isset( $args['layout'] ) ? $args['layout'] : 'horizontal',
263 'order_bump_product_selector' => isset( $args['product_id'] ) ? $args['product_id'] : '',
264 'order_bump_checkbox_label' => isset( $args['checkbox_label'] ) ? $args['checkbox_label'] : 'Try this product',
265 'order_bump_product_detail_header' => isset( $args['header'] ) ? $args['header'] : 'Amazing Product',
266 'order_bump_product_detail' => isset( $args['detail'] ) ? $args['detail'] : 'Product description',
267 ]
268 );
269 }
270 }
271