PluginProbe
Kit (formerly ConvertKit) – Email Newsletter, Email Marketing, Membership, Subscribers and Landing Pages / 2.7.4
Kit (formerly ConvertKit) – Email Newsletter, Email Marketing, Membership, Subscribers and Landing Pages v2.7.4
3.4.1 3.4.0 3.3.9 3.3.8 3.3.7 3.3.6 3.3.5 3.3.4 3.3.3 3.3.2 3.3.1 2.2.0 2.2.1 2.2.2 2.2.3 2.2.4 2.2.5 2.2.6 2.2.7 2.2.8 2.2.9 2.3.0 2.3.1 2.3.2 2.3.3 All 194 releases
convertkit / includes / blocks / class-convertkit-block.php

class-convertkit-block.php in Kit (formerly ConvertKit) – Email Newsletter, Email Marketing, Membership, Subscribers and Landing Pages 2.7.4, at includes/blocks/class-convertkit-block.php

427 lines 11.3 KB
No matching file
Up and down to move Enter to open Esc to close
Raw Download Zip
1 <?php
2 /**
3 * ConvertKit Block class.
4 *
5 * @package ConvertKit
6 * @author ConvertKit
7 */
8
9 /**
10 * ConvertKit Block definition for Gutenberg and Shortcode.
11 *
12 * @package ConvertKit
13 * @author ConvertKit
14 */
15 class ConvertKit_Block {
16
17 /**
18 * Registers this block with the ConvertKit Plugin.
19 *
20 * @since 1.9.6
21 *
22 * @param array $blocks Blocks to Register.
23 * @return array Blocks to Register
24 */
25 public function register( $blocks ) {
26
27 $blocks[ $this->get_name() ] = array_merge(
28 $this->get_overview(),
29 array(
30 'name' => $this->get_name(),
31 'fields' => $this->get_fields(),
32 'attributes' => $this->get_attributes(),
33 'supports' => $this->get_supports(),
34 'panels' => $this->get_panels(),
35 'default_values' => $this->get_default_values(),
36 )
37 );
38
39 return $blocks;
40
41 }
42
43 /**
44 * Returns this block's programmatic name, excluding the convertkit- prefix.
45 *
46 * @since 1.9.6
47 */
48 public function get_name() {
49
50 /**
51 * This will register as:
52 * - a shortcode, with the name [convertkit_form].
53 * - a shortcode, with the name [convertkit], for backward compat.
54 * - a Gutenberg block, with the name convertkit/form.
55 */
56 return '';
57
58 }
59
60 /**
61 * Returns this block's Title, Icon, Categories, Keywords and properties.
62 *
63 * @since 1.9.6
64 *
65 * @return array
66 */
67 public function get_overview() {
68
69 return array();
70
71 }
72
73 /**
74 * Returns this block's Attributes
75 *
76 * @since 1.9.6.5
77 *
78 * @return array
79 */
80 public function get_attributes() {
81
82 return array();
83
84 }
85
86 /**
87 * Gutenberg: Returns supported built in attributes, such as
88 * className, color etc.
89 *
90 * @since 1.9.7.4
91 *
92 * @return array Supports
93 */
94 public function get_supports() {
95
96 return array(
97 'className' => true,
98 );
99
100 }
101
102 /**
103 * Returns this block's Fields
104 *
105 * @since 1.9.6
106 *
107 * @return array
108 */
109 public function get_fields() {
110
111 return array();
112
113 }
114
115 /**
116 * Returns this block's UI panels / sections.
117 *
118 * @since 1.9.6
119 *
120 * @return array
121 */
122 public function get_panels() {
123
124 return array();
125
126 }
127
128 /**
129 * Returns this block's Default Values
130 *
131 * @since 1.9.6
132 *
133 * @return array
134 */
135 public function get_default_values() {
136
137 return array();
138
139 }
140
141 /**
142 * Returns the given block's field's Default Value
143 *
144 * @since 1.9.6
145 *
146 * @param string $field Field Name.
147 * @return string
148 */
149 public function get_default_value( $field ) {
150
151 $defaults = $this->get_default_values();
152 if ( isset( $defaults[ $field ] ) ) {
153 return $defaults[ $field ];
154 }
155
156 return '';
157
158 }
159
160 /**
161 * Performs several transformation on a block's attributes, including:
162 * - sanitization
163 * - adding attributes with default values are missing but registered by the block
164 * - cast attribute values based on their defined type
165 *
166 * These steps are performed because the attributes may be defined by a shortcode,
167 * block or third party widget/page builder's block, each of which handle attributes
168 * slightly differently.
169 *
170 * Returns a standardised attributes array.
171 *
172 * @since 1.9.7.4
173 *
174 * @param array $atts Declared attributes.
175 * @return array All attributes, standardised.
176 */
177 public function sanitize_and_declare_atts( $atts ) {
178
179 // Sanitize attributes, merging with default values so that the array
180 // of attributes contains all expected keys for this block.
181 $atts = shortcode_atts(
182 $this->get_default_values(),
183 $this->sanitize_atts( $atts ),
184 $this->get_name()
185 );
186
187 // Fetch attribute definitions.
188 $atts_definitions = $this->get_attributes();
189
190 // Iterate through attributes, casting them based on their attribute definition.
191 foreach ( $atts as $att => $value ) {
192 // Skip if no definition exists for this attribute.
193 if ( ! array_key_exists( $att, $atts_definitions ) ) {
194 continue;
195 }
196
197 // Skip if no type exists for this attribute.
198 if ( ! array_key_exists( 'type', $atts_definitions[ $att ] ) ) {
199 continue;
200 }
201
202 // Cast, depending on the attribute type.
203 switch ( $atts_definitions[ $att ]['type'] ) {
204 case 'number':
205 $atts[ $att ] = (int) $value;
206 break;
207
208 case 'boolean':
209 $atts[ $att ] = (bool) $value;
210 break;
211
212 case 'string':
213 // If the attribute's value is empty, check if the default attribute has a value.
214 // If so, apply it now.
215 // shortcode_atts() will only do this if the attribute key isn't specified.
216 if ( empty( $value ) && ! empty( $this->get_default_value( $att ) ) ) {
217 $atts[ $att ] = $this->get_default_value( $att );
218 }
219 break;
220 }
221 }
222
223 // Build CSS class(es) that might need to be added to the top level element for this block.
224 $atts['_css_classes'] = array( 'convertkit-' . $this->get_name() );
225 $atts['_css_styles'] = array();
226
227 // If the block supports a text color, and a preset color was selected, add it to the
228 // array of CSS classes.
229 if ( $atts['textColor'] ) {
230 $atts['_css_classes'][] = 'has-text-color';
231 $atts['_css_classes'][] = 'has-' . $atts['textColor'] . '-color';
232 }
233
234 // If the block supports a text color, and a custom hex color was selected, add it to the
235 // array of CSS inline styles.
236 if ( isset( $atts['style']['color'] ) && isset( $atts['style']['color']['text'] ) ) {
237 $atts['_css_classes'][] = 'has-text-color';
238 $atts['_css_styles']['color'] = 'color:' . $atts['style']['color']['text'];
239 }
240
241 // If the shortcode supports a text color, and a custom hex color was selected, add it to the
242 // array of CSS inline styles.
243 if ( isset( $atts['text_color'] ) && ! empty( $atts['text_color'] ) ) {
244 $atts['_css_classes'][] = 'has-text-color';
245 $atts['_css_styles']['color'] = 'color:' . $atts['text_color'];
246 }
247
248 // If the block supports a background color, and a preset color was selected, add it to the
249 // array of CSS classes.
250 if ( $atts['backgroundColor'] ) {
251 $atts['_css_classes'][] = 'has-background';
252 $atts['_css_classes'][] = 'has-' . $atts['backgroundColor'] . '-background-color';
253 }
254
255 // If the block supports a background color, and a custom hex color was selected, add it to the
256 // array of CSS inline styles.
257 if ( isset( $atts['style']['color'] ) && isset( $atts['style']['color']['background'] ) ) {
258 $atts['_css_classes'][] = 'has-background';
259 $atts['_css_styles']['background'] = 'background-color:' . $atts['style']['color']['background'];
260 }
261
262 // If the block supports a font size, and a preset font size was selected, add it to the
263 // array of CSS classes.
264 if ( isset( $atts['fontSize'] ) && ! empty( $atts['fontSize'] ) ) {
265 $atts['_css_classes'][] = 'has-custom-font-size';
266 $atts['_css_classes'][] = 'has-' . $atts['fontSize'] . '-font-size';
267 }
268
269 // If the block supports padding, and padding is set, add it to the
270 // array of CSS inline styles.
271 if ( isset( $atts['style']['spacing'] ) && isset( $atts['style']['spacing']['padding'] ) ) {
272 foreach ( $atts['style']['spacing']['padding'] as $position => $value ) {
273 $atts['_css_styles'][ 'padding-' . $position ] = 'padding-' . $position . ':' . $value;
274 }
275 }
276
277 // If the shortcode supports a background color, and a custom hex color was selected, add it to the
278 // array of CSS inline styles.
279 if ( isset( $atts['background_color'] ) && ! empty( $atts['background_color'] ) ) {
280 $atts['_css_classes'][] = 'has-background';
281 $atts['_css_styles']['background'] = 'background-color:' . $atts['background_color'];
282 }
283
284 // Remove some unused attributes, now they're declared above.
285 unset( $atts['style'] );
286
287 return $atts;
288
289 }
290
291 /**
292 * Removes any HTML that might be wrongly included in the shorcode attribute's values
293 * due to e.g. copy and pasting from Documentation or other examples.
294 *
295 * @since 1.9.6
296 *
297 * @param array $atts Block or shortcode attributes.
298 * @return array Block or shortcode attributes
299 */
300 public function sanitize_atts( $atts ) {
301
302 foreach ( $atts as $key => $value ) {
303 if ( is_array( $value ) ) {
304 continue;
305 }
306
307 $atts[ $key ] = wp_strip_all_tags( $value );
308 }
309
310 return $atts;
311
312 }
313
314 /**
315 * Returns the given block / shortcode attributes array as HTML data-* attributes, which can be output
316 * in a block's container.
317 *
318 * @since 1.9.7.6
319 *
320 * @param array $atts Block or shortcode attributes.
321 * @return string Block or shortcode attributes
322 */
323 public function get_atts_as_html_data_attributes( $atts ) {
324
325 // Define attributes provided by Gutenberg, which will be skipped, such as
326 // styling.
327 $skip_keys = array(
328 'backgroundColor',
329 'textColor',
330 '_css_classes',
331 '_css_styles',
332 );
333
334 // Define a blank string to build the data-* attributes in.
335 $data = '';
336
337 foreach ( $atts as $key => $value ) {
338 // Skip built in attributes provided by Gutenberg.
339 if ( in_array( $key, $skip_keys, true ) ) {
340 continue;
341 }
342
343 // Append to data string, replacing underscores with hyphens in the key name.
344 $data .= ' data-' . strtolower( str_replace( '_', '-', $key ) ) . '="' . esc_attr( $value ) . '"';
345 }
346
347 return trim( $data );
348
349 }
350
351 /**
352 * Determines if the request for the block is from the block editor or the frontend site.
353 *
354 * @since 1.9.8.5
355 *
356 * @return bool
357 */
358 public function is_block_editor_request() {
359
360 // Return false if not a WordPress REST API request, which Gutenberg uses.
361 if ( ! defined( 'REST_REQUEST' ) ) {
362 return false;
363 }
364 if ( REST_REQUEST !== true ) {
365 return false;
366 }
367
368 // Return false if the context parameter isn't edit.
369 if ( ! array_key_exists( 'context', $_GET ) ) { // phpcs:ignore WordPress.Security.NonceVerification
370 return false;
371 }
372 if ( sanitize_text_field( $_GET['context'] ) !== 'edit' ) { // phpcs:ignore WordPress.Security.NonceVerification
373 return false;
374 }
375
376 // Request is for the block editor.
377 return true;
378
379 }
380
381 /**
382 * If the Block Visiblity Plugin is active, run the block through its conditions now.
383 * We don't wait for Block Visibility to do this, as it performs this on the
384 * `render_block` filter, by which time the code in this method has fully executed,
385 * meaning any non-inline Forms will have had their scripts added to the
386 * `convertkit_output_scripts_footer` hook.
387 * As a result, the non-inline Form will always display, regardless of whether
388 * Block Visibility's conditions are met.
389 * We deliberately don't output non-inline Forms in their block, instead deferring
390 * to the `convertkit_output_scripts_footer` hook, to ensure the non-inline Forms
391 * styling are not constrained by the Theme's width, layout or other properties.
392 *
393 * @since 2.6.6
394 *
395 * @param array $atts Block Attributes.
396 * @return bool Display Block
397 */
398 public function is_block_visible( $atts ) {
399
400 // Display the block if the Block Visibility Plugin isn't active.
401 if ( ! function_exists( '\BlockVisibility\Frontend\render_with_visibility' ) ) {
402 return true;
403 }
404
405 // Determine whether the block should display.
406 $display_block = \BlockVisibility\Frontend\render_with_visibility(
407 'block',
408 array(
409 'blockName' => 'convertkit-' . $this->get_name(),
410 'attrs' => $atts,
411 )
412 );
413
414 // If the content returned is a blank string, conditions on this block set
415 // by the user in the Block Visibility Plugin resulted in the block not displaying.
416 // Don't display it.
417 if ( empty( $display_block ) ) {
418 return false;
419 }
420
421 // If here, the block can be displayed.
422 return true;
423
424 }
425
426 }
427