PluginProbe
Kit (formerly ConvertKit) – Email Newsletter, Email Marketing, Membership, Subscribers and Landing Pages / 3.4.5
Kit (formerly ConvertKit) – Email Newsletter, Email Marketing, Membership, Subscribers and Landing Pages v3.4.5
3.4.5 3.4.4 3.4.3 3.4.2 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 All 198 releases
← All changes | includes/blocks/class-convertkit-block-broadcasts.php +399 -100 2.2.0 → 3.4.5 View file →
@@ -26,30 +26,87 @@
26 26
27 27 // Register this as a Gutenberg block in the ConvertKit Plugin.
28 28 add_filter( 'convertkit_blocks', array( $this, 'register' ) );
29 29
30 - // Enqueue scripts and styles for this Gutenberg Block in the editor view.
31 - add_action( 'convertkit_gutenberg_enqueue_scripts', array( $this, 'enqueue_scripts_editor' ) );
30 + // Register this block's MCP abilities.
31 + add_filter( 'convertkit_abilities', array( $this, 'register_abilities' ) );
32 32
33 33 // Enqueue scripts and styles for this Gutenberg Block in the editor and frontend views.
34 34 add_action( 'convertkit_gutenberg_enqueue_scripts_editor_and_frontend', array( $this, 'enqueue_scripts' ) );
35 35 add_action( 'convertkit_gutenberg_enqueue_styles_editor_and_frontend', array( $this, 'enqueue_styles' ) );
36 36
37 - // Render Broadcasts block via AJAX.
38 - add_action( 'wp_ajax_nopriv_convertkit_broadcasts_render', array( $this, 'render_ajax' ) );
39 - add_action( 'wp_ajax_convertkit_broadcasts_render', array( $this, 'render_ajax' ) );
37 + // Register REST API routes.
38 + add_action( 'rest_api_init', array( $this, 'register_routes' ) );
40 39
41 40 }
42 41
43 42 /**
44 - * Enqueues scripts for this Gutenberg Block in the editor view.
43 + * Register REST API routes.
45 44 *
46 - * @since 2.0.1
45 + * @since 3.1.8
47 46 */
48 - public function enqueue_scripts_editor() {
47 + public function register_routes() {
49 48
50 - wp_enqueue_script( 'convertkit-gutenberg-block-broadcasts', CONVERTKIT_PLUGIN_URL . 'resources/backend/js/gutenberg-block-broadcasts.js', array( 'convertkit-gutenberg' ), CONVERTKIT_PLUGIN_VERSION, true );
49 + register_rest_route(
50 + 'kit/v1',
51 + '/broadcasts',
52 + array(
53 + 'methods' => WP_REST_Server::READABLE,
54 + 'args' => array(
55 + 'date_format' => array(
56 + 'default' => $this->get_default_value( 'date_format' ),
57 + 'sanitize_callback' => 'sanitize_text_field',
58 + ),
59 + 'display_image' => array(
60 + 'default' => $this->get_default_value( 'display_image' ),
61 + 'sanitize_callback' => 'absint',
62 + ),
63 + 'display_description' => array(
64 + 'default' => $this->get_default_value( 'display_description' ),
65 + 'sanitize_callback' => 'absint',
66 + ),
67 + 'display_read_more' => array(
68 + 'default' => $this->get_default_value( 'display_read_more' ),
69 + 'sanitize_callback' => 'absint',
70 + ),
71 + 'read_more_label' => array(
72 + 'default' => $this->get_default_value( 'read_more_label' ),
73 + 'sanitize_callback' => 'sanitize_text_field',
74 + ),
75 + 'limit' => array(
76 + 'default' => $this->get_default_value( 'limit' ),
77 + 'sanitize_callback' => 'absint',
78 + ),
79 + 'page' => array(
80 + 'default' => $this->get_default_value( 'page' ),
81 + 'sanitize_callback' => 'absint',
82 + ),
83 + 'paginate' => array(
84 + 'default' => $this->get_default_value( 'paginate' ),
85 + 'sanitize_callback' => 'absint',
86 + ),
87 + 'paginate_label_next' => array(
88 + 'default' => $this->get_default_value( 'paginate_label_next' ),
89 + 'sanitize_callback' => 'sanitize_text_field',
90 + ),
91 + 'paginate_label_prev' => array(
92 + 'default' => $this->get_default_value( 'paginate_label_prev' ),
93 + 'sanitize_callback' => 'sanitize_text_field',
94 + ),
95 + 'link_color' => array(
96 + 'default' => $this->get_default_value( 'link_color' ),
97 + 'sanitize_callback' => 'sanitize_text_field',
98 + ),
99 + ),
100 + 'callback' => function ( $request ) {
101 + return rest_ensure_response( $this->render_ajax( $request ) );
102 + },
51 103
104 + // No authentication required, as this is on the frontend site.
105 + 'permission_callback' => '__return_true',
106 + )
107 + );
108 +
52 109 }
53 110
54 111 /**
55 112 * Enqueues scripts for this Gutenberg Block in the editor and frontend views.
@@ -60,23 +117,24 @@
60 117
61 118 // Get ConvertKit Settings.
62 119 $settings = new ConvertKit_Settings();
63 120
64 - wp_enqueue_script( 'convertkit-' . $this->get_name(), CONVERTKIT_PLUGIN_URL . 'resources/frontend/js/broadcasts.js', array( 'jquery' ), CONVERTKIT_PLUGIN_VERSION, true );
121 + // Enqueue frontend JS.
122 + convertkit_enqueue_frontend_js();
123 +
124 + // Define variables.
65 125 wp_localize_script(
66 - 'convertkit-' . $this->get_name(),
126 + 'convertkit-js',
67 127 'convertkit_broadcasts',
68 128 array(
69 - // WordPress AJAX URL endpoint.
70 - 'ajax_url' => admin_url( 'admin-ajax.php' ),
129 + // REST API URL endpoint.
130 + 'ajax_url' => rest_url( 'kit/v1/broadcasts' ),
71 131
72 - // AJAX action registered in __construct().
73 - 'action' => 'convertkit_broadcasts_render',
74 -
75 132 // Whether debugging is enabled.
76 133 'debug' => $settings->debug_enabled(),
77 134 )
78 135 );
136 +
79 137 }
80 138
81 139 /**
82 140 * Enqueues styles for this Gutenberg Block in the editor and frontend views.
@@ -84,9 +142,9 @@
84 142 * @since 1.9.7.4
85 143 */
86 144 public function enqueue_styles() {
87 145
88 - wp_enqueue_style( 'convertkit-' . $this->get_name(), CONVERTKIT_PLUGIN_URL . 'resources/frontend/css/broadcasts.css', array(), CONVERTKIT_PLUGIN_VERSION );
146 + convertkit_enqueue_frontend_css();
89 147
90 148 }
91 149
92 150 /**
@@ -98,8 +156,9 @@
98 156
99 157 /**
100 158 * This will register as:
101 159 * - a shortcode, with the name [convertkit_broadcasts].
160 + * - a shortcode, with the name [kit_broadcasts].
102 161 * - a Gutenberg block, with the name convertkit/broadcasts.
103 162 */
104 163 return 'broadcasts';
105 164
@@ -105,8 +164,43 @@
105 164
106 165 }
107 166
108 167 /**
168 + * Returns this block's title.
169 + *
170 + * @since 3.1.1
171 + */
172 + public function get_title() {
173 +
174 + return __( 'Kit Broadcasts', 'convertkit' );
175 +
176 + }
177 +
178 + /**
179 + * Returns this block's plural title.
180 + *
181 + * @since 3.4.0
182 + *
183 + * @return string
184 + */
185 + public function get_title_plural() {
186 +
187 + return __( 'Kit Broadcasts', 'convertkit' );
188 +
189 + }
190 +
191 + /**
192 + * Returns this block's icon.
193 + *
194 + * @since 3.1.1
195 + */
196 + public function get_icon() {
197 +
198 + return 'resources/backend/images/block-icon-broadcasts.svg';
199 +
200 + }
201 +
202 + /**
109 203 * Returns this block's Title, Icon, Categories, Keywords and properties.
110 204 *
111 205 * @since 1.9.7.4
112 206 */
@@ -112,48 +206,59 @@
112 206 */
113 207 public function get_overview() {
114 208
115 209 // Fetch Posts.
116 - $posts = new ConvertKit_Resource_Posts( 'output_broadcasts' );
210 + $posts = new ConvertKit_Resource_Posts( 'output_broadcasts' );
211 + $settings = new ConvertKit_Settings();
117 212
118 213 return array(
119 - 'title' => __( 'ConvertKit Broadcasts', 'convertkit' ),
120 - 'description' => __( 'Displays a list of your ConvertKit broadcasts.', 'convertkit' ),
121 - 'icon' => 'resources/backend/images/block-icon-broadcasts.png',
122 - 'category' => 'convertkit',
123 - 'keywords' => array(
214 + 'title' => $this->get_title(),
215 + 'description' => __( 'Displays a list of your Kit broadcasts.', 'convertkit' ),
216 + 'icon' => $this->get_icon(),
217 + 'category' => 'convertkit',
218 + 'keywords' => array(
124 219 __( 'ConvertKit', 'convertkit' ),
220 + __( 'Kit', 'convertkit' ),
125 221 __( 'Broadcasts', 'convertkit' ),
126 222 __( 'Posts', 'convertkit' ),
127 223 ),
128 224
129 225 // Function to call when rendering as a block or a shortcode on the frontend web site.
130 - 'render_callback' => array( $this, 'render' ),
226 + 'render_callback' => array( $this, 'render' ),
131 227
132 228 // Shortcode: TinyMCE / QuickTags Modal Width and Height.
133 - 'modal' => array(
134 - 'width' => 500,
135 - 'height' => 580,
229 + 'modal' => array(
230 + 'width' => 650,
231 + 'height' => 455,
136 232 ),
137 233
138 234 // Shortcode: Include a closing [/shortcode] tag when using TinyMCE or QuickTag Modals.
139 - 'shortcode_include_closing_tag' => false,
235 + 'shortcode_include_closing_tag' => false,
140 236
141 237 // Gutenberg: Block Icon in Editor.
142 - 'gutenberg_icon' => file_get_contents( CONVERTKIT_PLUGIN_PATH . '/resources/backend/images/block-icon-broadcasts.svg' ), /* phpcs:ignore */
238 + 'gutenberg_icon' => convertkit_get_file_contents( CONVERTKIT_PLUGIN_PATH . '/resources/backend/images/block-icon-broadcasts.svg' ),
143 239
144 240 // Gutenberg: Example image showing how this block looks when choosing it in Gutenberg.
145 - 'gutenberg_example_image' => CONVERTKIT_PLUGIN_URL . 'resources/backend/images/block-example-broadcasts.png',
241 + 'gutenberg_example_image' => CONVERTKIT_PLUGIN_URL . 'resources/backend/images/block-example-broadcasts.png',
146 242
147 - // Gutenberg: Help description, displayed when no Posts exist.
148 - 'gutenberg_help_description' => __( 'No Broadcasts exist in ConvertKit. Send your first Broadcast in ConvertKit to see the link to it here.', 'convertkit' ),
243 + // Help descriptions, displayed when no Access Token / resources exist and this block/shortcode is added.
244 + 'no_access_token' => array(
245 + 'notice' => __( 'Not connected to Kit.', 'convertkit' ),
246 + 'link' => convertkit_get_setup_wizard_plugin_link(),
247 + 'link_text' => __( 'Click here to connect your Kit account.', 'convertkit' ),
248 + 'instruction_text' => __( 'Connect your Kit account at Settings > Kit, and then refresh this page to configure broadcasts to display.', 'convertkit' ),
249 + ),
250 + 'no_resources' => array(
251 + 'notice' => __( 'No broadcasts exist in Kit.', 'convertkit' ),
252 + 'link' => convertkit_get_new_broadcast_url(),
253 + 'link_text' => __( 'Click here to send your first broadcast.', 'convertkit' ),
254 + 'instruction_text' => __( 'Add a broadcast to your Kit account, and then refresh this page to configure broadcasts to display.', 'convertkit' ),
255 + ),
149 256
150 - // Gutenberg: JS function to call when rendering the block preview in the Gutenberg editor.
151 - // If not defined, render_callback above will be used.
152 - 'gutenberg_preview_render_callback' => 'convertKitGutenbergBroadcastsBlockRenderPreview',
153 -
154 - // Flag to determine if Broadcasts exist.
155 - 'has_posts' => $posts->exist(),
257 + // Whether an API Key exists in the Plugin, and are the required resources (broadcasts) available.
258 + // If no API Key is specified in the Plugin's settings, render the "No API Key" output.
259 + 'has_access_token' => $settings->has_access_and_refresh_token(),
260 + 'has_resources' => $posts->exist(),
156 261 );
157 262
158 263 }
159 264
@@ -165,12 +270,36 @@
165 270 public function get_attributes() {
166 271
167 272 return array(
168 273 // Block attributes.
274 + 'display_grid' => array(
275 + 'type' => 'boolean',
276 + 'default' => $this->get_default_value( 'display_grid' ),
277 + ),
278 + 'display_order' => array(
279 + 'type' => 'string',
280 + 'default' => $this->get_default_value( 'display_order' ),
281 + ),
169 282 'date_format' => array(
170 283 'type' => 'string',
171 284 'default' => $this->get_default_value( 'date_format' ),
172 285 ),
286 + 'display_image' => array(
287 + 'type' => 'boolean',
288 + 'default' => $this->get_default_value( 'display_image' ),
289 + ),
290 + 'display_description' => array(
291 + 'type' => 'boolean',
292 + 'default' => $this->get_default_value( 'display_description' ),
293 + ),
294 + 'display_read_more' => array(
295 + 'type' => 'boolean',
296 + 'default' => $this->get_default_value( 'display_read_more' ),
297 + ),
298 + 'read_more_label' => array(
299 + 'type' => 'string',
300 + 'default' => $this->get_default_value( 'read_more_label' ),
301 + ),
173 302 'limit' => array(
174 303 'type' => 'number',
175 304 'default' => $this->get_default_value( 'limit' ),
176 305 ),
@@ -190,9 +319,9 @@
190 319 'type' => 'string',
191 320 'default' => $this->get_default_value( 'paginate_label_next' ),
192 321 ),
193 322
194 - // get_supports() color attribute.
323 + // get_supports() style, color and typography attributes.
195 324 'style' => array(
196 325 'type' => 'object',
197 326 ),
198 327 'backgroundColor' => array(
@@ -200,8 +329,11 @@
200 329 ),
201 330 'textColor' => array(
202 331 'type' => 'string',
203 332 ),
333 + 'fontSize' => array(
334 + 'type' => 'string',
335 + ),
204 336
205 337 // Always required for Gutenberg.
206 338 'is_gutenberg_example' => array(
207 339 'type' => 'boolean',
@@ -220,14 +352,22 @@
220 352 */
221 353 public function get_supports() {
222 354
223 355 return array(
224 - 'className' => true,
225 - 'color' => array(
356 + 'className' => true,
357 + 'color' => array(
226 358 'link' => true,
227 359 'background' => true,
228 360 'text' => true,
229 361 ),
362 + 'typography' => array(
363 + 'fontSize' => true,
364 + 'lineHeight' => true,
365 + ),
366 + 'spacing' => array(
367 + 'margin' => true,
368 + 'padding' => true,
369 + ),
230 370 );
231 371
232 372 }
233 373
@@ -239,14 +379,22 @@
239 379 * @return bool|array
240 380 */
241 381 public function get_fields() {
242 382
243 - // Bail if the request is not for the WordPress Administration or frontend editor.
244 - if ( ! WP_ConvertKit()->is_admin_or_frontend_editor() ) {
245 - return false;
246 - }
247 -
248 383 return array(
384 + 'display_grid' => array(
385 + 'label' => __( 'Display as grid', 'convertkit' ),
386 + 'type' => 'toggle',
387 + 'description' => __( 'If enabled, displays broadcasts in a grid, instead of a list.', 'convertkit' ),
388 + ),
389 + 'display_order' => array(
390 + 'label' => __( 'Display order', 'convertkit' ),
391 + 'type' => 'select',
392 + 'values' => array(
393 + 'date-broadcast' => __( 'Date, Broadcast', 'convertkit' ),
394 + 'broadcast-date' => __( 'Broadcast, Date', 'convertkit' ),
395 + ),
396 + ),
249 397 'date_format' => array(
250 398 'label' => __( 'Date format', 'convertkit' ),
251 399 'type' => 'select',
252 400 'values' => array(
@@ -255,8 +403,29 @@
255 403 'm/d/Y' => date_i18n( 'm/d/Y', strtotime( 'now' ) ),
256 404 'd/m/Y' => date_i18n( 'd/m/Y', strtotime( 'now' ) ),
257 405 ),
258 406 ),
407 + 'display_image' => array(
408 + 'label' => __( 'Display images', 'convertkit' ),
409 + 'type' => 'toggle',
410 + ),
411 + 'display_description' => array(
412 + 'label' => __( 'Display descriptions', 'convertkit' ),
413 + 'type' => 'toggle',
414 + ),
415 + 'display_read_more' => array(
416 + 'label' => __( 'Display read more links', 'convertkit' ),
417 + 'type' => 'toggle',
418 + ),
419 + 'read_more_label' => array(
420 + 'label' => __( 'Read more label', 'convertkit' ),
421 + 'type' => 'text',
422 + 'description' => __( 'The label to display for the "read more" link below each broadcast.', 'convertkit' ),
423 + 'display_if' => array(
424 + 'key' => 'display_read_more',
425 + 'value' => 1,
426 + ),
427 + ),
259 428 'limit' => array(
260 429 'label' => __( 'Number of posts', 'convertkit' ),
261 430 'type' => 'number',
262 431 'min' => 1,
@@ -271,13 +440,21 @@
271 440 'paginate_label_prev' => array(
272 441 'label' => __( 'Newer posts label', 'convertkit' ),
273 442 'type' => 'text',
274 443 'description' => __( 'The label to display for the link to newer broadcasts.', 'convertkit' ),
444 + 'display_if' => array(
445 + 'key' => 'paginate',
446 + 'value' => 1,
447 + ),
275 448 ),
276 449 'paginate_label_next' => array(
277 450 'label' => __( 'Older posts label', 'convertkit' ),
278 451 'type' => 'text',
279 452 'description' => __( 'The label to display for the link to older broadcasts.', 'convertkit' ),
453 + 'display_if' => array(
454 + 'key' => 'paginate',
455 + 'value' => 1,
456 + ),
280 457 ),
281 458
282 459 // These fields will only display on the shortcode, and are deliberately not registered in get_attributes(),
283 460 // because Gutenberg will register its own color pickers for link, background and text.
@@ -305,22 +482,33 @@
305 482 * @return bool|array
306 483 */
307 484 public function get_panels() {
308 485
309 - // Bail if the request is not for the WordPress Administration or frontend editor.
310 - if ( ! WP_ConvertKit()->is_admin_or_frontend_editor() ) {
311 - return false;
312 - }
313 -
314 486 return array(
315 - 'general' => array(
487 + 'general' => array(
316 488 'label' => __( 'General', 'convertkit' ),
317 489 'fields' => array(
490 + 'display_grid',
491 + 'display_order',
318 492 'date_format',
493 + 'display_image',
494 + 'display_description',
495 + 'display_read_more',
496 + 'read_more_label',
497 + ),
498 + ),
499 + 'pagination' => array(
500 + 'label' => __( 'Pagination', 'convertkit' ),
501 + 'fields' => array(
319 502 'limit',
320 503 'paginate',
321 504 'paginate_label_prev',
322 505 'paginate_label_next',
506 + ),
507 + ),
508 + 'styles' => array(
509 + 'label' => __( 'Styles', 'convertkit' ),
510 + 'fields' => array(
323 511 'link_color',
324 512 'background_color',
325 513 'text_color',
326 514 ),
@@ -338,9 +526,15 @@
338 526 */
339 527 public function get_default_values() {
340 528
341 529 return array(
530 + 'display_grid' => false,
531 + 'display_order' => 'date-broadcast',
342 532 'date_format' => 'F j, Y',
533 + 'display_image' => false,
534 + 'display_description' => false,
535 + 'display_read_more' => false,
536 + 'read_more_label' => __( 'Read more', 'convertkit' ),
343 537 'limit' => 10,
344 538 'paginate' => false,
345 539 'paginate_label_prev' => __( 'Previous', 'convertkit' ),
346 540 'paginate_label_next' => __( 'Next', 'convertkit' ),
@@ -363,10 +557,10 @@
363 557 * Returns the block's output, based on the supplied configuration attributes.
364 558 *
365 559 * @since 1.9.7.4
366 560 *
367 - * @param array $atts Block / Shortcode Attributes.
368 - * @return string Output
561 + * @param array $atts Block / Shortcode / Page Builder Module Attributes.
562 + * @return string
369 563 */
370 564 public function render( $atts ) {
371 565
372 566 // Parse attributes, defining fallback defaults if required
@@ -378,19 +572,12 @@
378 572
379 573 // Fetch Posts.
380 574 $posts = new ConvertKit_Resource_Posts( 'output_broadcasts' );
381 575
382 - // If this is an admin request, refresh the Posts resource now from the API,
383 - // as it's an inexpensive query of ~ 0.5 seconds when we're editing a Page
384 - // containing this block.
385 - if ( function_exists( 'is_admin' ) && is_admin() ) {
386 - $posts->refresh();
387 - }
388 -
389 576 // If no Posts exist, bail.
390 577 if ( ! $posts->exist() ) {
391 578 if ( $settings->debug_enabled() ) {
392 - return '<!-- ' . __( 'No Broadcasts exist in ConvertKit.', 'convertkit' ) . ' -->';
579 + return '<!-- ' . __( 'No Broadcasts exist in Kit.', 'convertkit' ) . ' -->';
393 580 }
394 581
395 582 return '';
396 583 }
@@ -395,9 +582,29 @@
395 582 return '';
396 583 }
397 584
398 585 // Build HTML.
399 - $html = $this->build_html( $posts, $atts );
586 + if ( $this->is_block_editor_request() ) {
587 + // For the block editor, don't include compiled CSS classes and styles,
588 + // as the block editor will add these to the parent container.
589 + // Otherwise the block will render incorrectly with double padding, double margins etc.
590 + $html = $this->build_html(
591 + $posts,
592 + $atts,
593 + true,
594 + array(
595 + 'convertkit-' . $this->get_name(),
596 + )
597 + );
598 + } else {
599 + $html = $this->build_html(
600 + $posts,
601 + $atts,
602 + true,
603 + $this->get_css_classes(),
604 + $this->get_css_styles( $atts )
605 + );
606 + }
400 607
401 608 /**
402 609 * Filter the block's content immediately before it is output.
403 610 *
@@ -402,10 +609,10 @@
402 609 * Filter the block's content immediately before it is output.
403 610 *
404 611 * @since 1.9.7.4
405 612 *
406 - * @param string $html ConvertKit Broadcasts HTML.
407 - * @param array $atts Block Attributes.
613 + * @param string $html ConvertKit Broadcasts HTML.
614 + * @param array $atts Block Attributes.
408 615 */
409 616 $html = apply_filters( 'convertkit_block_broadcasts_render', $html, $atts );
410 617
411 618 return $html;
@@ -416,23 +623,27 @@
416 623 * Returns the block's output, based on the supplied configuration attributes,
417 624 * when requested via AJAX.
418 625 *
419 626 * @since 1.9.7.6
627 + *
628 + * @param WP_REST_Request $request The REST request.
629 + * @return string
420 630 */
421 - public function render_ajax() {
631 + public function render_ajax( $request ) {
422 632
423 - // Check nonce.
424 - check_ajax_referer( 'convertkit-broadcasts', 'nonce' );
425 -
426 633 // Build attributes array.
427 634 $atts = array(
428 - 'date_format' => stripslashes( sanitize_text_field( $_REQUEST['date_format'] ) ),
429 - 'limit' => stripslashes( sanitize_text_field( $_REQUEST['limit'] ) ),
430 - 'page' => absint( $_REQUEST['page'] ),
431 - 'paginate' => absint( $_REQUEST['paginate'] ),
432 - 'paginate_label_next' => stripslashes( sanitize_text_field( $_REQUEST['paginate_label_next'] ) ),
433 - 'paginate_label_prev' => stripslashes( sanitize_text_field( $_REQUEST['paginate_label_prev'] ) ),
434 - 'link_color' => stripslashes( sanitize_text_field( $_REQUEST['link_color'] ) ),
635 + 'date_format' => $request->get_param( 'date_format' ),
636 + 'display_image' => $request->get_param( 'display_image' ),
637 + 'display_description' => $request->get_param( 'display_description' ),
638 + 'display_read_more' => $request->get_param( 'display_read_more' ),
639 + 'read_more_label' => $request->get_param( 'read_more_label' ),
640 + 'limit' => $request->get_param( 'limit' ),
641 + 'page' => $request->get_param( 'page' ),
642 + 'paginate' => $request->get_param( 'paginate' ),
643 + 'paginate_label_next' => $request->get_param( 'paginate_label_next' ),
644 + 'paginate_label_prev' => $request->get_param( 'paginate_label_prev' ),
645 + 'link_color' => $request->get_param( 'link_color' ),
435 646 );
436 647
437 648 // Parse attributes, defining fallback defaults if required
438 649 // and moving some attributes (such as Gutenberg's styles), if defined.
@@ -437,11 +648,23 @@
437 648 // Parse attributes, defining fallback defaults if required
438 649 // and moving some attributes (such as Gutenberg's styles), if defined.
439 650 $atts = $this->sanitize_and_declare_atts( $atts );
440 651
652 + // Setup Settings class.
653 + $settings = new ConvertKit_Settings();
654 +
441 655 // Fetch Posts.
442 656 $posts = new ConvertKit_Resource_Posts( 'output_broadcasts' );
443 657
658 + // If no Posts exist, bail.
659 + if ( ! $posts->exist() ) {
660 + if ( $settings->debug_enabled() ) {
661 + return '<!-- ' . __( 'No Broadcasts exist in Kit.', 'convertkit' ) . ' -->';
662 + }
663 +
664 + return '';
665 + }
666 +
444 667 // Build HTML.
445 668 $html = $this->build_html( $posts, $atts, false );
446 669
447 670 /**
@@ -454,10 +677,9 @@
454 677 * @param array $atts Block Attributes.
455 678 */
456 679 $html = apply_filters( 'convertkit_block_broadcasts_render_ajax', $html, $atts );
457 680
458 - // Send HTML as response.
459 - wp_send_json_success( $html );
681 + return $html;
460 682
461 683 }
462 684
463 685 /**
@@ -468,11 +690,13 @@
468 690 *
469 691 * @param ConvertKit_Resource_Posts $posts ConvertKit Posts Resource class.
470 692 * @param array $atts Block attributes.
471 693 * @param bool $include_container Include container div in HTML.
472 - * @return string HTML
694 + * @param array $css_classes CSS classes to apply to block.
695 + * @param array $css_styles CSS inline styles to apply to block.
696 + * @return string
473 697 */
474 - private function build_html( $posts, $atts, $include_container = true ) {
698 + private function build_html( $posts, $atts, $include_container = true, $css_classes = array(), $css_styles = array() ) {
475 699
476 700 // Get paginated subset of Posts.
477 701 $broadcasts = $posts->get_paginated_subset( $atts['page'], $atts['limit'] );
478 702
@@ -483,33 +707,18 @@
483 707 $html = '';
484 708
485 709 // Include container, if required.
486 710 if ( $include_container ) {
487 - $html = '<div class="' . implode( ' ', map_deep( $atts['_css_classes'], 'sanitize_html_class' ) ) . '" style="' . implode( ';', map_deep( $atts['_css_styles'], 'esc_attr' ) ) . '" ' . $this->get_atts_as_html_data_attributes( $atts ) . '>';
711 + $html .= '<div class="' . implode( ' ', map_deep( $css_classes, 'sanitize_html_class' ) ) . '" style="' . implode( ';', map_deep( $css_styles, 'esc_attr' ) ) . '" ' . $this->get_atts_as_html_data_attributes( $atts ) . '>';
488 712 }
489 713
490 714 // Start list.
491 715 $html .= '<ul class="convertkit-broadcasts-list">';
492 716
493 - // Iterate through broadcasts.
717 + // Iterate through broadcasts, building HTML list items.
494 718 foreach ( $broadcasts['items'] as $count => $broadcast ) {
495 - // Convert UTC date to timestamp.
496 - $date_timestamp = strtotime( $broadcast['published_at'] );
497 -
498 - // Build broadcast URL.
499 - $url = add_query_arg(
500 - array(
501 - 'utm_source' => 'wordpress',
502 - 'utm_content' => 'convertkit',
503 - ),
504 - $broadcast['url']
505 - );
506 -
507 719 // Add broadcast as list item.
508 - $html .= '<li class="convertkit-broadcast">
509 - <time datetime="' . esc_attr( date_i18n( 'Y-m-d', $date_timestamp ) ) . '">' . esc_html( date_i18n( $atts['date_format'], $date_timestamp ) ) . '</time>
510 - <a href="' . esc_attr( $url ) . '" target="_blank" rel="nofollow noopener"' . $this->get_link_style_tag( $atts ) . '>' . esc_html( $broadcast['title'] ) . '</a>
511 - </li>';
720 + $html .= $this->build_html_list_item( $broadcast, $atts );
512 721 }
513 722
514 723 // End list.
515 724 $html .= '</ul>';
@@ -544,8 +753,18 @@
544 753 if ( $include_container ) {
545 754 $html .= '</div>';
546 755 }
547 756
757 + /**
758 + * Filter the block's content immediately before it is output.
759 + *
760 + * @since 2.2.3
761 + *
762 + * @param string $html ConvertKit Broadcasts HTML.
763 + * @param array $atts Block Attributes.
764 + */
765 + $html = apply_filters( 'convertkit_block_broadcasts_render', $html, $atts );
766 +
548 767 // Return.
549 768 return $html;
550 769
551 770 }
@@ -550,8 +769,88 @@
550 769
551 770 }
552 771
553 772 /**
773 + * Defines the HTML for an individual broadcast item in the Broadcasts block.
774 + *
775 + * @since 2.2.3
776 + *
777 + * @param array $broadcast Broadcast.
778 + * @param array $atts Block attributes.
779 + * @return string HTML
780 + */
781 + private function build_html_list_item( $broadcast, $atts ) {
782 +
783 + // Convert UTC date to timestamp.
784 + $date_timestamp = strtotime( $broadcast['published_at'] );
785 +
786 + // Build broadcast URL.
787 + $url = add_query_arg(
788 + array(
789 + 'utm_source' => 'wordpress',
790 + 'utm_term' => get_locale(),
791 + 'utm_content' => 'convertkit',
792 + ),
793 + $broadcast['url']
794 + );
795 +
796 + // Build HTML.
797 + $html = '<li class="convertkit-broadcast">';
798 +
799 + // Display date.
800 + $html .= '<time datetime="' . esc_attr( date_i18n( 'Y-m-d', $date_timestamp ) ) . '">' . esc_html( date_i18n( $atts['date_format'], $date_timestamp ) ) . '</time>';
801 +
802 + // Display linked title.
803 + $html .= '<a href="' . esc_url( $url ) . '" target="_blank" rel="nofollow noopener"' . $this->get_link_style_tag( $atts ) . ' class="convertkit-broadcast-title">' . esc_html( $broadcast['title'] ) . '</a>';
804 +
805 + // Display image.
806 + // We check for thumbnail_url, as these were added to the API in https://github.com/ConvertKit/convertkit/pull/23938,
807 + // and might not immediately be available until the resources are refreshed.
808 + if ( $atts['display_image'] && array_key_exists( 'thumbnail_url', $broadcast ) && ! is_null( $broadcast['thumbnail_url'] ) ) {
809 + $html .= '<a href="' . esc_url( $url ) . '" target="_blank" rel="nofollow noopener" class="convertkit-broadcast-image">
810 + <img src="' . esc_url( $broadcast['thumbnail_url'] ) . '" alt="' . esc_attr( $broadcast['thumbnail_alt'] ) . '" />
811 + </a>';
812 + }
813 +
814 + // Display description / read more.
815 + if ( $atts['display_description'] || $atts['display_read_more'] ) {
816 + $html .= '<span class="convertkit-broadcast-text">';
817 +
818 + // Display description.
819 + // We check for description, as these were added to the API in https://github.com/ConvertKit/convertkit/pull/23938,
820 + // and might not immediately be available until the resources are refreshed.
821 + if ( $atts['display_description'] && array_key_exists( 'description', $broadcast ) && ! is_null( $broadcast['description'] ) ) {
822 + $html .= '<span class="convertkit-broadcast-description">' . esc_html( $broadcast['description'] ) . '</span>';
823 + }
824 +
825 + // Display read more link.
826 + if ( $atts['display_read_more'] ) {
827 + $html .= '<a href="' . esc_url( $url ) . '" target="_blank" rel="nofollow noopener" class="convertkit-broadcast-read-more">' . esc_html( $atts['read_more_label'] ) . '</a>';
828 + }
829 +
830 + $html .= '</span>';
831 + }
832 +
833 + // Close list item.
834 + $html .= '</li>';
835 +
836 + /**
837 + * Defines the HTML for an individual broadcast item in the Broadcasts block.
838 + *
839 + * @since 2.2.3
840 + *
841 + * @param string $html HTML.
842 + * @param array $broadcast Broadcast.
843 + * @param array $atts Block attributes.
844 + * @return string HTML
845 + */
846 + $html = apply_filters( 'convertkit_block_broadcasts_build_html_list_item', $html, $broadcast, $atts );
847 +
848 + return $html;
849 +
850 + }
851 +
852 + /**
554 853 * Returns the HTML link to paginate to the previous page, to view
555 854 * newer broadcasts.
556 855 *
557 856 * @since 1.9.7.6
@@ -561,9 +860,9 @@
561 860 * @return string HTML Link
562 861 */
563 862 private function get_pagination_link_prev_html( $atts, $nonce ) {
564 863
565 - return '<a href="' . esc_attr( $this->get_pagination_link( $atts['page'] - 1, $nonce ) ) . '" title="' . esc_attr( $atts['paginate_label_prev'] ) . '" data-page="' . esc_attr( (string) ( $atts['page'] - 1 ) ) . '" data-nonce="' . esc_attr( $nonce ) . '"' . $this->get_link_style_tag( $atts ) . '>
864 + return '<a href="' . esc_url( $this->get_pagination_link( $atts['page'] - 1, $nonce ) ) . '" title="' . esc_attr( $atts['paginate_label_prev'] ) . '" data-page="' . esc_attr( (string) ( $atts['page'] - 1 ) ) . '" data-nonce="' . esc_attr( $nonce ) . '"' . $this->get_link_style_tag( $atts ) . '>
566 865 ' . esc_html( $atts['paginate_label_prev'] ) . '
567 866 </a>';
568 867
569 868 }
@@ -579,9 +878,9 @@
579 878 * @return string HTML Link
580 879 */
581 880 private function get_pagination_link_next_html( $atts, $nonce ) {
582 881
583 - return '<a href="' . esc_attr( $this->get_pagination_link( $atts['page'] + 1, $nonce ) ) . '" title="' . esc_attr( $atts['paginate_label_next'] ) . '" data-page="' . esc_attr( (string) ( $atts['page'] + 1 ) ) . '" data-nonce="' . esc_attr( $nonce ) . '"' . $this->get_link_style_tag( $atts ) . '>
882 + return '<a href="' . esc_url( $this->get_pagination_link( $atts['page'] + 1, $nonce ) ) . '" title="' . esc_attr( $atts['paginate_label_next'] ) . '" data-page="' . esc_attr( (string) ( $atts['page'] + 1 ) ) . '" data-nonce="' . esc_attr( $nonce ) . '"' . $this->get_link_style_tag( $atts ) . '>
584 883 ' . esc_html( $atts['paginate_label_next'] ) . '
585 884 </a>';
586 885
587 886 }