PluginProbe
BetterDocs – AI Documentation, Knowledge Base, MCP Server, Docs, Wikis, FAQ & Chatbot / 4.9.2
BetterDocs – AI Documentation, Knowledge Base, MCP Server, Docs, Wikis, FAQ & Chatbot v4.9.2
4.9.2 4.9.1 4.9.0 4.8.2 4.8.1 4.8.0 4.7.0 4.6.2 4.6.1 4.6.0 4.5.6 4.5.5 4.5.4 4.5.3 4.5.2 4.5.1 4.5.0 4.4.1 4.4.0 3.3.4 3.4.0 3.4.1 3.4.2 3.5.0 3.5.1 All 200 releases
← All changes | includes/Modules/StyleHandler.php +370 -334 4.4.14.9.2 View file →
@@ -1,389 +1,425 @@
1 1 <?php
2 +namespace WPDeveloper\BetterDocs\Modules;
2 3
3 -namespace WPDeveloper\BetterDocs\Modules;
4 +if ( ! defined( 'ABSPATH' ) ) {
5 + exit;
6 +}
4 7
8 +
9 +
10 +// Doc/category-listing primitives (meta_query/tax_query, post__not_in/exclude)
11 +// are intrinsic to BetterDocs' KB / category / FAQ filters and intentional.
12 +// phpcs:disable WordPress.DB.SlowDBQuery.slow_db_query_meta_key
13 +// phpcs:disable WordPress.DB.SlowDBQuery.slow_db_query_meta_query
14 +// phpcs:disable WordPress.DB.SlowDBQuery.slow_db_query_tax_query
15 +// phpcs:disable WordPressVIPMinimum.Performance.WPQueryParams.PostNotIn_exclude
16 +// phpcs:disable WordPressVIPMinimum.Performance.WPQueryParams.PostNotIn_post__not_in
5 17 use WPDeveloper\BetterDocs\Utils\CSSParser;
6 18
7 19 final class StyleHandler {
8 - private static $instance;
20 + private static $instance;
9 21
10 - private $prefix = 'betterdocs-style';
11 - private $style_dir;
12 - private $style_url;
13 - /**
14 - * Holds block styles array
15 - *
16 - * @var array
17 - */
18 - public static $_block_styles = [];
22 + private $prefix = 'betterdocs-style';
23 + private $style_dir;
24 + private $style_url;
25 + /**
26 + * Holds block styles array
27 + *
28 + * @var array
29 + */
30 + public static $_block_styles = array( );
19 31
20 - public static function init() {
21 - if ( null === self::$instance ) {
22 - self::$instance = new self();
23 - }
32 + /**
33 + * Post IDs of FSE templates / template parts whose CSS was generated
34 + * during the current request. Used to enqueue the matching per-template
35 + * CSS files on the frontend.
36 + *
37 + * @var int[]
38 + */
39 + public static $_fse_template_post_ids = array( );
24 40
25 - return self::$instance;
26 - }
41 + public static function init() {
42 + if ( null === self::$instance ) {
43 + self::$instance = new self();
44 + }
27 45
28 - public function __construct() {
29 - $upload_dir = wp_upload_dir();
46 + return self::$instance;
47 + }
30 48
31 - $this->style_dir = $upload_dir['basedir'] . '/' . $this->prefix . DIRECTORY_SEPARATOR;
32 - $this->style_url = set_url_scheme( $upload_dir['baseurl'] ) . '/' . $this->prefix . '/';
49 + public function __construct() {
50 + $upload_dir = wp_upload_dir();
33 51
34 - add_action( 'wp_enqueue_scripts', [ $this, 'enqueue_frontend_assets' ], 99 );
35 - add_action( 'save_post', [ $this, 'on_save_post' ], 10, 3 );
36 - add_action( 'wp', [ $this, 'generate_post_content' ] );
37 - add_action( 'rest_after_save_widget', [ $this, 'after_save_widget' ], 10, 4 );
52 + $this->style_dir = $upload_dir[ 'basedir' ] . '/' . $this->prefix . DIRECTORY_SEPARATOR;
53 + $this->style_url = set_url_scheme( $upload_dir[ 'baseurl' ] ) . '/' . $this->prefix . '/';
38 54
39 - // FSE assets generation
40 - add_action(
41 - 'init',
42 - function () {
43 - if ( function_exists( 'wp_is_block_theme' ) && wp_is_block_theme() ) {
44 - add_filter( '404_template', [ $this, 'fse_assets_generation' ], 99, 3 );
45 - add_filter( 'archive_template', [ $this, 'fse_assets_generation' ], 99, 3 );
46 - add_filter( 'category_template', [ $this, 'fse_assets_generation' ], 99, 3 );
47 - add_filter( 'frontpage_template', [ $this, 'fse_assets_generation' ], 99, 3 );
48 - add_filter( 'home_template', [ $this, 'fse_assets_generation' ], 99, 3 );
49 - add_filter( 'index_template', [ $this, 'fse_assets_generation' ], 99, 3 );
50 - add_filter( 'page_template', [ $this, 'fse_assets_generation' ], 99, 3 );
51 - add_filter( 'search_template', [ $this, 'fse_assets_generation' ], 99, 3 );
52 - add_filter( 'single_template', [ $this, 'fse_assets_generation' ], 99, 3 );
53 - add_filter( 'singular_template', [ $this, 'fse_assets_generation' ], 99, 3 );
54 - add_filter( 'tag_template', [ $this, 'fse_assets_generation' ], 99, 3 );
55 - add_filter( 'taxonomy_template', [ $this, 'fse_assets_generation' ], 99, 3 );
56 - }
57 - },
58 - 999
59 - );
60 - }
55 + add_action( 'wp_enqueue_scripts', array( $this, 'enqueue_frontend_assets' ), 99 );
56 + add_action( 'save_post', array( $this, 'on_save_post' ), 10, 3 );
57 + add_action( 'wp', array( $this, 'generate_post_content' ) );
58 + add_action( 'rest_after_save_widget', array( $this, 'after_save_widget' ), 10, 4 );
61 59
62 - /**
63 - * Generate FSE Assets
64 - */
65 - public function fse_assets_generation( $template, $type, $templates ) {
66 - $block_template = resolve_block_template( $type, $templates, $template );
67 - if ( ! empty( $block_template ) ) {
68 - $parsed_content = parse_blocks( $block_template->content );
69 - if ( is_array( $parsed_content ) && ! empty( $parsed_content ) ) {
70 - foreach ( $parsed_content as $content ) {
71 - if ( ( 'core/template-part' == $content['blockName'] ) || ( 'core/template' == $content['blockName'] ) ) {
72 - $post_ids = isset( $content['attrs']['slug'] ) ? self::betterdocs_get_post_content_by_post_name( $content['attrs']['slug'] ) : [];
60 + // FSE assets generation
61 + add_action(
62 + 'init',
63 + function () {
64 + if ( function_exists( 'wp_is_block_theme' ) && wp_is_block_theme() ) {
65 + add_filter( '404_template', array( $this, 'fse_assets_generation' ), 99, 3 );
66 + add_filter( 'archive_template', array( $this, 'fse_assets_generation' ), 99, 3 );
67 + add_filter( 'category_template', array( $this, 'fse_assets_generation' ), 99, 3 );
68 + add_filter( 'frontpage_template', array( $this, 'fse_assets_generation' ), 99, 3 );
69 + add_filter( 'home_template', array( $this, 'fse_assets_generation' ), 99, 3 );
70 + add_filter( 'index_template', array( $this, 'fse_assets_generation' ), 99, 3 );
71 + add_filter( 'page_template', array( $this, 'fse_assets_generation' ), 99, 3 );
72 + add_filter( 'search_template', array( $this, 'fse_assets_generation' ), 99, 3 );
73 + add_filter( 'single_template', array( $this, 'fse_assets_generation' ), 99, 3 );
74 + add_filter( 'singular_template', array( $this, 'fse_assets_generation' ), 99, 3 );
75 + add_filter( 'tag_template', array( $this, 'fse_assets_generation' ), 99, 3 );
76 + add_filter( 'taxonomy_template', array( $this, 'fse_assets_generation' ), 99, 3 );
77 + }
78 + },
79 + 999
80 + );
81 + }
73 82
74 - if ( ! empty( $post_ids ) ) {
75 - foreach ( $post_ids as $id ) {
76 - $post_id = (int) $id['ID'];
77 - $post = get_post( $post_id );
78 - if ( ! $post ) {
79 - continue;
80 - }
81 - $parsed_content = parse_blocks( $post->post_content );
82 - $this->write_css_from_content( $post, $post_id, $parsed_content );
83 - }
84 - }
85 - } else {
86 - $post_ids = self::betterdocs_get_post_content_by_post_name( $block_template->slug );
87 - if ( ! empty( $post_ids ) ) {
88 - foreach ( $post_ids as $id ) {
89 - $post_id = (int) $id['ID'];
90 - $post = get_post( $post_id );
91 - if ( ! $post ) {
92 - continue;
93 - }
94 - $parsed_content = parse_blocks( $post->post_content );
95 - $this->write_css_from_content( $post, $post_id, $parsed_content );
96 - }
97 - }
98 - }
99 - }
100 - }
101 - }
83 + /**
84 + * Generate FSE Assets
85 + */
86 + public function fse_assets_generation( $template, $type, $templates ) {
87 + $block_template = resolve_block_template( $type, $templates, $template );
88 + if ( ! empty( $block_template ) ) {
89 + $parsed_content = parse_blocks( $block_template->content );
90 + if ( is_array( $parsed_content ) && ! empty( $parsed_content ) ) {
91 + foreach ( $parsed_content as $content ) {
92 + if ( ( 'core/template-part' == $content[ 'blockName' ] ) || ( 'core/template' == $content[ 'blockName' ] ) ) {
93 + $post_ids = isset( $content[ 'attrs' ][ 'slug' ] ) ? self::betterdocs_get_post_content_by_post_name( $content[ 'attrs' ][ 'slug' ] ) : array( );
102 94
103 - return $template;
104 - }
95 + if ( ! empty( $post_ids ) ) {
96 + foreach ( $post_ids as $id ) {
97 + $post_id = (int) $id[ 'ID' ];
98 + self::$_fse_template_post_ids[ ] = $post_id;
99 + $post = get_post( $post_id );
100 + $parsed_content = parse_blocks( $post->post_content );
101 + $this->write_css_from_content( $post, $post_id, $parsed_content );
102 + }
103 + }
104 + } else {
105 + $post_ids = self::betterdocs_get_post_content_by_post_name( $block_template->slug );
106 + if ( ! empty( $post_ids ) ) {
107 + foreach ( $post_ids as $id ) {
108 + $post_id = (int) $id[ 'ID' ];
109 + self::$_fse_template_post_ids[ ] = $post_id;
110 + $post = get_post( $post_id );
111 + $parsed_content = parse_blocks( $post->post_content );
112 + $this->write_css_from_content( $post, $post_id, $parsed_content );
113 + }
114 + }
115 + }
116 + }
117 + }
118 + }
105 119
106 - /**
107 - * Write CSS
108 - */
109 - public function write_css_from_content( $post, $post_id, $parsed_content ) {
110 - $betterdocs_blocks = [];
111 - $recursive_response = CSSParser::betterdocs_block_style_recursive( $parsed_content, $betterdocs_blocks );
112 - $reusable_Blocks = ! empty( $recursive_response['reusableBlocks'] ) ? $recursive_response['reusableBlocks'] : [];
113 - // remove empty reusable blocks
114 - $reusable_Blocks = array_filter(
115 - $reusable_Blocks,
116 - function ( $v ) {
117 - return ! empty( $v );
118 - }
119 - );
120 - unset( $recursive_response['reusableBlocks'] );
121 - $style = CSSParser::blocks_to_style_array( $recursive_response );
122 - $reusableIds = $reusable_Blocks ? array_keys( $reusable_Blocks ) : [];
123 - if ( ! empty( $reusableIds ) ) {
124 - update_option( '_betterdocs_reusable_block_ids', $reusableIds );
125 - }
126 - update_post_meta( $post_id, '_betterdocs_reusable_block_ids', $reusableIds );
127 - $this->write_block_css( $style, $post ); //Write CSS file for this page
120 + return $template;
121 + }
128 122
129 - if ( ! empty( $reusable_Blocks ) ) {
130 - foreach ( $reusable_Blocks as $blockId => $block ) {
131 - $style = CSSParser::blocks_to_style_array( $block );
132 - $this->write_reusable_block_css( $style, $blockId );
133 - }
134 - }
135 - }
123 + /**
124 + * Write CSS
125 + */
126 + public function write_css_from_content( $post, $post_id, $parsed_content ) {
127 + $betterdocs_blocks = array( );
128 + $recursive_response = CSSParser::betterdocs_block_style_recursive( $parsed_content, $betterdocs_blocks );
129 + $reusable_Blocks = ! empty( $recursive_response[ 'reusableBlocks' ] ) ? $recursive_response[ 'reusableBlocks' ] : array( );
130 + // remove empty reusable blocks
131 + $reusable_Blocks = array_filter(
132 + $reusable_Blocks,
133 + function ( $v ) {
134 + return ! empty( $v );
135 + }
136 + );
137 + unset( $recursive_response[ 'reusableBlocks' ] );
138 + $style = CSSParser::blocks_to_style_array( $recursive_response );
139 + $reusableIds = $reusable_Blocks ? array_keys( $reusable_Blocks ) : array( );
140 + if ( ! empty( $reusableIds ) ) {
141 + update_option( '_betterdocs_reusable_block_ids', $reusableIds );
142 + }
143 + update_post_meta( $post_id, '_betterdocs_reusable_block_ids', $reusableIds );
144 + $this->write_block_css( $style, $post ); //Write CSS file for this page
136 145
137 - /**
138 - * Save Widget CSS when Widget is saved
139 - * @return void
140 - * @since 3.5.3
141 - */
142 - public function after_save_widget( $id, $sidebar_id, $request, $creating ) {
143 - $parsed_content = isset( $request['instance']['raw']['content'] ) ? parse_blocks( $request['instance']['raw']['content'] ) : [];
144 - if ( is_array( $parsed_content ) && ! empty( $parsed_content ) ) {
145 - $betterdocs_blocks = [];
146 - $recursive_response = CSSParser::betterdocs_block_style_recursive( $parsed_content, $betterdocs_blocks );
147 - unset( $recursive_response['reusableBlocks'] );
148 - $style = CSSParser::blocks_to_style_array( $recursive_response );
149 - //Write CSS file for Widget
150 - $this->single_file_css_generator( $style, $this->style_dir, $this->prefix . '-widget.min.css' );
151 - }
152 - }
146 + if ( ! empty( $reusable_Blocks ) ) {
147 + foreach ( $reusable_Blocks as $blockId => $block ) {
148 + $style = CSSParser::blocks_to_style_array( $block );
149 + $this->write_reusable_block_css( $style, $blockId );
150 + }
151 + }
152 + }
153 153
154 - /**
155 - * Load Dependencies
156 - */
157 - private function load_style_handler_dependencies() {
158 - require_once plugin_dir_path( __FILE__ ) . 'includes/class-parse-css.php';
159 - }
154 + /**
155 + * Save Widget CSS when Widget is saved
156 + * @return void
157 + * @since 3.5.3
158 + */
159 + public function after_save_widget( $id, $sidebar_id, $request, $creating ) {
160 + $parsed_content = isset( $request[ 'instance' ][ 'raw' ][ 'content' ] ) ? parse_blocks( $request[ 'instance' ][ 'raw' ][ 'content' ] ) : array( );
161 + if ( is_array( $parsed_content ) && ! empty( $parsed_content ) ) {
162 + $betterdocs_blocks = array( );
163 + $recursive_response = CSSParser::betterdocs_block_style_recursive( $parsed_content, $betterdocs_blocks );
164 + unset( $recursive_response[ 'reusableBlocks' ] );
165 + $style = CSSParser::blocks_to_style_array( $recursive_response );
166 + //Write CSS file for Widget
167 + $this->single_file_css_generator( $style, $this->style_dir, $this->prefix . '-widget.min.css' );
168 + }
169 + }
160 170
161 - /**
162 - * Enqueue frontend css for post if have one
163 - * @return void
164 - * @since 1.0.2
165 - */
166 - public function enqueue_frontend_assets() {
167 - global $post;
168 - $deps = apply_filters( 'betterdocs_generated_css_frontend_deps', [] );
171 + /**
172 + * Load Dependencies
173 + */
174 + private function load_style_handler_dependencies() {
175 + require_once plugin_dir_path( __FILE__ ) . 'includes/class-parse-css.php';
176 + }
169 177
170 - // generatepress elements
171 - if ( in_array( 'gp-premium/gp-premium.php', apply_filters( 'active_plugins', get_option( 'active_plugins' ) ) ) ) {
172 - $gp_elements = get_posts( [ 'post_type' => 'gp_elements' ] );
173 - if ( is_array( $gp_elements ) && ! empty( $gp_elements ) ) {
174 - foreach ( $gp_elements as $element ) {
175 - if ( file_exists( $this->style_dir . $this->prefix . '-' . $element->ID . '.min.css' ) ) {
176 - wp_enqueue_style( 'betterdocs-block-style-' . $element->ID, $this->style_url . $this->prefix . '-' . $element->ID . '.min.css', $deps, substr( md5( microtime( true ) ), 0, 10 ) );
177 - }
178 - }
179 - }
180 - }
178 + /**
179 + * Enqueue frontend css for post if have one
180 + * @return void
181 + * @since 1.0.2
182 + */
183 + public function enqueue_frontend_assets() {
184 + global $post;
185 + $deps = apply_filters( 'betterdocs_generated_css_frontend_deps', array( ) );
181 186
182 - if ( ! empty( $post ) && ! empty( $post->ID ) ) {
183 - //Page/Post Style Enqueue
184 - if ( file_exists( $this->style_dir . $this->prefix . '-' . $post->ID . '.min.css' ) ) {
185 - wp_enqueue_style( 'betterdocs-block-style-' . $post->ID, $this->style_url . $this->prefix . '-' . $post->ID . '.min.css', $deps, substr( md5( microtime( true ) ), 0, 10 ) );
186 - }
187 + // generatepress elements
188 + // phpcs:ignore WordPress.NamingConventions.PrefixAllGlobals.NonPrefixedHooknameFound -- WP core 'active_plugins' filter, applied to detect GeneratePress Premium presence on multisite.
189 + if ( in_array( 'gp-premium/gp-premium.php', apply_filters( 'active_plugins', get_option( 'active_plugins' ) ) ) ) {
190 + $gp_elements = get_posts( array( 'post_type' => 'gp_elements' ) );
191 + if ( is_array( $gp_elements ) && ! empty( $gp_elements ) ) {
192 + foreach ( $gp_elements as $element ) {
193 + if ( file_exists( $this->style_dir . $this->prefix . '-' . $element->ID . '.min.css' ) ) {
194 + wp_enqueue_style( 'betterdocs-block-style-' . $element->ID, $this->style_url . $this->prefix . '-' . $element->ID . '.min.css', $deps, substr( md5( microtime( true ) ), 0, 10 ) );
195 + }
196 + }
197 + }
198 + }
187 199
188 - // Reusable block Style Enqueues
189 - $reusableIds = get_post_meta( $post->ID, '_betterdocs_reusable_block_ids', true );
190 - $reusableIds = ! empty( $reusableIds ) ? $reusableIds : [];
191 - $templateReusableIds = get_option( '_betterdocs_reusable_block_ids', [] );
192 - $reusableIds = array_unique( array_merge( $reusableIds, $templateReusableIds ) );
193 - if ( ! empty( $reusableIds ) ) {
194 - foreach ( $reusableIds as $reusableId ) {
195 - if ( file_exists( $this->style_dir . 'reusable-blocks/betterdocs-reusable-' . $reusableId . '.min.css' ) ) {
196 - wp_enqueue_style( 'betterdocs-reusable-block-style-' . $reusableId, $this->style_url . 'reusable-blocks/betterdocs-reusable-' . $reusableId . '.min.css', $deps, substr( md5( microtime( true ) ), 0, 10 ) );
197 - }
198 - }
199 - }
200 - }
200 + if ( ! empty( $post ) && ! empty( $post->ID ) ) {
201 + //Page/Post Style Enqueue
202 + if ( file_exists( $this->style_dir . $this->prefix . '-' . $post->ID . '.min.css' ) ) {
203 + wp_enqueue_style( 'betterdocs-block-style-' . $post->ID, $this->style_url . $this->prefix . '-' . $post->ID . '.min.css', $deps, substr( md5( microtime( true ) ), 0, 10 ) );
204 + }
201 205
202 - //Widget Style Enqueue
203 - if ( file_exists( $this->style_dir . $this->prefix . '-widget.min.css' ) ) {
204 - wp_enqueue_style( 'betterdocs-widget-style', $this->style_url . $this->prefix . '-widget.min.css', $deps, substr( md5( microtime( true ) ), 0, 10 ) );
205 - }
206 + // Reusable block Style Enqueues
207 + $reusableIds = get_post_meta( $post->ID, '_betterdocs_reusable_block_ids', true );
208 + $reusableIds = ! empty( $reusableIds ) ? $reusableIds : array( );
209 + $templateReusableIds = get_option( '_betterdocs_reusable_block_ids', array( ) );
210 + $reusableIds = array_unique( array_merge( $reusableIds, $templateReusableIds ) );
211 + if ( ! empty( $reusableIds ) ) {
212 + foreach ( $reusableIds as $reusableId ) {
213 + if ( file_exists( $this->style_dir . 'reusable-blocks/betterdocs-reusable-' . $reusableId . '.min.css' ) ) {
214 + wp_enqueue_style( 'betterdocs-reusable-block-style-' . $reusableId, $this->style_url . 'reusable-blocks/betterdocs-reusable-' . $reusableId . '.min.css', $deps, substr( md5( microtime( true ) ), 0, 10 ) );
215 + }
216 + }
217 + }
218 + }
206 219
207 - //FSE Style Enqueue
208 - if ( function_exists( 'wp_is_block_theme' ) && wp_is_block_theme() && file_exists( $this->style_dir . $this->prefix . '-edit-site.min.css' ) && betterdocs()->helper->is_templates() ) {
209 - wp_enqueue_style( 'betterdocs-fullsite-style', $this->style_url . $this->prefix . '-edit-site.min.css', $deps, substr( md5( microtime( true ) ), 0, 10 ) );
210 - }
220 + //Widget Style Enqueue
221 + if ( file_exists( $this->style_dir . $this->prefix . '-widget.min.css' ) ) {
222 + wp_enqueue_style( 'betterdocs-widget-style', $this->style_url . $this->prefix . '-widget.min.css', $deps, substr( md5( microtime( true ) ), 0, 10 ) );
223 + }
211 224
212 - /**
213 - * Hooks assets for enqueue in frontend
214 - *
215 - * @param $path string
216 - * @param $url string
217 - *
218 - * @since 3.0.0
219 - */
220 - do_action( 'betterdocs_frontend_assets', $this->style_dir, $this->style_url );
221 - }
225 + //FSE Style Enqueue — one file per FSE template/template-part post so
226 + // styles do not bleed across templates (issue #53).
227 + if ( function_exists( 'wp_is_block_theme' ) && wp_is_block_theme() && betterdocs()->helper->is_templates() && ! empty( self::$_fse_template_post_ids ) ) {
228 + foreach ( array_unique( self::$_fse_template_post_ids ) as $template_post_id ) {
229 + $file_name = $this->prefix . '-edit-site-' . abs( $template_post_id ) . '.min.css';
230 + if ( file_exists( $this->style_dir . $file_name ) ) {
231 + wp_enqueue_style(
232 + 'betterdocs-fullsite-style-' . abs( $template_post_id ),
233 + $this->style_url . $file_name,
234 + $deps,
235 + substr( md5( microtime( true ) ), 0, 10 )
236 + );
237 + }
238 + }
239 + }
222 240
223 - /**
224 - * Get post content when page is saved
225 - */
226 - public function on_save_post( $post_id, $post, $update ) {
227 - $post_type = get_post_type( $post_id );
241 + /**
242 + * Hooks assets for enqueue in frontend
243 + *
244 + * @param $path string
245 + * @param $url string
246 + *
247 + * @since 3.0.0
248 + */
249 + do_action( 'betterdocs_frontend_assets', $this->style_dir, $this->style_url );
250 + }
228 251
229 - //If This page is draft, return
230 - if ( isset( $post->post_status ) && 'auto-draft' == $post->post_status ) {
231 - return;
232 - }
252 + /**
253 + * Get post content when page is saved
254 + */
255 + public function on_save_post( $post_id, $post, $update ) {
256 + $post_type = get_post_type( $post_id );
233 257
234 - // Autosave, do nothing
235 - if ( defined( 'DOING_AUTOSAVE' ) && DOING_AUTOSAVE ) {
236 - return;
237 - }
258 + //If This page is draft, return
259 + if ( isset( $post->post_status ) && 'auto-draft' == $post->post_status ) {
260 + return;
261 + }
238 262
239 - // Return if it's a post revision
240 - if ( false !== wp_is_post_revision( $post_id ) ) {
241 - return;
242 - }
263 + // Autosave, do nothing
264 + if ( defined( 'DOING_AUTOSAVE' ) && DOING_AUTOSAVE ) {
265 + return;
266 + }
243 267
244 - $parsed_content = $this->get_parsed_content( $post_id, $post, $post_type );
268 + // Return if it's a post revision
269 + if ( false !== wp_is_post_revision( $post_id ) ) {
270 + return;
271 + }
245 272
246 - if ( is_array( $parsed_content ) && ! empty( $parsed_content ) ) {
247 - $this->write_css_from_content( $post, $post_id, $parsed_content );
248 - }
249 - }
273 + $parsed_content = $this->get_parsed_content( $post_id, $post, $post_type );
250 274
251 - private function get_parsed_content( $post_id, $post, $post_type ) {
252 - if ( $post_type === 'wp_template_part' || $post_type === 'wp_template' ) {
253 - $post = get_post( $post_id );
254 - }
275 + if ( is_array( $parsed_content ) && ! empty( $parsed_content ) ) {
276 + $this->write_css_from_content( $post, $post_id, $parsed_content );
277 + }
278 + }
255 279
256 - if ( ! $post ) {
257 - return [];
258 - }
280 + private function get_parsed_content( $post_id, $post, $post_type ) {
281 + if ( 'wp_template_part' === $post_type || 'wp_template' === $post_type ) {
282 + $post = get_post( $post_id );
283 + }
259 284
260 - $parsed_content = parse_blocks( $post->post_content );
285 + if ( ! $post ) {
286 + return array( );
287 + }
261 288
262 - if ( empty( $parsed_content ) ) {
263 - delete_post_meta( $post_id, '_betterdocs_reusable_block_ids' );
264 - }
289 + $parsed_content = parse_blocks( $post->post_content );
265 290
266 - return $parsed_content;
267 - }
291 + if ( empty( $parsed_content ) ) {
292 + delete_post_meta( $post_id, '_betterdocs_reusable_block_ids' );
293 + }
268 294
269 - /**
270 - * Get post content when page is load in frontend
271 - */
272 - public function generate_post_content() {
273 - $post_id = get_the_ID();
274 - if ( $post_id ) {
275 - $post_type = get_post_type( $post_id );
276 - $post = get_post( $post_id );
277 - //If This page is draft, return
278 - if ( isset( $post->post_status ) && 'auto-draft' == $post->post_status ) {
279 - return;
280 - }
295 + return $parsed_content;
296 + }
281 297
282 - // Return if it's a post revision
283 - if ( false !== wp_is_post_revision( $post_id ) ) {
284 - return null;
285 - }
298 + /**
299 + * Get post content when page is load in frontend
300 + */
301 + public function generate_post_content() {
302 + $post_id = get_the_ID();
303 + if ( $post_id ) {
304 + $post_type = get_post_type( $post_id );
305 + $post = get_post( $post_id );
306 + //If This page is draft, return
307 + if ( isset( $post->post_status ) && 'auto-draft' == $post->post_status ) {
308 + return;
309 + }
286 310
287 - $parsed_content = $this->get_parsed_content( $post_id, $post, $post_type );
311 + // Return if it's a post revision
312 + if ( false !== wp_is_post_revision( $post_id ) ) {
313 + return null;
314 + }
288 315
289 - if ( is_array( $parsed_content ) && ! empty( $parsed_content ) ) {
290 - $this->write_css_from_content( $post, $post_id, $parsed_content );
291 - }
292 - }
293 - }
316 + $parsed_content = $this->get_parsed_content( $post_id, $post, $post_type );
294 317
295 - /**
296 - * Ajax callback to write css in upload directory
297 - * @retun void
298 - * @since 1.0.2
299 - */
300 - private function write_block_css( $block_styles, $post ) {
301 - if ( ! $post ) {
302 - return;
303 - }
318 + if ( is_array( $parsed_content ) && ! empty( $parsed_content ) ) {
319 + $this->write_css_from_content( $post, $post_id, $parsed_content );
320 + }
321 + }
322 + }
304 323
305 - //Write CSS for FSE
306 - if ( isset( $post->post_type ) && ( $post->post_type === 'wp_template_part' || $post->post_type === 'wp_template' && ! empty( $block_styles ) ) ) {
307 - $this->single_file_css_generator( $block_styles, $this->style_dir, $this->prefix . '-edit-site.min.css' );
308 - } // Write CSS for Page/Posts
309 - elseif ( ! empty( $css = CSSParser::build_css( $block_styles ) ) ) {
310 - if ( ! file_exists( $this->style_dir ) ) {
311 - mkdir( $this->style_dir );
312 - }
313 - file_put_contents( $this->style_dir . $this->prefix . '-' . abs( $post->ID ) . '.min.css', $css );
314 - }
315 - }
324 + /**
325 + * Ajax callback to write css in upload directory
326 + * @retun void
327 + * @since 1.0.2
328 + */
329 + private function write_block_css( $block_styles, $post ) {
330 + // Write CSS for FSE templates / template parts — one file per post so
331 + // styles from different templates do not overwrite each other in a
332 + // shared file (issue #53).
333 + if ( isset( $post->post_type ) && ( 'wp_template_part' === $post->post_type || 'wp_template' === $post->post_type ) ) {
334 + if ( empty( $block_styles ) ) {
335 + return;
336 + }
337 + if ( ! empty( $css = CSSParser::build_css( $block_styles ) ) ) {
338 + if ( ! file_exists( $this->style_dir ) ) {
339 + wp_mkdir_p( $this->style_dir );
340 + }
341 + file_put_contents( $this->style_dir . $this->prefix . '-edit-site-' . abs( $post->ID ) . '.min.css', $css );
342 + }
343 + } // Write CSS for Page/Posts
344 + elseif ( ! empty( $css = CSSParser::build_css( $block_styles ) ) ) {
345 + if ( ! file_exists( $this->style_dir ) ) {
346 + wp_mkdir_p( $this->style_dir );
347 + }
348 + file_put_contents( $this->style_dir . $this->prefix . '-' . abs( $post->ID ) . '.min.css', $css );
349 + }
350 + }
316 351
317 - /**
318 - * Write css for Reusable block
319 - * @retun void
320 - * @since 3.4.0
321 - */
322 - private function write_reusable_block_css( $block_styles, $id ) {
323 - if ( isset( $block_styles ) && is_array( $block_styles ) ) {
324 - if ( ! empty( $css = CSSParser::build_css( $block_styles ) ) ) {
325 - $upload_dir = $this->style_dir . 'reusable-blocks/';
326 - if ( ! file_exists( $upload_dir ) ) {
327 - mkdir( $upload_dir, 0777, true );
328 - }
329 - file_put_contents( $upload_dir . '/' . 'betterdocs-reusable-' . abs( $id ) . '.min.css', $css );
330 - }
331 - }
332 - }
352 + /**
353 + * Write css for Reusable block
354 + * @retun void
355 + * @since 3.4.0
356 + */
357 + private function write_reusable_block_css( $block_styles, $id ) {
358 + if ( isset( $block_styles ) && is_array( $block_styles ) ) {
359 + if ( ! empty( $css = CSSParser::build_css( $block_styles ) ) ) {
360 + $upload_dir = $this->style_dir . 'reusable-blocks/';
361 + if ( ! file_exists( $upload_dir ) ) {
362 + wp_mkdir_p( $upload_dir );
363 + }
364 + file_put_contents( $upload_dir . '/' . 'betterdocs-reusable-' . abs( $id ) . '.min.css', $css );
365 + }
366 + }
367 + }
333 368
334 - /**
335 - * Single file css generator
336 - * @retun void
337 - * @since 3.5.3
338 - */
339 - private function single_file_css_generator( $block_styles, $upload_dir, $filename ) {
340 - $editSiteCssPath = $upload_dir . $filename;
341 - if ( file_exists( $editSiteCssPath ) ) {
342 - $existingCss = file_get_contents( $editSiteCssPath );
343 - $pattern = '~\/\*(.*?)\*\/~';
344 - preg_match_all( $pattern, $existingCss, $result, PREG_PATTERN_ORDER );
345 - $allComments = $result[0];
346 - $seperatedIds = [];
347 - foreach ( $allComments as $comment ) {
348 - $id = preg_replace( '/[^A-Za-z0-9\-]|Ends|Starts/', '', $comment );
369 + /**
370 + * Single file css generator
371 + * @retun void
372 + * @since 3.5.3
373 + */
374 + private function single_file_css_generator( $block_styles, $upload_dir, $filename ) {
375 + $editSiteCssPath = $upload_dir . $filename;
376 + if ( file_exists( $editSiteCssPath ) ) {
377 + $existingCss = file_get_contents( $editSiteCssPath );
378 + $pattern = '~\/\*(.*?)\*\/~';
379 + preg_match_all( $pattern, $existingCss, $result, PREG_PATTERN_ORDER );
380 + $allComments = $result[ 0 ];
381 + $seperatedIds = array( );
382 + foreach ( $allComments as $comment ) {
383 + $id = preg_replace( '/[^A-Za-z0-9\-]|Ends|Starts/', '', $comment );
349 384
350 - if ( strpos( $comment, 'Starts' ) ) {
351 - $seperatedIds[ $id ]['start'] = $comment;
352 - } elseif ( strpos( $comment, 'Ends' ) ) {
353 - $seperatedIds[ $id ]['end'] = $comment;
354 - }
355 - }
385 + if ( strpos( $comment, 'Starts' ) ) {
386 + $seperatedIds[ $id ][ 'start' ] = $comment;
387 + } elseif ( strpos( $comment, 'Ends' ) ) {
388 + $seperatedIds[ $id ][ 'end' ] = $comment;
389 + }
390 + }
356 391
357 - $seperateStyles = [];
358 - foreach ( $seperatedIds as $key => $ids ) {
359 - $seperateStyles[][ $key ] = isset( $block_styles[ $key ] ) ? $block_styles[ $key ] : [];
360 - }
392 + $seperateStyles = array( );
393 + foreach ( $seperatedIds as $key => $ids ) {
394 + $seperateStyles[ ][ $key ] = isset( $block_styles[ $key ] ) ? $block_styles[ $key ] : array( );
395 + }
361 396
362 - self::$_block_styles = array_merge( self::$_block_styles, $block_styles );
397 + self::$_block_styles = array_merge( self::$_block_styles, $block_styles );
363 398
364 - if ( ! empty( $css = CSSParser::build_css( self::$_block_styles ) ) ) {
365 - if ( ! file_exists( $upload_dir ) ) {
366 - mkdir( $upload_dir );
367 - }
399 + if ( ! empty( $css = CSSParser::build_css( self::$_block_styles ) ) ) {
400 + if ( ! file_exists( $upload_dir ) ) {
401 + wp_mkdir_p( $upload_dir );
402 + }
368 403
369 - file_put_contents( $editSiteCssPath, $css );
370 - }
371 - } elseif ( ! empty( $css = CSSParser::build_css( $block_styles ) ) ) {
372 - if ( ! file_exists( $this->style_dir ) ) {
373 - mkdir( $this->style_dir );
374 - }
404 + file_put_contents( $editSiteCssPath, $css );
405 + }
406 + } elseif ( ! empty( $css = CSSParser::build_css( $block_styles ) ) ) {
407 + if ( ! file_exists( $this->style_dir ) ) {
408 + wp_mkdir_p( $this->style_dir );
409 + }
375 410
376 - file_put_contents( $editSiteCssPath, $css );
377 - }
378 - }
411 + file_put_contents( $editSiteCssPath, $css );
412 + }
413 + }
379 414
380 - /**
381 - * Get post id by post_name for template
382 - */
383 - public static function betterdocs_get_post_content_by_post_name( $post_name ) {
384 - global $wpdb;
385 - $sql = $wpdb->prepare( "SELECT ID FROM {$wpdb->prefix}posts WHERE post_name = %s", $post_name );
415 + /**
416 + * Get post id by post_name for template
417 + */
418 + public static function betterdocs_get_post_content_by_post_name( $post_name ) {
419 + global $wpdb;
420 + $sql = $wpdb->prepare( "SELECT ID FROM {$wpdb->prefix}posts WHERE post_name = %s", $post_name );
386 421
387 - return $wpdb->get_results( $sql, ARRAY_A ); // phpcs:ignore WordPress.DB.PreparedSQL.NotPrepared
388 - }
422 + // phpcs:ignore WordPress.DB.PreparedSQL.NotPrepared, WordPress.DB.DirectDatabaseQuery.DirectQuery, WordPress.DB.DirectDatabaseQuery.NoCaching -- one-off lookup of FSE template posts by post_name during CSS generation; no caching layer applies.
423 + return $wpdb->get_results( $sql, ARRAY_A );
424 + }
389 425 }