PluginProbe ʕ •ᴥ•ʔ
Presto Player / trunk
Presto Player vtrunk
4.4.1 4.4.0 4.3.3 4.3.2 4.3.1 4.3.0 4.2.4 4.2.3 4.2.2 4.2.0 4.2.1 trunk 1.10.0 1.10.1 1.10.2 1.11.0 1.12.0 1.13.0 1.14.0 1.14.1 1.5.10 1.5.11 1.5.12 1.5.13 1.5.14 1.5.15 1.5.5 1.5.6 1.5.7 1.5.8 1.5.9 1.6.0 1.6.1 1.6.10 1.6.11 1.6.12 1.6.13 1.6.2 1.6.3 1.6.4 1.6.5 1.6.6 1.6.7 1.6.8 1.6.9 1.7.0 1.7.1 1.7.2 1.8.0 1.8.1 1.8.2 1.8.3 1.8.4 1.8.5 1.8.6 1.9.0 1.9.1 1.9.10 1.9.11 1.9.12 1.9.13 1.9.14 1.9.2 1.9.3 1.9.4 1.9.5 1.9.6 1.9.7 1.9.8 1.9.9 2.0.0 2.0.1 2.0.10 2.0.11 2.0.12 2.0.13 2.0.14 2.0.15 2.0.16 2.0.2 2.0.3 2.0.4 2.0.5 2.0.6 2.0.7 2.0.8 2.0.9 2.1.0 2.2.0 2.2.1 2.2.2 2.2.3 2.2.3-beta1 2.3.0 2.3.1 2.3.2 2.3.3 3.0.0 3.0.0-beta1 3.0.1 3.0.2 3.0.3 3.0.4 3.0.5 3.0.6 3.0.7 3.0.8 3.1.0 3.1.1 3.1.2 3.1.3 4.0.0 4.0.1 4.0.2 4.0.3 4.0.4 4.0.5 4.0.6 4.0.7 4.0.8 4.1.0 4.1.1 4.1.2 4.1.3 4.1.4
presto-player / inc / Services / Shortcodes.php
presto-player / inc / Services Last commit date
API 1 week ago Abilities 1 week ago Blocks 3 weeks ago License 1 month ago OAuth 1 week ago AdminNotice.php 2 months ago AdminNotices.php 2 months ago AjaxActions.php 2 months ago Blocks.php 2 years ago Compatibility.php 11 months ago FeatureAnnounce.php 1 week ago Learn.php 1 week ago Menu.php 1 week ago Migrations.php 2 years ago NpsSurvey.php 6 months ago Onboarding.php 2 months ago Player.php 3 weeks ago PluginInstaller.php 1 week ago PreloadService.php 2 years ago ProCompatibility.php 3 weeks ago ReusableVideos.php 2 months ago RewriteRulesManager.php 2 years ago Scripts.php 2 months ago Settings.php 3 months ago Shortcodes.php 1 week ago Streamer.php 2 months ago Translation.php 3 weeks ago Usage.php 1 week ago VideoPostType.php 3 weeks ago
Shortcodes.php
636 lines
1 <?php
2 /**
3 * Shortcodes service file.
4 *
5 * @package PrestoPlayer\Services
6 */
7
8 namespace PrestoPlayer\Services;
9
10 use PrestoPlayer\Blocks\AudioBlock;
11 use PrestoPlayer\Pro\Blocks\PlaylistBlock;
12 use PrestoPlayer\Models\Video;
13 use PrestoPlayer\Blocks\VimeoBlock;
14 use PrestoPlayer\Blocks\YouTubeBlock;
15 use PrestoPlayer\Blocks\SelfHostedBlock;
16 use PrestoPlayer\Models\ReusableVideo;
17 use PrestoPlayer\Services\ReusableVideos;
18 use PrestoPlayer\Support\Block;
19 use PrestoPlayer\Pro\Blocks\BunnyCDNBlock;
20 use PrestoPlayer\Plugin;
21
22 /**
23 * Shortcodes service.
24 *
25 * @package PrestoPlayer\Services
26 */
27 class Shortcodes {
28
29 /**
30 * Register shortcodes.
31 *
32 * @return void
33 */
34 public function register() {
35 add_shortcode( 'presto_player_chapter', '__return_false' );
36 add_shortcode( 'presto_playlist_item', '__return_false' );
37 add_shortcode( 'presto_player_overlay', '__return_false' );
38 add_shortcode( 'presto_player_track', '__return_false' );
39 add_shortcode( 'presto_player', array( $this, 'playerShortcode' ), 10, 2 );
40 add_shortcode( 'presto_timestamp', array( $this, 'timestampShortcode' ), 10, 2 );
41 add_shortcode( 'pptime', array( $this, 'timestampShortcode' ), 10, 2 );
42 add_shortcode( 'presto_playlist', array( $this, 'playlistShortcode' ), 10, 2 );
43 add_shortcode( 'presto_popup', array( $this, 'popupShortcode' ), 10, 2 );
44 }
45
46 /**
47 * Do the shortcode
48 *
49 * @param array $atts Array of shortcode attributes.
50 * @param string $content String of content.
51 * @return void|string
52 */
53 public function playerShortcode( $atts, $content ) {
54 if ( ! is_admin() ) {
55 // global is the most reliable between page builders.
56 global $load_presto_js;
57 $load_presto_js = true;
58 ( new Scripts() )->blockAssets(); // Enqueue block assets.
59 }
60
61 $atts = shortcode_atts(
62 array(
63 'id' => '',
64 'src' => '',
65 'title' => '',
66 'provider' => '',
67 'class' => '',
68 'custom_field' => '',
69 'poster' => '',
70 'preload' => 'auto',
71 'preset' => 0,
72 'autoplay' => false,
73 'plays_inline' => false,
74 'chapters' => array(),
75 'overlays' => array(),
76 'muted_autoplay_preview' => false,
77 'muted_autoplay_caption_preview' => false,
78 'ratio' => 'original',
79 ),
80 $atts
81 );
82
83 // could not find source but ID is present.
84 if ( ! $atts['src'] && ! $atts['custom_field'] && $atts['id'] ) {
85 $fallback = $this->maybeUnauthorizedFallback( $atts['id'] );
86 if ( false !== $fallback ) {
87 return $fallback;
88 }
89 return ReusableVideos::getBlock( $atts['id'] );
90 }
91
92 $atts = $this->parseAttributes( $atts, $content );
93 return $this->renderBlock( $atts );
94 }
95
96 /**
97 * Do the shortcode
98 *
99 * @param array $atts Array of shortcode attributes.
100 * @param string $content String of content.
101 * @return void|string
102 */
103 public function playlistShortcode( $atts, $content ) {
104 if ( ! is_admin() ) {
105 // global is the most reliable between page builders.
106 global $load_presto_js;
107 $load_presto_js = true;
108 ( new Scripts() )->blockAssets(); // enqueue block assets.
109 }
110
111 $atts = $this->parsePlaylistAttributes( $atts, $content );
112
113 return ( new PlaylistBlock() )->html( $atts );
114 }
115
116 /**
117 * Timestamp shortcode.
118 *
119 * @param array $atts Shortcode attributes.
120 * @param string $content Content inside shortcode.
121 * @return string
122 */
123 public function timestampShortcode( $atts, $content ) {
124 $atts = shortcode_atts(
125 array(
126 'time' => '',
127 ),
128 $atts
129 );
130 return '<presto-timestamp time="' . esc_attr( $atts['time'] ) . '">' . $content . '</presto-timestamp>';
131 }
132
133 /**
134 * Popup shortcode.
135 *
136 * @param array $atts Shortcode attributes.
137 * @param string $content Content inside shortcode.
138 * @return string
139 */
140 public function popupShortcode( $atts, $content ) {
141 $atts = shortcode_atts(
142 array(
143 'media_id' => '',
144 'image_url' => '',
145 'button_text' => '',
146 ),
147 $atts
148 );
149
150 if ( empty( $atts['media_id'] ) ) {
151 return '';
152 }
153
154 // Get the popup block content.
155 $popup_block_content = $this->popupBlockContent( $atts, $content );
156
157 // Return the processed block markup.
158 return $this->getProcessedBlockHtml( $popup_block_content );
159 }
160
161 /**
162 * Generate complete popup block content including trigger.
163 *
164 * @param array $atts Shortcode attributes.
165 * @param string $content Content between shortcode tags.
166 * @return string
167 */
168 private function popupBlockContent( $atts, $content ) {
169 $trigger_content = '';
170
171 // Image trigger.
172 if ( ! empty( $atts['image_url'] ) ) {
173 // Use core/image for non-premium users, core/cover for premium users.
174 if ( ! Plugin::hasRequiredProVersion( 'popups' ) ) {
175 // For non-premium users, use the popup-image-trigger variation of core/image.
176 $trigger_content .= '<!-- wp:image {"url":"' . esc_url( $atts['image_url'] ) . '","className":"presto-popup-image-trigger","style":{"aspectRatio":"16/9","border":{"radius":"5px"}},"width":"100%","height":"auto","sizeSlug":"large"} -->
177 <figure class="wp-block-image size-large presto-popup-image-trigger" style="aspect-ratio:16/9;border-radius:5px;width:100%"><img src="' . esc_url( $atts['image_url'] ) . '" alt="" style="width:100%;height:auto"/></figure>
178 <!-- /wp:image -->';
179 } else {
180 // For premium users, use core/cover block with overlay and play button.
181 $play_button_url = PRESTO_PLAYER_PLUGIN_URL . 'img/play-button.svg';
182 $trigger_content .= '<!-- wp:cover {"url":"' . esc_url( $atts['image_url'] ) . '","className":"presto-popup-cover-trigger","customOverlayColor":"#131313","isUserOverlayColor":true,"dimRatio":50,"minHeight":336,"minHeightUnit":"px","contentPosition":"center center","layout":{"type":"constrained"},"style":{"aspectRatio":"16/9","border":{"radius":"5px"}}} -->
183 <div class="wp-block-cover presto-popup-cover-trigger" style="border-radius:5px;aspect-ratio:16/9;min-height:336px"><span aria-hidden="true" class="wp-block-cover__background has-background-dim has-background-dim-50" style="background-color:#131313"></span><div class="wp-block-cover__image-background" style="background-image:url(' . esc_url( $atts['image_url'] ) . ');background-position:50% 50%"></div><div class="wp-block-cover__inner-container"><!-- wp:group {"layout":{"type":"flex","flexWrap":"nowrap","justifyContent":"center"}} -->
184 <div class="wp-block-group"><!-- wp:image {"url":"' . $play_button_url . '","alt":"","width":"48px","height":"auto","sizeSlug":"large","align":"center","className":"is-style-default","style":{"color":{"duotone":"unset"}}} -->
185 <figure class="wp-block-image aligncenter size-large is-style-default" style="width:48px"><img src="' . esc_url( $play_button_url ) . '" alt="" style="width:48px;height:auto"/></figure>
186 <!-- /wp:image --></div>
187 <!-- /wp:group --></div></div>
188 <!-- /wp:cover -->';
189 }
190 }
191
192 // Button trigger.
193 if ( ! empty( $atts['button_text'] ) ) {
194 $trigger_content .= '<!-- wp:buttons -->
195 <div class="wp-block-buttons"><!-- wp:button -->
196 <div class="wp-block-button"><a class="wp-block-button__link wp-element-button">' . esc_html( $atts['button_text'] ) . '</a></div>
197 <!-- /wp:button --></div>
198 <!-- /wp:buttons -->';
199 }
200
201 // Custom content.
202 if ( ! empty( $content ) ) {
203 $trigger_content .= $content;
204 }
205
206 // Return complete popup block with trigger and media.
207 return '<!-- wp:presto-player/popup {"popupId":"' . (int) $atts['media_id'] . '"} -->
208 <div class="wp-block-presto-player-popup"><!-- wp:presto-player/popup-trigger -->
209 <div class="wp-block-presto-player-popup-trigger">' . $trigger_content . '</div>
210 <!-- /wp:presto-player/popup-trigger -->
211
212 <!-- wp:presto-player/popup-media -->
213 <div class="wp-block-presto-player-popup-media"><!-- wp:presto-player/reusable-display {"id":' . (int) $atts['media_id'] . '} -->
214 <div class="wp-block-presto-player-reusable-display"></div>
215 <!-- /wp:presto-player/reusable-display --></div>
216 <!-- /wp:presto-player/popup-media --></div>
217 <!-- /wp:presto-player/popup -->';
218 }
219
220 /**
221 * Parse playlist attributes.
222 *
223 * @param array $atts Shortcode attributes.
224 * @param string $content Content inside shortcode.
225 * @return array
226 */
227 public function parsePlaylistAttributes( $atts, $content = '' ) {
228
229 // backwards compat.
230 $atts['listTextPlural'] = $atts['listtextplural'] ?? null;
231 $atts['listTextSingular'] = $atts['listtextplural'] ?? null;
232 $atts['transitionDuration'] = $atts['transitionduration'] ?? null;
233
234 $atts = shortcode_atts(
235 array(
236 'heading' => __( 'Playlist', 'presto-player' ),
237 'listTextPlural' => __( 'Videos', 'presto-player' ),
238 'listTextSingular' => __( 'Video', 'presto-player' ),
239 'transitionDuration' => 5,
240 'styles' => '',
241 ),
242 $atts
243 );
244
245 $atts['items'] = $this->getPlaylistItems( $content );
246
247 return $atts;
248 }
249
250 /**
251 * Parse attributes.
252 *
253 * @param array $atts Shortcode attributes.
254 * @param string $content Content inside shortcode.
255 * @return array
256 */
257 public function parseAttributes( $atts, $content = '' ) {
258 $atts = shortcode_atts(
259 array(
260 'id' => '',
261 'src' => '',
262 'title' => '',
263 'provider' => '',
264 'class' => '',
265 'custom_field' => '',
266 'poster' => '',
267 'preload' => 'auto',
268 'preset' => 0,
269 'autoplay' => false,
270 'plays_inline' => false,
271 'chapters' => array(),
272 'overlays' => array(),
273 'muted_autoplay_preview' => false,
274 'muted_autoplay_caption_preview' => false,
275 'ratio' => 'original',
276 ),
277 $atts
278 );
279
280 if ( ! $atts['id'] && ! $atts['src'] && ! $atts['custom_field'] ) {
281 return array();
282 }
283
284 // custom field as a src.
285 if ( $atts['custom_field'] ) {
286 $atts['src'] = get_post_meta( get_the_ID(), $atts['custom_field'], true );
287
288 // Compatibility for file input field type from Advanced custom field plugin.
289 if ( function_exists( 'get_field' ) ) {
290 // phpcs:disable-next-line Generic.Functions.CallTimePassByReference.NotAllowed
291 $custom_field = \get_field( $atts['custom_field'] );
292 if ( $custom_field ) {
293 switch ( gettype( $custom_field ?? null ) ) {
294 case 'array':
295 $atts['src'] = $custom_field['url'] ?? '';
296 break;
297 case 'integer':
298 $atts['src'] = wp_get_attachment_url( $custom_field ) ?? '';
299 break;
300 case 'string':
301 $atts['src'] = $custom_field;
302 break;
303 }
304 }
305 }
306 }
307
308 // get provider based on src, if not provided.
309 $atts['provider'] = ! $atts['provider'] ? $this->getProvider( $atts['src'] ) : $atts['provider'];
310
311 $atts['id'] = $this->getOrCreateVideoId( $atts );
312 $atts['chapters'] = $this->getChapters( $content );
313 $atts['overlays'] = $this->getOverlays( $content );
314 $atts['tracks'] = $this->getTracks( $content );
315 $atts['playsInline'] = (bool) $atts['plays_inline'];
316 $atts['mutedPreview'] = array(
317 'enabled' => (bool) $atts['muted_autoplay_preview'],
318 'captions' => (bool) $atts['muted_autoplay_caption_preview'],
319 );
320 $atts['className'] = sanitize_html_class( $atts['class'] );
321
322 unset( $atts['plays_inline'] );
323 unset( $atts['muted_autoplay_preview'] );
324 unset( $atts['muted_autoplay_caption_preview'] );
325 unset( $atts['class'] );
326
327 return $atts;
328 }
329
330 /**
331 * Renders the block with attributes.
332 *
333 * @param array $atts Block attributes.
334 * @return void|string
335 */
336 public function renderBlock( $atts ) {
337 switch ( $atts['provider'] ?? '' ) {
338 case 'self-hosted':
339 return ( new SelfHostedBlock() )->html( $atts, '' );
340
341 case 'youtube':
342 return ( new YouTubeBlock() )->html( $atts, '' );
343
344 case 'vimeo':
345 return ( new VimeoBlock() )->html( $atts, '' );
346
347 case 'bunny':
348 return ( new BunnyCDNBlock() )->html( $atts, '' );
349
350 case 'audio':
351 return ( new AudioBlock() )->html( $atts, '' );
352 }
353 }
354
355 /**
356 * Get or create video id for analytics.
357 *
358 * @param array $atts Block attributes.
359 * @return int
360 */
361 public function getOrCreateVideoId( $atts ) {
362 $create = array(
363 'src' => $atts['src'],
364 'type' => $atts['provider'],
365 );
366 if ( ! empty( $atts['title'] ) ) {
367 $create['title'] = $atts['title'];
368 }
369
370 $video = new Video();
371 $model = $video->getOrCreate(
372 array( 'src' => $atts['src'] ),
373 $create
374 );
375
376 if ( is_wp_error( $model ) ) {
377 return 0;
378 }
379
380 $model = $model->toObject();
381 return ! empty( $model->id ) ? $model->id : 0;
382 }
383
384 /**
385 * Get chapters from shortcodes.
386 *
387 * @param string $content Content inside shortcode.
388 * @return array
389 */
390 public function getChapters( $content ) {
391 $chapters = $this->getShortcodesAtts(
392 'presto_player_chapter',
393 $content,
394 array(
395 'time' => '00:00',
396 'title' => '',
397 )
398 );
399 foreach ( (array) $chapters as $key => $chapter ) {
400 if ( ! strpos( $chapter['time'], ':' ) ) {
401 $chapters[ $key ]['time'] = '00:' . $chapter['time'];
402 }
403 }
404
405 return $chapters;
406 }
407
408 /**
409 * Get playlist items from shortcodes.
410 *
411 * @param string $content Content inside shortcode.
412 * @return array
413 */
414 public function getPlaylistItems( $content ) {
415 $items = $this->getShortcodesAtts(
416 'presto_playlist_item',
417 $content,
418 array(
419 'duration' => '00:00',
420 'title' => '',
421 'id' => 0,
422 )
423 );
424 foreach ( $items as $key => $item ) {
425 $video_details = ( new ReusableVideo( $item['id'] ) )->getAttributes();
426 $items[ $key ] = array(
427 'id' => $items[ $key ]['id'],
428 'config' => $video_details,
429 'duration' => $items[ $key ]['duration'],
430 'title' => $items[ $key ]['title'],
431 );
432 }
433 return $items;
434 }
435
436 /**
437 * Get overlays from shortcodes.
438 *
439 * @param string $content Content inside shortcode.
440 * @return array
441 */
442 public function getOverlays( $content ) {
443
444 $overlays = $this->getShortcodesAtts(
445 'presto_player_overlay',
446 $content,
447 array(
448 'start_time' => '00:00',
449 'end_time' => '',
450 'text' => '',
451 'link' => array(),
452 'position' => '',
453 )
454 );
455 foreach ( (array) $overlays as $key => $overlay ) {
456 if ( ! strpos( $overlay['start_time'], ':' ) ) {
457 $overlays[ $key ]['startTime'] = '00:' . $overlay['start_time'];
458 } else {
459 $overlays[ $key ]['startTime'] = $overlay['start_time'];
460 }
461
462 if ( ! strpos( $overlay['end_time'], ':' ) ) {
463 $overlays[ $key ]['endTime'] = '00:' . $overlay['end_time'];
464 } else {
465 $overlays[ $key ]['endTime'] = $overlay['end_time'];
466 }
467
468 $overlays[ $key ]['link']['url'] = esc_url_raw( $overlay['link_url'] );
469 $overlays[ $key ]['link']['opensInNewTab'] = (bool) $overlay['link_new_tab'];
470
471 unset( $overlays[ $key ]['link_url'] );
472 unset( $overlays[ $key ]['link_new_tab'] );
473 unset( $overlays[ $key ]['start_time'] );
474 unset( $overlays[ $key ]['end_time'] );
475 }
476 return $overlays;
477 }
478
479 /**
480 * Get tracks from shortcodes.
481 *
482 * @param string $content Content inside shortcode.
483 * @return array
484 */
485 public function getTracks( $content ) {
486 return $this->getShortcodesAtts(
487 'presto_player_track',
488 $content,
489 array(
490 'label' => '',
491 'src' => '',
492 'srclang' => '',
493 )
494 );
495 }
496
497 /**
498 * Get specific shortcode atts from content.
499 *
500 * @param string $name Name of shortcode.
501 * @param string $content Page content.
502 * @param array $defaults Defaults for each shortcode.
503 * @return array
504 */
505 public function getShortcodesAtts( $name, $content, $defaults = array() ) {
506 $items = array();
507
508 // if shortcode exists.
509 if (
510 preg_match_all( '/' . get_shortcode_regex() . '/s', $content, $matches )
511 && array_key_exists( 2, $matches )
512 && in_array( $name, $matches[2], true )
513 ) {
514 foreach ( (array) $matches[0] as $key => $value ) {
515 if ( strpos( $value, $name ) !== false ) {
516 $items[] = wp_parse_args(
517 shortcode_parse_atts( $matches[3][ $key ] ),
518 $defaults
519 );
520 }
521 }
522 }
523
524 return $items;
525 }
526
527 /**
528 * Pre-render gate for the player shortcode.
529 *
530 * The shortcode `[presto_player id=X]` renders the underlying Media Hub
531 * post directly via ReusableVideos::getBlock(). That bypasses the
532 * normal singular-post visibility check WordPress applies when you
533 * visit the Media Hub permalink — so a Media Hub item set to Private
534 * was leaking through the shortcode.
535 *
536 * This method short-circuits the shortcode with the standard
537 * "Please login for access" curtain whenever the referenced
538 * pp_video_block post is non-public AND the current user cannot read
539 * it. We defer to current_user_can( 'read_post', $id ) so WP's
540 * map_meta_cap chain stays in charge — site owners and capability
541 * plugins (membership, LMS) keep full control without us inventing
542 * a parallel filter.
543 *
544 * @param int|string $id Media Hub post ID supplied to the shortcode.
545 * @return string|false Curtain HTML to short-circuit, or false to continue.
546 */
547 public function maybeUnauthorizedFallback( $id ) {
548 $reusable = new ReusableVideo( (int) $id );
549 $visibility = $reusable->getMediaHubPostVisibility();
550
551 // Not a Media Hub post — let the normal flow handle it.
552 if ( null === $visibility ) {
553 return false;
554 }
555
556 // Public statuses (publish) are viewable by anyone — fast path.
557 $status_obj = get_post_status_object( $visibility );
558 if ( $status_obj && $status_obj->public ) {
559 return false;
560 }
561
562 // Non-public status — defer to WP's standard post-visibility check
563 // so admins/editors and capability plugins still pass through.
564 if ( current_user_can( 'read_post', $reusable->post->ID ) ) {
565 return false;
566 }
567
568 return ( new Block() )->getFallbackHTMLForUnauthorizeAccess();
569 }
570
571 /**
572 * Maybe switch provider if the url is overridden.
573 *
574 * @param string $src Source URL.
575 * @return string
576 */
577 protected function getProvider( $src ) {
578 $provider = 'self-hosted';
579
580 if ( ! empty( $src ) ) {
581 $filetype = wp_check_filetype( $src );
582 if ( isset( $filetype['type'] ) && false !== strpos( $filetype['type'], 'audio' ) ) {
583 return 'audio';
584 }
585
586 $yt_rx = '/^((?:https?:)?\/\/)?((?:www|m)\.)?((?:youtube\.com|youtu.be))(\/(?:[\w\-]+\?v=|embed\/|v\/)?)([\w\-]+)(\S+)?$/';
587 $has_match_youtube = preg_match( $yt_rx, $src, $yt_matches );
588
589 if ( $has_match_youtube ) {
590 return 'youtube';
591 }
592
593 $vm_rx = '/(https?:\/\/)?(www\.)?(player\.)?vimeo\.com\/([a-z]*\/)*([‌​0-9]{6,11})[?]?.*/';
594 $has_match_vimeo = preg_match( $vm_rx, $src, $vm_matches );
595
596 if ( $has_match_vimeo ) {
597 return 'vimeo';
598 }
599
600 if ( strpos( $src, 'https://vz-' ) !== false && strpos( $src, 'b-cdn.net' ) !== false ) {
601 return 'bunny';
602 }
603 }
604
605 return $provider;
606 }
607
608 /**
609 * Returns the markup for the current block.
610 *
611 * @param string $content Block content.
612 * @global WP_Embed $wp_embed
613 *
614 * @return string Block markup.
615 */
616 public function getProcessedBlockHtml( $content ) {
617 global $wp_embed;
618
619 if ( ! $content ) {
620 return;
621 }
622
623 $content = $wp_embed->run_shortcode( $content );
624 $content = $wp_embed->autoembed( $content );
625 $content = do_blocks( $content );
626 $content = wptexturize( $content );
627 $content = convert_smilies( $content );
628 $content = shortcode_unautop( $content );
629 $content = wp_filter_content_tags( $content, 'template' );
630 $content = do_shortcode( $content );
631 $content = str_replace( ']]>', ']]&gt;', $content );
632
633 return $content;
634 }
635 }
636