From c026a2ff078e86f6e4163ba155da0c8918620364 Mon Sep 17 00:00:00 2001 From: Dean Sas Date: Wed, 28 Jan 2026 10:52:00 +0000 Subject: [PATCH 1/2] Fix CSS concatenation to preserve original stylesheet order The previous implementation grouped all concatenatable CSS files into a single bundle that was always output first, before non-concatenatable items. This broke the relative order between concatenated stylesheets and non-concatenated items (such as files with inline styles). This caused issues where theme stylesheets that should appear after Gutenberg's global styles were instead output before them, allowing Gutenberg's `a:where(:not(.wp-element-button))` rule to override theme link styling due to CSS cascade order. The fix adopts the same approach used in concat-js.php: use a level counter where non-concatenatable items break the current concat group (double-increment pattern), preserving the original WordPress enqueue order. Fixes DOTTHEM-159 --- concat-css.php | 94 ++++++++++++++++++++++++++------------------------ 1 file changed, 49 insertions(+), 45 deletions(-) diff --git a/concat-css.php b/concat-css.php index 18024d8..a937df3 100644 --- a/concat-css.php +++ b/concat-css.php @@ -42,11 +42,9 @@ function do_items( $handles = false, $group = false ) { $this->all_deps( $handles ); - $stylesheet_group_index = 0; - // Merge CSS into a single file - $concat_group = 'concat'; - // Concat group on top (first array element gets processed earlier) - $stylesheets[ $concat_group ] = array(); + // Track position in output order. Non-concat items break concat groups + // to preserve the original stylesheet order (matching concat-js.php approach). + $level = 0; foreach ( $this->to_do as $key => $handle ) { $obj = $this->registered[ $handle ]; @@ -136,59 +134,65 @@ function do_items( $handles = false, $group = false ) { $media = 'all'; } - $stylesheets[ $concat_group ][ $media ][ $handle ] = $css_url_parsed['path']; + // Add to current concat group (create if needed) + if ( ! isset( $stylesheets[ $level ] ) ) { + $stylesheets[ $level ]['type'] = 'concat'; + } + $stylesheets[ $level ]['paths'][ $media ][ $handle ] = $css_url_parsed['path']; $this->done[] = $handle; } else { - $stylesheet_group_index ++; - $stylesheets[ $stylesheet_group_index ]['noconcat'][] = $handle; - $stylesheet_group_index ++; + // Non-concat items break the group to preserve order (double-increment pattern from concat-js.php) + $level++; + $stylesheets[ $level ]['type'] = 'do_item'; + $stylesheets[ $level ]['handle'] = $handle; + $level++; } unset( $this->to_do[ $key ] ); } - foreach ( $stylesheets as $idx => $stylesheets_group ) { - foreach ( $stylesheets_group as $media => $css ) { - if ( 'noconcat' == $media ) { - foreach ( $css as $handle ) { - if ( $this->do_item( $handle, $group ) ) { - $this->done[] = $handle; + foreach ( $stylesheets as $css_array ) { + if ( 'do_item' === $css_array['type'] ) { + if ( $this->do_item( $css_array['handle'], $group ) ) { + $this->done[] = $css_array['handle']; + } + } elseif ( 'concat' === $css_array['type'] ) { + // Process each media type within the concat group + foreach ( $css_array['paths'] as $media => $css ) { + if ( count( $css ) > 1 ) { + $fs_paths = array(); + foreach ( $css as $css_uri_path ) { + $fs_paths[] = $this->dependency_path_mapping->uri_path_to_fs_path( $css_uri_path ); } - } - continue; - } elseif ( count( $css ) > 1 ) { - $fs_paths = array(); - foreach ( $css as $css_uri_path ) { - $fs_paths[] = $this->dependency_path_mapping->uri_path_to_fs_path( $css_uri_path ); - } - $mtime = max( array_map( 'filemtime', $fs_paths ) ); - if ( page_optimize_use_concat_base_dir() ) { - $path_str = implode( ',', array_map( 'page_optimize_remove_concat_base_prefix', $fs_paths ) ); - } else { - $path_str = implode( ',', $css ); - } - $path_str = "$path_str?m=$mtime"; + $mtime = max( array_map( 'filemtime', $fs_paths ) ); + if ( page_optimize_use_concat_base_dir() ) { + $path_str = implode( ',', array_map( 'page_optimize_remove_concat_base_prefix', $fs_paths ) ); + } else { + $path_str = implode( ',', $css ); + } + $path_str = "$path_str?m=$mtime"; - if ( $this->allow_gzip_compression ) { - $path_64 = base64_encode( gzcompress( $path_str ) ); - if ( strlen( $path_str ) > ( strlen( $path_64 ) + 1 ) ) { - $path_str = '-' . $path_64; + if ( $this->allow_gzip_compression ) { + $path_64 = base64_encode( gzcompress( $path_str ) ); + if ( strlen( $path_str ) > ( strlen( $path_64 ) + 1 ) ) { + $path_str = '-' . $path_64; + } } - } - $href = $siteurl . "/_static/??" . $path_str; - } else { - $href = Page_Optimize_Utils::cache_bust_mtime( current( $css ), $siteurl ); - } + $href = $siteurl . "/_static/??" . $path_str; + } else { + $href = Page_Optimize_Utils::cache_bust_mtime( current( $css ), $siteurl ); + } - $handles = array_keys( $css ); - $css_id = "$media-css-" . md5( $href ); - if ( defined( 'WP_DEBUG' ) && WP_DEBUG ) { - echo apply_filters( 'page_optimize_style_loader_tag', "\n", $handles, $href, $media ); - } else { - echo apply_filters( 'page_optimize_style_loader_tag', "\n", $handles, $href, $media ); + $handles = array_keys( $css ); + $css_id = "$media-css-" . md5( $href ); + if ( defined( 'WP_DEBUG' ) && WP_DEBUG ) { + echo apply_filters( 'page_optimize_style_loader_tag', "\n", $handles, $href, $media ); + } else { + echo apply_filters( 'page_optimize_style_loader_tag', "\n", $handles, $href, $media ); + } + array_map( array( $this, 'print_inline_style' ), array_keys( $css ) ); } - array_map( array( $this, 'print_inline_style' ), array_keys( $css ) ); } } From 8b043f988a4315a484eda7c86ab5bf40856fcdf2 Mon Sep 17 00:00:00 2001 From: Dean Sas Date: Wed, 28 Jan 2026 11:07:42 +0000 Subject: [PATCH 2/2] Add defensive isset() check for paths array --- concat-css.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/concat-css.php b/concat-css.php index a937df3..535e205 100644 --- a/concat-css.php +++ b/concat-css.php @@ -155,7 +155,7 @@ function do_items( $handles = false, $group = false ) { if ( $this->do_item( $css_array['handle'], $group ) ) { $this->done[] = $css_array['handle']; } - } elseif ( 'concat' === $css_array['type'] ) { + } elseif ( 'concat' === $css_array['type'] && isset( $css_array['paths'] ) ) { // Process each media type within the concat group foreach ( $css_array['paths'] as $media => $css ) { if ( count( $css ) > 1 ) {