class-fl-builder-wp-blocks-layout.php 4.9 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167
  1. <?php
  2. /**
  3. * Beaver Builder layout block for the new editor.
  4. *
  5. * @since 2.1
  6. */
  7. final class FLBuilderWPBlocksLayout {
  8. /**
  9. * @since 2.1
  10. * @return void
  11. */
  12. static public function init() {
  13. // Actions
  14. add_action( 'current_screen', __CLASS__ . '::init_template' );
  15. add_action( 'admin_enqueue_scripts', __CLASS__ . '::update_legacy_post', 1 );
  16. add_action( 'pre_post_update', __CLASS__ . '::disable_builder_on_post_update', 10, 2 );
  17. // Filters
  18. add_filter( 'fl_builder_editor_content', __CLASS__ . '::filter_editor_content' );
  19. add_filter( 'fl_builder_migrated_post_content', __CLASS__ . '::filter_migrated_post_content' );
  20. }
  21. /**
  22. * Initialize a template for empty posts that have
  23. * the builder enabled for them.
  24. *
  25. * @since 2.1
  26. * @return void
  27. */
  28. static public function init_template() {
  29. global $pagenow;
  30. if ( in_array( $pagenow, array( 'post.php', 'post-new.php' ) ) ) {
  31. $post_id = isset( $_GET['post'] ) ? absint( $_GET['post'] ) : null;
  32. $render_ui = apply_filters( 'fl_builder_render_admin_edit_ui', true );
  33. $post_types = FLBuilderModel::get_post_types();
  34. $screen = get_current_screen();
  35. $enabled = ! $post_id ? false : FLBuilderModel::is_builder_enabled( $post_id );
  36. $user_access = FLBuilderUserAccess::current_user_can( 'builder_access' );
  37. $unrestricted = FLBuilderUserAccess::current_user_can( 'unrestricted_editing' );
  38. if ( $render_ui && in_array( $screen->post_type, $post_types ) ) {
  39. $post_type = get_post_type_object( $screen->post_type );
  40. if ( $post_type && ( $enabled || ( $user_access && $unrestricted ) ) ) {
  41. $post_type->template = array(
  42. array( 'fl-builder/layout' ),
  43. );
  44. if ( ! $user_access || ! $unrestricted ) {
  45. $post_type->template_lock = 'all';
  46. }
  47. }
  48. }
  49. }
  50. }
  51. /**
  52. * Updates posts being edited in the admin that we're built
  53. * using Beaver Builder before WordPress blocks existed.
  54. *
  55. * @since 2.1
  56. * @return void
  57. */
  58. static public function update_legacy_post() {
  59. global $pagenow, $post;
  60. if ( 'post.php' !== $pagenow || ! is_object( $post ) ) {
  61. return;
  62. } else {
  63. $enabled = FLBuilderModel::is_builder_enabled( $post->ID );
  64. $blocks = preg_match( '/<!-- wp:(.*) \/?-->/', $post->post_content );
  65. if ( $enabled && ! $blocks ) {
  66. $block = '<!-- wp:fl-builder/layout -->';
  67. $block .= self::remove_broken_p_tags( $post->post_content );
  68. $block .= '<!-- /wp:fl-builder/layout -->';
  69. $post->post_content = $block;
  70. wp_update_post( array(
  71. 'ID' => $post->ID,
  72. 'post_content' => $block,
  73. ) );
  74. }
  75. }
  76. }
  77. /**
  78. * Disable the builder if old post content has a l
  79. * ayout block but the new post content doesn't.
  80. *
  81. * @since 2.1
  82. * @return void
  83. */
  84. static public function disable_builder_on_post_update( $post_id, $new_post ) {
  85. $new_post = (object) $new_post;
  86. $old_post = get_post( $post_id );
  87. $post_types = FLBuilderModel::get_post_types();
  88. if ( ! $old_post || ! in_array( $old_post->post_type, $post_types ) ) {
  89. return;
  90. }
  91. $old_layout = preg_match( '/<!-- wp:fl-builder\/layout \/?-->/', $old_post->post_content );
  92. $new_layout = preg_match( '/<!-- wp:fl-builder\/layout \/?-->/', $new_post->post_content );
  93. if ( $old_layout && ! $new_layout ) {
  94. update_post_meta( $post_id, '_fl_builder_enabled', false );
  95. }
  96. }
  97. /**
  98. * Filters the content saved back to the post editor when a builder
  99. * layout is published and wraps it in our layout block. If our block
  100. * exists in the post content then it will be replaced with this block.
  101. * Otherwise, the entire post content will be replaced.
  102. *
  103. * @since 2.1
  104. * @param string $content
  105. * @return string
  106. */
  107. static public function filter_editor_content( $content ) {
  108. $post_id = FLBuilderModel::get_post_id();
  109. $post = get_post( $post_id );
  110. $block = '<!-- wp:fl-builder/layout -->';
  111. $block .= self::remove_broken_p_tags( $content );
  112. $block .= '<!-- /wp:fl-builder/layout -->';
  113. return $block;
  114. }
  115. /**
  116. * Removes the builder layout block from migrated post content.
  117. *
  118. * @since 2.1
  119. * @param string $content
  120. * @return string
  121. */
  122. static public function filter_migrated_post_content( $content ) {
  123. $content = preg_replace( '/<!-- \/?wp:fl-builder\/layout \/?-->/', '', $content );
  124. return $content;
  125. }
  126. /**
  127. * Removes unclosed or unopened paragraph tags caused by a bug
  128. * in wpautop. If we don't remove those here, Gutenberg will
  129. * think our layout block has an error.
  130. *
  131. * See: https://core.trac.wordpress.org/ticket/43100
  132. *
  133. * @since 2.1
  134. * @param string $content
  135. * @return string
  136. */
  137. static public function remove_broken_p_tags( $content ) {
  138. $content = preg_replace( '/<p>(.*)<\/p>/i', '<fl-p-placeholder>$1</fl-p-placeholder>', $content );
  139. $content = preg_replace( '/<\/?p[^>]*\>/i', '', $content );
  140. $content = preg_replace( '/fl-p-placeholder/i', 'p', $content );
  141. return $content;
  142. }
  143. }
  144. FLBuilderWPBlocksLayout::init();