Changeset 3789508
- Timestamp:
- 11/07/2026 12:09:08 PM (less than one hour ago)
- Location:
- theme-builder-for-elementor
- Files:
-
- 30 edited
- 1 copied
-
tags/2.0.1 (copied) (copied from theme-builder-for-elementor/trunk )
-
tags/2.0.1/assets/css/frontend.css (modified) (1 diff)
-
tags/2.0.1/assets/css/frontend.min.css (modified) (1 diff)
-
tags/2.0.1/includes/conditions/class-resolver.php (modified) (1 diff)
-
tags/2.0.1/includes/elementor/widgets/class-breadcrumbs.php (modified) (1 diff)
-
tags/2.0.1/includes/elementor/widgets/class-posts.php (modified) (1 diff)
-
tags/2.0.1/includes/library/class-library.php (modified) (1 diff)
-
tags/2.0.1/includes/library/class-references.php (modified) (1 diff)
-
tags/2.0.1/includes/render/class-renderer.php (modified) (1 diff)
-
tags/2.0.1/includes/render/class-theme-support.php (modified) (7 diffs)
-
tags/2.0.1/readme.txt (modified) (2 diffs)
-
tags/2.0.1/templates/archive.php (modified) (1 diff)
-
tags/2.0.1/templates/canvas.php (modified) (1 diff)
-
tags/2.0.1/templates/full-width.php (modified) (2 diffs)
-
tags/2.0.1/templates/single.php (modified) (1 diff)
-
tags/2.0.1/theme-builder-for-elementor.php (modified) (2 diffs)
-
trunk/assets/css/frontend.css (modified) (1 diff)
-
trunk/assets/css/frontend.min.css (modified) (1 diff)
-
trunk/includes/conditions/class-resolver.php (modified) (1 diff)
-
trunk/includes/elementor/widgets/class-breadcrumbs.php (modified) (1 diff)
-
trunk/includes/elementor/widgets/class-posts.php (modified) (1 diff)
-
trunk/includes/library/class-library.php (modified) (1 diff)
-
trunk/includes/library/class-references.php (modified) (1 diff)
-
trunk/includes/render/class-renderer.php (modified) (1 diff)
-
trunk/includes/render/class-theme-support.php (modified) (7 diffs)
-
trunk/readme.txt (modified) (2 diffs)
-
trunk/templates/archive.php (modified) (1 diff)
-
trunk/templates/canvas.php (modified) (1 diff)
-
trunk/templates/full-width.php (modified) (2 diffs)
-
trunk/templates/single.php (modified) (1 diff)
-
trunk/theme-builder-for-elementor.php (modified) (2 diffs)
Legend:
- Unmodified
- Added
- Removed
-
theme-builder-for-elementor/tags/2.0.1/assets/css/frontend.css
r3783780 r3789508 8 8 .tbfe-location-404, 9 9 .tbfe-location-content { display: block; width: 100%; } 10 11 /* Themes style their own #site-header, #site-footer, #content and main (flex rows, paddings, floats of a sidebar 12 layout); the elements of the plugin carry the same ids, so these rules beat the theme's. Position and background 13 stay free for the sticky and transparent header. */ 14 #site-header.tbfe-location, 15 #site-footer.tbfe-location { display: block; float: none; clear: both; box-sizing: border-box; width: 100%; max-width: none; height: auto; min-height: 0; margin: 0; padding: 0; border: 0; } 16 17 #content.tbfe-location, 18 main.tbfe-location { float: none; clear: both; box-sizing: border-box; width: 100%; max-width: none; } 10 19 11 20 .tbfe-container, -
theme-builder-for-elementor/tags/2.0.1/assets/css/frontend.min.css
r3783780 r3789508 1 .tbfe-location-404,.tbfe-location-archive,.tbfe-location-content,.tbfe-location-footer,.tbfe-location-header,.tbfe-location-single{display:block;width:100%} .tbfe-archive--boxed,.tbfe-container{box-sizing:border-box;width:100%;max-width:var(--tbfe-container, 1140px);margin-right:auto;margin-left:auto;padding-right:20px;padding-left:20px}.tbfe-archive{display:grid;grid-template-columns:minmax(0,1fr);gap:40px;padding-top:40px;padding-bottom:40px}.tbfe-archive--full{padding-right:20px;padding-left:20px}.tbfe-archive--sidebar{grid-template-columns:minmax(0,3fr) minmax(0,1fr)}.tbfe-archive__posts{display:flex;flex-direction:column;gap:30px;min-width:0}.tbfe-archive__item{margin:0}.tbfe-archive__sidebar{min-width:0}@media (max-width:767px){.tbfe-archive--sidebar{grid-template-columns:minmax(0,1fr)}}.tbfe-password{padding-top:40px;padding-bottom:40px}.tbfe-header--sticky,.tbfe-header--transparent{z-index:990;transition:background-color .3s ease,box-shadow .3s ease,transform .3s ease}.tbfe-header--sticky{position:sticky;top:var(--wp-admin--admin-bar--height, 0px)}.tbfe-header--transparent{position:absolute;top:var(--wp-admin--admin-bar--height, 0px);right:0;left:0;background-color:transparent}.tbfe-header--transparent.tbfe-header--sticky{position:fixed}.tbfe-header--sticky.is-scrolled{background-color:var(--tbfe-scrolled-bg, transparent)}.tbfe-header--shadow.is-scrolled{box-shadow:0 6px 24px rgba(15,23,42,.1)}.tbfe-header--hide.is-hidden{transform:translateY(-110%)}.tbfe-header--shrink .elementor-element-populated,.tbfe-header--shrink .elementor>.e-con,.tbfe-header--shrink .elementor>.elementor-section,.tbfe-header--shrink .tbfe-site-logo img{transition:padding .3s ease,min-height .3s ease,max-height .3s ease}.tbfe-header--shrink.is-scrolled .elementor>.e-con,.tbfe-header--shrink.is-scrolled .elementor>.elementor-section{padding-top:4px!important;padding-bottom:4px!important}.tbfe-header--shrink.is-scrolled .elementor-element-populated{padding-top:2px!important;padding-bottom:2px!important}.tbfe-header--shrink.is-scrolled .elementor-container{min-height:0!important}.tbfe-header--shrink.is-scrolled .tbfe-site-logo img{width:auto!important;max-height:var(--tbfe-shrink-logo, 36px)}@media (max-width:600px){.tbfe-header--sticky,.tbfe-header--transparent{top:0}}@media (max-width:1024px){.tbfe-header--transparent.tbfe-transparent-desktop.tbfe-header--sticky{position:sticky;top:0}.tbfe-header--transparent.tbfe-transparent-desktop,.tbfe-location-header.tbfe-header--sticky.tbfe-sticky-desktop{position:relative;top:auto}.tbfe-location-header.tbfe-header--transparent.tbfe-sticky-desktop:not(.tbfe-transparent-desktop){position:absolute;top:0}}@media (max-width:767px){.tbfe-header--transparent.tbfe-transparent-desktop-tablet.tbfe-header--sticky{position:sticky;top:0}.tbfe-header--transparent.tbfe-transparent-desktop-tablet,.tbfe-location-header.tbfe-header--sticky.tbfe-sticky-desktop-tablet{position:relative;top:auto}.tbfe-location-header.tbfe-header--transparent.tbfe-sticky-desktop-tablet.tbfe-transparent-all{position:absolute;top:0}}1 .tbfe-location-404,.tbfe-location-archive,.tbfe-location-content,.tbfe-location-footer,.tbfe-location-header,.tbfe-location-single{display:block;width:100%}#site-footer.tbfe-location,#site-header.tbfe-location{display:block;height:auto;min-height:0;margin:0;padding:0;border:0}#content.tbfe-location,#site-footer.tbfe-location,#site-header.tbfe-location,main.tbfe-location{float:none;clear:both;box-sizing:border-box;width:100%;max-width:none}.tbfe-archive--boxed,.tbfe-container{box-sizing:border-box;width:100%;max-width:var(--tbfe-container, 1140px);margin-right:auto;margin-left:auto;padding-right:20px;padding-left:20px}.tbfe-archive{display:grid;grid-template-columns:minmax(0,1fr);gap:40px;padding-top:40px;padding-bottom:40px}.tbfe-archive--full{padding-right:20px;padding-left:20px}.tbfe-archive--sidebar{grid-template-columns:minmax(0,3fr) minmax(0,1fr)}.tbfe-archive__posts{display:flex;flex-direction:column;gap:30px;min-width:0}.tbfe-archive__item{margin:0}.tbfe-archive__sidebar{min-width:0}@media (max-width:767px){.tbfe-archive--sidebar{grid-template-columns:minmax(0,1fr)}}.tbfe-password{padding-top:40px;padding-bottom:40px}.tbfe-header--sticky,.tbfe-header--transparent{z-index:990;transition:background-color .3s ease,box-shadow .3s ease,transform .3s ease}.tbfe-header--sticky{position:sticky;top:var(--wp-admin--admin-bar--height, 0px)}.tbfe-header--transparent{position:absolute;top:var(--wp-admin--admin-bar--height, 0px);right:0;left:0;background-color:transparent}.tbfe-header--transparent.tbfe-header--sticky{position:fixed}.tbfe-header--sticky.is-scrolled{background-color:var(--tbfe-scrolled-bg, transparent)}.tbfe-header--shadow.is-scrolled{box-shadow:0 6px 24px rgba(15,23,42,.1)}.tbfe-header--hide.is-hidden{transform:translateY(-110%)}.tbfe-header--shrink .elementor-element-populated,.tbfe-header--shrink .elementor>.e-con,.tbfe-header--shrink .elementor>.elementor-section,.tbfe-header--shrink .tbfe-site-logo img{transition:padding .3s ease,min-height .3s ease,max-height .3s ease}.tbfe-header--shrink.is-scrolled .elementor>.e-con,.tbfe-header--shrink.is-scrolled .elementor>.elementor-section{padding-top:4px!important;padding-bottom:4px!important}.tbfe-header--shrink.is-scrolled .elementor-element-populated{padding-top:2px!important;padding-bottom:2px!important}.tbfe-header--shrink.is-scrolled .elementor-container{min-height:0!important}.tbfe-header--shrink.is-scrolled .tbfe-site-logo img{width:auto!important;max-height:var(--tbfe-shrink-logo, 36px)}@media (max-width:600px){.tbfe-header--sticky,.tbfe-header--transparent{top:0}}@media (max-width:1024px){.tbfe-header--transparent.tbfe-transparent-desktop.tbfe-header--sticky{position:sticky;top:0}.tbfe-header--transparent.tbfe-transparent-desktop,.tbfe-location-header.tbfe-header--sticky.tbfe-sticky-desktop{position:relative;top:auto}.tbfe-location-header.tbfe-header--transparent.tbfe-sticky-desktop:not(.tbfe-transparent-desktop){position:absolute;top:0}}@media (max-width:767px){.tbfe-header--transparent.tbfe-transparent-desktop-tablet.tbfe-header--sticky{position:sticky;top:0}.tbfe-header--transparent.tbfe-transparent-desktop-tablet,.tbfe-location-header.tbfe-header--sticky.tbfe-sticky-desktop-tablet{position:relative;top:auto}.tbfe-location-header.tbfe-header--transparent.tbfe-sticky-desktop-tablet.tbfe-transparent-all{position:absolute;top:0}} -
theme-builder-for-elementor/tags/2.0.1/includes/conditions/class-resolver.php
r3783780 r3789508 132 132 } 133 133 134 // Products and the shop of WooCommerce: All singular / All archives of a blog Single or Archive template do 135 // not count there. The blog layout would take the add to cart and the shop loop away; the theme's shop (or the 136 // product templates of PRO) stay, unless a condition chooses them, like Products. 137 $shop = in_array( $location, array( 'single', 'archive' ), true ) && function_exists( 'is_woocommerce' ) && is_woocommerce(); 138 134 139 $best = 0; 135 140 $best_score = -1; 136 141 foreach ( $index[ $location ] as $id => $rules ) { 142 if ( $shop && in_array( Template::type( $id ), array( 'single', 'archive' ), true ) ) { 143 $rules = array_filter( 144 $rules, 145 static function ( $rule ) { 146 return 'exclude' === $rule['type'] || ! in_array( $rule['name'], array( 'singular', 'archive' ), true ); 147 } 148 ); 149 } 137 150 $score = self::rules_score( $rules ); 138 151 if ( $score > $best_score ) { -
theme-builder-for-elementor/tags/2.0.1/includes/elementor/widgets/class-breadcrumbs.php
r3783780 r3789508 162 162 } 163 163 164 /** 165 * Breadcrumbs of Yoast SEO or Rank Math, only when their breadcrumbs are switched on. 166 * Empty string otherwise, so the built-in trail is used. 167 */ 168 private function seo_plugin_trail() { 169 if ( function_exists( 'yoast_breadcrumb' ) ) { 170 $enabled = current_theme_supports( 'yoast-seo-breadcrumbs' ) 171 || ( class_exists( 'WPSEO_Options' ) && \WPSEO_Options::get( 'breadcrumbs-enable', false ) ); 172 if ( $enabled ) { 173 $html = (string) yoast_breadcrumb( '', '', false ); 174 if ( '' !== trim( wp_strip_all_tags( $html ) ) ) { 175 return $html; 176 } 177 } 178 } 179 if ( function_exists( 'rank_math_get_breadcrumbs' ) ) { 180 $enabled = method_exists( '\RankMath\Helper', 'is_breadcrumbs_enabled' ) 181 ? \RankMath\Helper::is_breadcrumbs_enabled() 182 : current_theme_supports( 'rank-math-breadcrumbs' ); 183 if ( $enabled ) { 184 $html = (string) rank_math_get_breadcrumbs(); 185 if ( '' !== trim( wp_strip_all_tags( $html ) ) ) { 186 return $html; 187 } 188 } 189 } 190 return ''; 191 } 192 164 193 protected function render() { 165 194 $settings = $this->get_settings_for_display(); 166 195 167 196 if ( 'auto' === $settings['source'] && ! Context::is_template_preview() ) { 168 if ( function_exists( 'yoast_breadcrumb' ) ) { 169 yoast_breadcrumb( '<nav class="tbfe-breadcrumbs" aria-label="' . esc_attr__( 'Breadcrumbs', 'theme-builder-for-elementor' ) . '">', '</nav>' ); 170 return; 171 } 172 if ( function_exists( 'rank_math_the_breadcrumbs' ) ) { 173 echo '<nav class="tbfe-breadcrumbs" aria-label="' . esc_attr__( 'Breadcrumbs', 'theme-builder-for-elementor' ) . '">'; 174 rank_math_the_breadcrumbs(); 175 echo '</nav>'; 197 $seo = $this->seo_plugin_trail(); 198 if ( '' !== $seo ) { 199 echo '<nav class="tbfe-breadcrumbs" aria-label="' . esc_attr__( 'Breadcrumbs', 'theme-builder-for-elementor' ) . '">' . wp_kses_post( $seo ) . '</nav>'; 176 200 return; 177 201 } -
theme-builder-for-elementor/tags/2.0.1/includes/elementor/widgets/class-posts.php
r3783780 r3789508 575 575 while ( $query->have_posts() ) { 576 576 $query->the_post(); 577 echo '<article class="' . esc_attr( implode( ' ', get_post_class( 'tbfe-posts__item' ) ) ) . '">';577 echo '<article class="' . esc_attr( implode( ' ', Renderer::post_class( 'tbfe-posts__item' ) ) ) . '">'; 578 578 if ( $template ) { 579 579 Renderer::render_template( $template ); -
theme-builder-for-elementor/tags/2.0.1/includes/library/class-library.php
r3783780 r3789508 475 475 } 476 476 477 $posts = array_merge( wp_list_pluck( $pages, 'id' ), $templates ); 478 foreach ( $posts as $post_id ) { 479 $document = \Elementor\Plugin::$instance->documents->get( (int) $post_id, false ); 477 $posts = array_map( 'absint', array_merge( wp_list_pluck( $pages, 'id' ), $templates ) ); 478 $next = 0; 479 while ( $next < count( $posts ) ) { 480 $post_id = $posts[ $next++ ]; 481 $document = \Elementor\Plugin::$instance->documents->get( $post_id, false ); 480 482 if ( ! $document ) { 481 483 continue; 482 484 } 483 485 $elements = $document->get_elements_data(); 484 $changed = false; 486 // Templates imported with the content (slides of a Slider, Section templates, Post Cards) get their links 487 // updated too. 488 foreach ( References::ids( $elements ) as $ref ) { 489 if ( ! in_array( $ref, $posts, true ) && Template::is_template( $ref ) && get_post_meta( $ref, '_tbfe_library_item', true ) ) { 490 $posts[] = $ref; 491 } 492 } 493 $changed = false; 485 494 $elements = self::walk( 486 495 $elements, -
theme-builder-for-elementor/tags/2.0.1/includes/library/class-references.php
r3783780 r3789508 49 49 } 50 50 return $elements; 51 } 52 53 /** 54 * Templates of this site that Elementor content refers to (Post Card, Section Template, slides of a Slider). 55 * 56 * @return int[] 57 */ 58 public static function ids( array $elements ) { 59 $ids = array(); 60 foreach ( $elements as $element ) { 61 if ( ! is_array( $element ) ) { 62 continue; 63 } 64 $type = isset( $element['widgetType'] ) ? $element['widgetType'] : ''; 65 $settings = isset( $element['settings'] ) && is_array( $element['settings'] ) ? $element['settings'] : array(); 66 if ( 'tbfe-posts' === $type && ! empty( $settings['card_template'] ) ) { 67 $ids[] = absint( $settings['card_template'] ); 68 } elseif ( 'tbfe-template' === $type && ! empty( $settings['template_id'] ) ) { 69 $ids[] = absint( $settings['template_id'] ); 70 } elseif ( 'tbfe-slider' === $type && ! empty( $settings['slides'] ) && is_array( $settings['slides'] ) ) { 71 foreach ( $settings['slides'] as $slide ) { 72 if ( ! empty( $slide['template_id'] ) ) { 73 $ids[] = absint( $slide['template_id'] ); 74 } 75 } 76 } 77 if ( ! empty( $element['elements'] ) && is_array( $element['elements'] ) ) { 78 $ids = array_merge( $ids, self::ids( $element['elements'] ) ); 79 } 80 } 81 return array_values( array_unique( array_filter( $ids ) ) ); 51 82 } 52 83 -
theme-builder-for-elementor/tags/2.0.1/includes/render/class-renderer.php
r3783780 r3789508 160 160 * @param int $id Template ID. 161 161 */ 162 /** 163 * Classes of the post element in the plugin's layouts: get_post_class() without the post_class filters of the 164 * theme. Themes add their own card and grid classes there (Astra: ast-article-post, ast-grid-common-col) and 165 * style them as boxes, which put a theme box around the cards of the Posts widget. Plugins (WooCommerce) stay. 166 * 167 * @param string $class Own class. 168 * @return string[] 169 */ 170 public static function post_class( $class = '' ) { 171 global $wp_filter; 172 $removed = array(); 173 if ( isset( $wp_filter['post_class'] ) ) { 174 $dirs = array_unique( array( wp_normalize_path( get_template_directory() ) . '/', wp_normalize_path( get_stylesheet_directory() ) . '/' ) ); 175 foreach ( $wp_filter['post_class']->callbacks as $priority => $callbacks ) { 176 foreach ( $callbacks as $callback ) { 177 $file = self::callback_file( $callback['function'] ); 178 foreach ( $dirs as $dir ) { 179 if ( $file && 0 === strpos( $file, $dir ) ) { 180 $removed[] = array( $callback['function'], $priority, $callback['accepted_args'] ); 181 break; 182 } 183 } 184 } 185 } 186 } 187 foreach ( $removed as $filter ) { 188 remove_filter( 'post_class', $filter[0], $filter[1] ); 189 } 190 $classes = get_post_class( $class ); 191 foreach ( $removed as $filter ) { 192 add_filter( 'post_class', $filter[0], $filter[1], $filter[2] ); 193 } 194 return $classes; 195 } 196 197 /** 198 * File that defines a callback ('' when unknown). 199 */ 200 private static function callback_file( $callback ) { 201 try { 202 if ( is_string( $callback ) && false !== strpos( $callback, '::' ) ) { 203 $callback = explode( '::', $callback, 2 ); 204 } 205 if ( is_array( $callback ) && 2 === count( $callback ) ) { 206 $reflection = new \ReflectionMethod( $callback[0], $callback[1] ); 207 } elseif ( $callback instanceof \Closure || ( is_string( $callback ) && function_exists( $callback ) ) ) { 208 $reflection = new \ReflectionFunction( $callback ); 209 } else { 210 return ''; 211 } 212 return wp_normalize_path( (string) $reflection->getFileName() ); 213 } catch ( \ReflectionException $e ) { 214 return ''; 215 } 216 } 217 162 218 public static function render_template( $id ) { 163 219 $id = (int) $id; -
theme-builder-for-elementor/tags/2.0.1/includes/render/class-theme-support.php
r3783780 r3789508 4 4 * 5 5 * Classic themes: on get_header / get_footer the plugin prints its own header (with wp_head) or footer (with 6 * wp_footer) and loads the theme's header.php / footer.php into a buffer that is thrown away. 6 * wp_footer) and loads the theme's header.php / footer.php into a buffer that is thrown away. On pages the theme 7 * renders itself, the content wrappers that header.php leaves open are printed again after the plugin's header and 8 * closed before its footer, so the theme's content keeps its container. 7 9 * Block themes: the header and footer template parts are replaced, and the plugin's page templates print the whole 8 10 * document themselves. … … 19 21 class Theme_Support { 20 22 23 /** @var bool The page is rendered by a page template of the plugin (page_start()). */ 24 private static $plugin_page = false; 25 26 /** @var array[] Content wrappers of the theme reopened after the plugin's header: tag, html. */ 27 private static $wrappers = array(); 28 21 29 public static function init() { 22 30 add_action( 'get_header', array( __CLASS__, 'replace_header' ), 99 ); … … 33 41 return; 34 42 } 43 self::remove_theme_part( 'header' ); 35 44 require TBFE_PATH . 'templates/parts/header.php'; 36 45 … … 44 53 ob_start(); 45 54 locate_template( $templates, true ); 46 ob_end_clean(); 55 $html = ob_get_clean(); 56 57 // Pages the theme renders itself (no page template of the plugin): its content wrappers stay. 58 if ( ! self::$plugin_page ) { 59 self::$wrappers = self::content_wrappers( $html ); 60 foreach ( self::$wrappers as $wrapper ) { 61 echo $wrapper['html']; // phpcs:ignore WordPress.Security.EscapeOutput.OutputNotEscaped -- opening tag printed by the theme. 62 } 63 } 47 64 } 48 65 … … 51 68 return; 52 69 } 70 self::remove_theme_part( 'footer' ); 71 foreach ( array_reverse( self::$wrappers ) as $wrapper ) { 72 printf( '</%s>', esc_html( $wrapper['tag'] ) ); 73 } 74 self::$wrappers = array(); 53 75 require TBFE_PATH . 'templates/parts/footer.php'; 54 76 … … 63 85 locate_template( $templates, true ); 64 86 ob_end_clean(); 87 } 88 89 /** 90 * Elements that the theme's header.php leaves open after its header (Astra: #content.site-content > 91 * .ast-container, Twenty Twenty-One: #content > #primary > main…) and closes in footer.php. Wrappers around the 92 * theme's header (#page) are left out, the plugin's header is not inside them on any page. 93 * 94 * @param string $html Output of header.php. 95 * @return array[] tag, html (opening tag), outermost first. 96 */ 97 public static function content_wrappers( $html ) { 98 if ( ! class_exists( 'WP_HTML_Tag_Processor' ) || false === stripos( $html, '<body' ) ) { 99 return array(); 100 } 101 $void = array( 'AREA', 'BASE', 'BR', 'COL', 'EMBED', 'HR', 'IMG', 'INPUT', 'LINK', 'META', 'SOURCE', 'TRACK', 'WBR' ); 102 $processor = new \WP_HTML_Tag_Processor( $html ); 103 $stack = array(); 104 $in_body = false; 105 $boundary = null; // Depth of the parent of the theme's header. 106 107 while ( $processor->next_tag( array( 'tag_closers' => 'visit' ) ) ) { 108 $tag = $processor->get_tag(); 109 if ( ! $in_body ) { 110 $in_body = 'BODY' === $tag && ! $processor->is_tag_closer(); 111 continue; 112 } 113 if ( $processor->is_tag_closer() ) { 114 // Closes the last element with that tag (and the ones left open inside it, like svg paths). 115 for ( $i = count( $stack ) - 1; $i >= 0 && $stack[ $i ]['tag'] !== $tag; $i-- ) { 116 } 117 if ( $i < 0 ) { 118 continue; 119 } 120 $element = $stack[ $i ]; 121 $stack = array_slice( $stack, 0, $i ); 122 if ( $element['header'] && ( null === $boundary || $i < $boundary ) ) { 123 $boundary = $i; 124 } 125 continue; 126 } 127 if ( in_array( $tag, $void, true ) || in_array( $tag, array( 'BODY', 'HTML' ), true ) ) { 128 continue; 129 } 130 131 $attributes = ''; 132 foreach ( (array) $processor->get_attribute_names_with_prefix( '' ) as $name ) { 133 $value = $processor->get_attribute( $name ); 134 $attributes .= true === $value ? ' ' . $name : sprintf( ' %s="%s"', $name, esc_attr( $value ) ); 135 } 136 $id = (string) $processor->get_attribute( 'id' ); 137 $class = ' ' . $processor->get_attribute( 'class' ) . ' '; 138 $stack[] = array( 139 'tag' => $tag, 140 'html' => sprintf( '<%s%s>', strtolower( $tag ), $attributes ), 141 'header' => 'HEADER' === $tag || in_array( $id, array( 'masthead', 'site-header', 'header' ), true ) || false !== strpos( $class, ' site-header ' ), 142 ); 143 } 144 145 $wrappers = array_slice( $stack, (int) $boundary ); 146 foreach ( $wrappers as &$wrapper ) { 147 $wrapper['tag'] = strtolower( $wrapper['tag'] ); 148 unset( $wrapper['header'] ); 149 } 150 unset( $wrapper ); 151 152 /** 153 * Filters the content wrappers of the theme reopened after the plugin's header on pages the theme renders. 154 * 155 * @param array[] $wrappers array( array( 'tag' => 'div', 'html' => '<div id="content">' ), … ). 156 * @param string $html Output of the theme's header.php. 157 */ 158 return (array) apply_filters( 'tbfe/theme_support/content_wrappers', $wrappers, $html ); 159 } 160 161 /** 162 * Classic themes that print their header on wp_body_open or their footer on wp_footer (not in header.php / 163 * footer.php), like the Envo themes: those callbacks are removed while the plugin's header or footer is shown 164 * and on canvas pages. 165 */ 166 public static function remove_theme_part( $location ) { 167 $prefix = str_replace( '-', '_', get_template() ); 168 $parts = array( 169 'header' => array( array( 'wp_body_open', $prefix . '_body_header_code' ) ), 170 'footer' => array( array( 'wp_footer', $prefix . '_wp_footer_code' ) ), 171 ); 172 173 /** 174 * Filters the callbacks of the theme that print its header or footer outside header.php / footer.php. 175 * 176 * @param array $callbacks array( array( hook, callback ), … ). 177 * @param string $location header or footer. 178 */ 179 $callbacks = apply_filters( 'tbfe/theme_support/theme_part_callbacks', $parts[ $location ], $location ); 180 181 foreach ( (array) $callbacks as $callback ) { 182 list( $hook, $function ) = $callback; 183 $priority = has_action( $hook, $function ); 184 if ( false !== $priority ) { 185 remove_action( $hook, $function, $priority ); 186 } 187 } 65 188 } 66 189 … … 123 246 */ 124 247 public static function page_start() { 248 self::$plugin_page = true; 125 249 if ( ! self::is_block_theme() ) { 126 250 get_header(); -
theme-builder-for-elementor/tags/2.0.1/readme.txt
r3783817 r3789508 5 5 Tested up to: 7.1 6 6 Requires PHP: 7.4 7 Stable tag: 2.0. 07 Stable tag: 2.0.1 8 8 License: GPLv2 or later 9 9 License URI: https://www.gnu.org/licenses/gpl-2.0.html … … 139 139 == Changelog == 140 140 141 = 2.0.1 = 142 * Fix: after a Websites Import the buttons in sliders, section templates and post cards link to your site, not to the demo site. 143 * Fix: the Breadcrumbs widget uses the breadcrumbs of Yoast SEO or Rank Math only when they are switched on there, otherwise its own trail. 144 * Fix: Single and Archive templates for the blog are no longer used for WooCommerce products, the shop and product categories. 145 * Fix: themes that print their own header or footer through hooks (e.g. Envo One) no longer show it next to the header or footer of the plugin. 146 * Fix: header, footer and content of the plugin are no longer changed by theme styles (e.g. Royal Elementor Kit, PopularFX). 147 * Fix: on pages the theme renders, its content container is kept with the header and footer of the plugin. 148 * Fix: post cards of the Posts widget are no longer boxed again by the theme (e.g. Astra). 149 141 150 = 2.0.0 = 142 151 * New: completely rewritten plugin with a new administration. -
theme-builder-for-elementor/tags/2.0.1/templates/archive.php
r3783780 r3789508 37 37 the_post(); 38 38 ?> 39 <article id="post-<?php the_ID(); ?>" <?php post_class( 'tbfe-archive__item' ); ?>>39 <article id="post-<?php the_ID(); ?>" class="<?php echo esc_attr( implode( ' ', Renderer::post_class( 'tbfe-archive__item' ) ) ); ?>"> 40 40 <?php Renderer::render_template( $tbfe_id ); ?> 41 41 </article> -
theme-builder-for-elementor/tags/2.0.1/templates/canvas.php
r3783780 r3789508 8 8 9 9 defined( 'ABSPATH' ) || exit; 10 11 // No header and footer of the theme either. 12 TBFE\Render\Theme_Support::remove_theme_part( 'header' ); 13 TBFE\Render\Theme_Support::remove_theme_part( 'footer' ); 10 14 11 15 require __DIR__ . '/parts/document-start.php'; -
theme-builder-for-elementor/tags/2.0.1/templates/full-width.php
r3783780 r3789508 7 7 */ 8 8 9 use TBFE\Render\Renderer; 9 10 use TBFE\Render\Theme_Support; 10 11 … … 18 19 the_post(); 19 20 ?> 20 <div <?php post_class( 'tbfe-page' ); ?>>21 <div class="<?php echo esc_attr( implode( ' ', Renderer::post_class( 'tbfe-page' ) ) ); ?>"> 21 22 <?php the_content(); ?> 22 23 </div> -
theme-builder-for-elementor/tags/2.0.1/templates/single.php
r3783780 r3789508 22 22 } 23 23 ?> 24 <article id="post-<?php the_ID(); ?>" <?php post_class( 'tbfe-single' ); ?>>24 <article id="post-<?php the_ID(); ?>" class="<?php echo esc_attr( implode( ' ', Renderer::post_class( 'tbfe-single' ) ) ); ?>"> 25 25 <?php Renderer::render_location( 'single' ); ?> 26 26 </article> -
theme-builder-for-elementor/tags/2.0.1/theme-builder-for-elementor.php
r3783780 r3789508 4 4 * Plugin URI: https://blocks-wp.com/theme-builder-for-elementor/ 5 5 * Description: Build the header, footer, single posts and pages, archives and the 404 page of any theme with the free Elementor. 6 * Version: 2.0. 06 * Version: 2.0.1 7 7 * Requires at least: 6.5 8 8 * Requires PHP: 7.4 … … 20 20 defined( 'ABSPATH' ) || exit; 21 21 22 define( 'TBFE_VERSION', '2.0. 0' );22 define( 'TBFE_VERSION', '2.0.1' ); 23 23 define( 'TBFE_FILE', __FILE__ ); 24 24 define( 'TBFE_PATH', plugin_dir_path( __FILE__ ) ); -
theme-builder-for-elementor/trunk/assets/css/frontend.css
r3783780 r3789508 8 8 .tbfe-location-404, 9 9 .tbfe-location-content { display: block; width: 100%; } 10 11 /* Themes style their own #site-header, #site-footer, #content and main (flex rows, paddings, floats of a sidebar 12 layout); the elements of the plugin carry the same ids, so these rules beat the theme's. Position and background 13 stay free for the sticky and transparent header. */ 14 #site-header.tbfe-location, 15 #site-footer.tbfe-location { display: block; float: none; clear: both; box-sizing: border-box; width: 100%; max-width: none; height: auto; min-height: 0; margin: 0; padding: 0; border: 0; } 16 17 #content.tbfe-location, 18 main.tbfe-location { float: none; clear: both; box-sizing: border-box; width: 100%; max-width: none; } 10 19 11 20 .tbfe-container, -
theme-builder-for-elementor/trunk/assets/css/frontend.min.css
r3783780 r3789508 1 .tbfe-location-404,.tbfe-location-archive,.tbfe-location-content,.tbfe-location-footer,.tbfe-location-header,.tbfe-location-single{display:block;width:100%} .tbfe-archive--boxed,.tbfe-container{box-sizing:border-box;width:100%;max-width:var(--tbfe-container, 1140px);margin-right:auto;margin-left:auto;padding-right:20px;padding-left:20px}.tbfe-archive{display:grid;grid-template-columns:minmax(0,1fr);gap:40px;padding-top:40px;padding-bottom:40px}.tbfe-archive--full{padding-right:20px;padding-left:20px}.tbfe-archive--sidebar{grid-template-columns:minmax(0,3fr) minmax(0,1fr)}.tbfe-archive__posts{display:flex;flex-direction:column;gap:30px;min-width:0}.tbfe-archive__item{margin:0}.tbfe-archive__sidebar{min-width:0}@media (max-width:767px){.tbfe-archive--sidebar{grid-template-columns:minmax(0,1fr)}}.tbfe-password{padding-top:40px;padding-bottom:40px}.tbfe-header--sticky,.tbfe-header--transparent{z-index:990;transition:background-color .3s ease,box-shadow .3s ease,transform .3s ease}.tbfe-header--sticky{position:sticky;top:var(--wp-admin--admin-bar--height, 0px)}.tbfe-header--transparent{position:absolute;top:var(--wp-admin--admin-bar--height, 0px);right:0;left:0;background-color:transparent}.tbfe-header--transparent.tbfe-header--sticky{position:fixed}.tbfe-header--sticky.is-scrolled{background-color:var(--tbfe-scrolled-bg, transparent)}.tbfe-header--shadow.is-scrolled{box-shadow:0 6px 24px rgba(15,23,42,.1)}.tbfe-header--hide.is-hidden{transform:translateY(-110%)}.tbfe-header--shrink .elementor-element-populated,.tbfe-header--shrink .elementor>.e-con,.tbfe-header--shrink .elementor>.elementor-section,.tbfe-header--shrink .tbfe-site-logo img{transition:padding .3s ease,min-height .3s ease,max-height .3s ease}.tbfe-header--shrink.is-scrolled .elementor>.e-con,.tbfe-header--shrink.is-scrolled .elementor>.elementor-section{padding-top:4px!important;padding-bottom:4px!important}.tbfe-header--shrink.is-scrolled .elementor-element-populated{padding-top:2px!important;padding-bottom:2px!important}.tbfe-header--shrink.is-scrolled .elementor-container{min-height:0!important}.tbfe-header--shrink.is-scrolled .tbfe-site-logo img{width:auto!important;max-height:var(--tbfe-shrink-logo, 36px)}@media (max-width:600px){.tbfe-header--sticky,.tbfe-header--transparent{top:0}}@media (max-width:1024px){.tbfe-header--transparent.tbfe-transparent-desktop.tbfe-header--sticky{position:sticky;top:0}.tbfe-header--transparent.tbfe-transparent-desktop,.tbfe-location-header.tbfe-header--sticky.tbfe-sticky-desktop{position:relative;top:auto}.tbfe-location-header.tbfe-header--transparent.tbfe-sticky-desktop:not(.tbfe-transparent-desktop){position:absolute;top:0}}@media (max-width:767px){.tbfe-header--transparent.tbfe-transparent-desktop-tablet.tbfe-header--sticky{position:sticky;top:0}.tbfe-header--transparent.tbfe-transparent-desktop-tablet,.tbfe-location-header.tbfe-header--sticky.tbfe-sticky-desktop-tablet{position:relative;top:auto}.tbfe-location-header.tbfe-header--transparent.tbfe-sticky-desktop-tablet.tbfe-transparent-all{position:absolute;top:0}}1 .tbfe-location-404,.tbfe-location-archive,.tbfe-location-content,.tbfe-location-footer,.tbfe-location-header,.tbfe-location-single{display:block;width:100%}#site-footer.tbfe-location,#site-header.tbfe-location{display:block;height:auto;min-height:0;margin:0;padding:0;border:0}#content.tbfe-location,#site-footer.tbfe-location,#site-header.tbfe-location,main.tbfe-location{float:none;clear:both;box-sizing:border-box;width:100%;max-width:none}.tbfe-archive--boxed,.tbfe-container{box-sizing:border-box;width:100%;max-width:var(--tbfe-container, 1140px);margin-right:auto;margin-left:auto;padding-right:20px;padding-left:20px}.tbfe-archive{display:grid;grid-template-columns:minmax(0,1fr);gap:40px;padding-top:40px;padding-bottom:40px}.tbfe-archive--full{padding-right:20px;padding-left:20px}.tbfe-archive--sidebar{grid-template-columns:minmax(0,3fr) minmax(0,1fr)}.tbfe-archive__posts{display:flex;flex-direction:column;gap:30px;min-width:0}.tbfe-archive__item{margin:0}.tbfe-archive__sidebar{min-width:0}@media (max-width:767px){.tbfe-archive--sidebar{grid-template-columns:minmax(0,1fr)}}.tbfe-password{padding-top:40px;padding-bottom:40px}.tbfe-header--sticky,.tbfe-header--transparent{z-index:990;transition:background-color .3s ease,box-shadow .3s ease,transform .3s ease}.tbfe-header--sticky{position:sticky;top:var(--wp-admin--admin-bar--height, 0px)}.tbfe-header--transparent{position:absolute;top:var(--wp-admin--admin-bar--height, 0px);right:0;left:0;background-color:transparent}.tbfe-header--transparent.tbfe-header--sticky{position:fixed}.tbfe-header--sticky.is-scrolled{background-color:var(--tbfe-scrolled-bg, transparent)}.tbfe-header--shadow.is-scrolled{box-shadow:0 6px 24px rgba(15,23,42,.1)}.tbfe-header--hide.is-hidden{transform:translateY(-110%)}.tbfe-header--shrink .elementor-element-populated,.tbfe-header--shrink .elementor>.e-con,.tbfe-header--shrink .elementor>.elementor-section,.tbfe-header--shrink .tbfe-site-logo img{transition:padding .3s ease,min-height .3s ease,max-height .3s ease}.tbfe-header--shrink.is-scrolled .elementor>.e-con,.tbfe-header--shrink.is-scrolled .elementor>.elementor-section{padding-top:4px!important;padding-bottom:4px!important}.tbfe-header--shrink.is-scrolled .elementor-element-populated{padding-top:2px!important;padding-bottom:2px!important}.tbfe-header--shrink.is-scrolled .elementor-container{min-height:0!important}.tbfe-header--shrink.is-scrolled .tbfe-site-logo img{width:auto!important;max-height:var(--tbfe-shrink-logo, 36px)}@media (max-width:600px){.tbfe-header--sticky,.tbfe-header--transparent{top:0}}@media (max-width:1024px){.tbfe-header--transparent.tbfe-transparent-desktop.tbfe-header--sticky{position:sticky;top:0}.tbfe-header--transparent.tbfe-transparent-desktop,.tbfe-location-header.tbfe-header--sticky.tbfe-sticky-desktop{position:relative;top:auto}.tbfe-location-header.tbfe-header--transparent.tbfe-sticky-desktop:not(.tbfe-transparent-desktop){position:absolute;top:0}}@media (max-width:767px){.tbfe-header--transparent.tbfe-transparent-desktop-tablet.tbfe-header--sticky{position:sticky;top:0}.tbfe-header--transparent.tbfe-transparent-desktop-tablet,.tbfe-location-header.tbfe-header--sticky.tbfe-sticky-desktop-tablet{position:relative;top:auto}.tbfe-location-header.tbfe-header--transparent.tbfe-sticky-desktop-tablet.tbfe-transparent-all{position:absolute;top:0}} -
theme-builder-for-elementor/trunk/includes/conditions/class-resolver.php
r3783780 r3789508 132 132 } 133 133 134 // Products and the shop of WooCommerce: All singular / All archives of a blog Single or Archive template do 135 // not count there. The blog layout would take the add to cart and the shop loop away; the theme's shop (or the 136 // product templates of PRO) stay, unless a condition chooses them, like Products. 137 $shop = in_array( $location, array( 'single', 'archive' ), true ) && function_exists( 'is_woocommerce' ) && is_woocommerce(); 138 134 139 $best = 0; 135 140 $best_score = -1; 136 141 foreach ( $index[ $location ] as $id => $rules ) { 142 if ( $shop && in_array( Template::type( $id ), array( 'single', 'archive' ), true ) ) { 143 $rules = array_filter( 144 $rules, 145 static function ( $rule ) { 146 return 'exclude' === $rule['type'] || ! in_array( $rule['name'], array( 'singular', 'archive' ), true ); 147 } 148 ); 149 } 137 150 $score = self::rules_score( $rules ); 138 151 if ( $score > $best_score ) { -
theme-builder-for-elementor/trunk/includes/elementor/widgets/class-breadcrumbs.php
r3783780 r3789508 162 162 } 163 163 164 /** 165 * Breadcrumbs of Yoast SEO or Rank Math, only when their breadcrumbs are switched on. 166 * Empty string otherwise, so the built-in trail is used. 167 */ 168 private function seo_plugin_trail() { 169 if ( function_exists( 'yoast_breadcrumb' ) ) { 170 $enabled = current_theme_supports( 'yoast-seo-breadcrumbs' ) 171 || ( class_exists( 'WPSEO_Options' ) && \WPSEO_Options::get( 'breadcrumbs-enable', false ) ); 172 if ( $enabled ) { 173 $html = (string) yoast_breadcrumb( '', '', false ); 174 if ( '' !== trim( wp_strip_all_tags( $html ) ) ) { 175 return $html; 176 } 177 } 178 } 179 if ( function_exists( 'rank_math_get_breadcrumbs' ) ) { 180 $enabled = method_exists( '\RankMath\Helper', 'is_breadcrumbs_enabled' ) 181 ? \RankMath\Helper::is_breadcrumbs_enabled() 182 : current_theme_supports( 'rank-math-breadcrumbs' ); 183 if ( $enabled ) { 184 $html = (string) rank_math_get_breadcrumbs(); 185 if ( '' !== trim( wp_strip_all_tags( $html ) ) ) { 186 return $html; 187 } 188 } 189 } 190 return ''; 191 } 192 164 193 protected function render() { 165 194 $settings = $this->get_settings_for_display(); 166 195 167 196 if ( 'auto' === $settings['source'] && ! Context::is_template_preview() ) { 168 if ( function_exists( 'yoast_breadcrumb' ) ) { 169 yoast_breadcrumb( '<nav class="tbfe-breadcrumbs" aria-label="' . esc_attr__( 'Breadcrumbs', 'theme-builder-for-elementor' ) . '">', '</nav>' ); 170 return; 171 } 172 if ( function_exists( 'rank_math_the_breadcrumbs' ) ) { 173 echo '<nav class="tbfe-breadcrumbs" aria-label="' . esc_attr__( 'Breadcrumbs', 'theme-builder-for-elementor' ) . '">'; 174 rank_math_the_breadcrumbs(); 175 echo '</nav>'; 197 $seo = $this->seo_plugin_trail(); 198 if ( '' !== $seo ) { 199 echo '<nav class="tbfe-breadcrumbs" aria-label="' . esc_attr__( 'Breadcrumbs', 'theme-builder-for-elementor' ) . '">' . wp_kses_post( $seo ) . '</nav>'; 176 200 return; 177 201 } -
theme-builder-for-elementor/trunk/includes/elementor/widgets/class-posts.php
r3783780 r3789508 575 575 while ( $query->have_posts() ) { 576 576 $query->the_post(); 577 echo '<article class="' . esc_attr( implode( ' ', get_post_class( 'tbfe-posts__item' ) ) ) . '">';577 echo '<article class="' . esc_attr( implode( ' ', Renderer::post_class( 'tbfe-posts__item' ) ) ) . '">'; 578 578 if ( $template ) { 579 579 Renderer::render_template( $template ); -
theme-builder-for-elementor/trunk/includes/library/class-library.php
r3783780 r3789508 475 475 } 476 476 477 $posts = array_merge( wp_list_pluck( $pages, 'id' ), $templates ); 478 foreach ( $posts as $post_id ) { 479 $document = \Elementor\Plugin::$instance->documents->get( (int) $post_id, false ); 477 $posts = array_map( 'absint', array_merge( wp_list_pluck( $pages, 'id' ), $templates ) ); 478 $next = 0; 479 while ( $next < count( $posts ) ) { 480 $post_id = $posts[ $next++ ]; 481 $document = \Elementor\Plugin::$instance->documents->get( $post_id, false ); 480 482 if ( ! $document ) { 481 483 continue; 482 484 } 483 485 $elements = $document->get_elements_data(); 484 $changed = false; 486 // Templates imported with the content (slides of a Slider, Section templates, Post Cards) get their links 487 // updated too. 488 foreach ( References::ids( $elements ) as $ref ) { 489 if ( ! in_array( $ref, $posts, true ) && Template::is_template( $ref ) && get_post_meta( $ref, '_tbfe_library_item', true ) ) { 490 $posts[] = $ref; 491 } 492 } 493 $changed = false; 485 494 $elements = self::walk( 486 495 $elements, -
theme-builder-for-elementor/trunk/includes/library/class-references.php
r3783780 r3789508 49 49 } 50 50 return $elements; 51 } 52 53 /** 54 * Templates of this site that Elementor content refers to (Post Card, Section Template, slides of a Slider). 55 * 56 * @return int[] 57 */ 58 public static function ids( array $elements ) { 59 $ids = array(); 60 foreach ( $elements as $element ) { 61 if ( ! is_array( $element ) ) { 62 continue; 63 } 64 $type = isset( $element['widgetType'] ) ? $element['widgetType'] : ''; 65 $settings = isset( $element['settings'] ) && is_array( $element['settings'] ) ? $element['settings'] : array(); 66 if ( 'tbfe-posts' === $type && ! empty( $settings['card_template'] ) ) { 67 $ids[] = absint( $settings['card_template'] ); 68 } elseif ( 'tbfe-template' === $type && ! empty( $settings['template_id'] ) ) { 69 $ids[] = absint( $settings['template_id'] ); 70 } elseif ( 'tbfe-slider' === $type && ! empty( $settings['slides'] ) && is_array( $settings['slides'] ) ) { 71 foreach ( $settings['slides'] as $slide ) { 72 if ( ! empty( $slide['template_id'] ) ) { 73 $ids[] = absint( $slide['template_id'] ); 74 } 75 } 76 } 77 if ( ! empty( $element['elements'] ) && is_array( $element['elements'] ) ) { 78 $ids = array_merge( $ids, self::ids( $element['elements'] ) ); 79 } 80 } 81 return array_values( array_unique( array_filter( $ids ) ) ); 51 82 } 52 83 -
theme-builder-for-elementor/trunk/includes/render/class-renderer.php
r3783780 r3789508 160 160 * @param int $id Template ID. 161 161 */ 162 /** 163 * Classes of the post element in the plugin's layouts: get_post_class() without the post_class filters of the 164 * theme. Themes add their own card and grid classes there (Astra: ast-article-post, ast-grid-common-col) and 165 * style them as boxes, which put a theme box around the cards of the Posts widget. Plugins (WooCommerce) stay. 166 * 167 * @param string $class Own class. 168 * @return string[] 169 */ 170 public static function post_class( $class = '' ) { 171 global $wp_filter; 172 $removed = array(); 173 if ( isset( $wp_filter['post_class'] ) ) { 174 $dirs = array_unique( array( wp_normalize_path( get_template_directory() ) . '/', wp_normalize_path( get_stylesheet_directory() ) . '/' ) ); 175 foreach ( $wp_filter['post_class']->callbacks as $priority => $callbacks ) { 176 foreach ( $callbacks as $callback ) { 177 $file = self::callback_file( $callback['function'] ); 178 foreach ( $dirs as $dir ) { 179 if ( $file && 0 === strpos( $file, $dir ) ) { 180 $removed[] = array( $callback['function'], $priority, $callback['accepted_args'] ); 181 break; 182 } 183 } 184 } 185 } 186 } 187 foreach ( $removed as $filter ) { 188 remove_filter( 'post_class', $filter[0], $filter[1] ); 189 } 190 $classes = get_post_class( $class ); 191 foreach ( $removed as $filter ) { 192 add_filter( 'post_class', $filter[0], $filter[1], $filter[2] ); 193 } 194 return $classes; 195 } 196 197 /** 198 * File that defines a callback ('' when unknown). 199 */ 200 private static function callback_file( $callback ) { 201 try { 202 if ( is_string( $callback ) && false !== strpos( $callback, '::' ) ) { 203 $callback = explode( '::', $callback, 2 ); 204 } 205 if ( is_array( $callback ) && 2 === count( $callback ) ) { 206 $reflection = new \ReflectionMethod( $callback[0], $callback[1] ); 207 } elseif ( $callback instanceof \Closure || ( is_string( $callback ) && function_exists( $callback ) ) ) { 208 $reflection = new \ReflectionFunction( $callback ); 209 } else { 210 return ''; 211 } 212 return wp_normalize_path( (string) $reflection->getFileName() ); 213 } catch ( \ReflectionException $e ) { 214 return ''; 215 } 216 } 217 162 218 public static function render_template( $id ) { 163 219 $id = (int) $id; -
theme-builder-for-elementor/trunk/includes/render/class-theme-support.php
r3783780 r3789508 4 4 * 5 5 * Classic themes: on get_header / get_footer the plugin prints its own header (with wp_head) or footer (with 6 * wp_footer) and loads the theme's header.php / footer.php into a buffer that is thrown away. 6 * wp_footer) and loads the theme's header.php / footer.php into a buffer that is thrown away. On pages the theme 7 * renders itself, the content wrappers that header.php leaves open are printed again after the plugin's header and 8 * closed before its footer, so the theme's content keeps its container. 7 9 * Block themes: the header and footer template parts are replaced, and the plugin's page templates print the whole 8 10 * document themselves. … … 19 21 class Theme_Support { 20 22 23 /** @var bool The page is rendered by a page template of the plugin (page_start()). */ 24 private static $plugin_page = false; 25 26 /** @var array[] Content wrappers of the theme reopened after the plugin's header: tag, html. */ 27 private static $wrappers = array(); 28 21 29 public static function init() { 22 30 add_action( 'get_header', array( __CLASS__, 'replace_header' ), 99 ); … … 33 41 return; 34 42 } 43 self::remove_theme_part( 'header' ); 35 44 require TBFE_PATH . 'templates/parts/header.php'; 36 45 … … 44 53 ob_start(); 45 54 locate_template( $templates, true ); 46 ob_end_clean(); 55 $html = ob_get_clean(); 56 57 // Pages the theme renders itself (no page template of the plugin): its content wrappers stay. 58 if ( ! self::$plugin_page ) { 59 self::$wrappers = self::content_wrappers( $html ); 60 foreach ( self::$wrappers as $wrapper ) { 61 echo $wrapper['html']; // phpcs:ignore WordPress.Security.EscapeOutput.OutputNotEscaped -- opening tag printed by the theme. 62 } 63 } 47 64 } 48 65 … … 51 68 return; 52 69 } 70 self::remove_theme_part( 'footer' ); 71 foreach ( array_reverse( self::$wrappers ) as $wrapper ) { 72 printf( '</%s>', esc_html( $wrapper['tag'] ) ); 73 } 74 self::$wrappers = array(); 53 75 require TBFE_PATH . 'templates/parts/footer.php'; 54 76 … … 63 85 locate_template( $templates, true ); 64 86 ob_end_clean(); 87 } 88 89 /** 90 * Elements that the theme's header.php leaves open after its header (Astra: #content.site-content > 91 * .ast-container, Twenty Twenty-One: #content > #primary > main…) and closes in footer.php. Wrappers around the 92 * theme's header (#page) are left out, the plugin's header is not inside them on any page. 93 * 94 * @param string $html Output of header.php. 95 * @return array[] tag, html (opening tag), outermost first. 96 */ 97 public static function content_wrappers( $html ) { 98 if ( ! class_exists( 'WP_HTML_Tag_Processor' ) || false === stripos( $html, '<body' ) ) { 99 return array(); 100 } 101 $void = array( 'AREA', 'BASE', 'BR', 'COL', 'EMBED', 'HR', 'IMG', 'INPUT', 'LINK', 'META', 'SOURCE', 'TRACK', 'WBR' ); 102 $processor = new \WP_HTML_Tag_Processor( $html ); 103 $stack = array(); 104 $in_body = false; 105 $boundary = null; // Depth of the parent of the theme's header. 106 107 while ( $processor->next_tag( array( 'tag_closers' => 'visit' ) ) ) { 108 $tag = $processor->get_tag(); 109 if ( ! $in_body ) { 110 $in_body = 'BODY' === $tag && ! $processor->is_tag_closer(); 111 continue; 112 } 113 if ( $processor->is_tag_closer() ) { 114 // Closes the last element with that tag (and the ones left open inside it, like svg paths). 115 for ( $i = count( $stack ) - 1; $i >= 0 && $stack[ $i ]['tag'] !== $tag; $i-- ) { 116 } 117 if ( $i < 0 ) { 118 continue; 119 } 120 $element = $stack[ $i ]; 121 $stack = array_slice( $stack, 0, $i ); 122 if ( $element['header'] && ( null === $boundary || $i < $boundary ) ) { 123 $boundary = $i; 124 } 125 continue; 126 } 127 if ( in_array( $tag, $void, true ) || in_array( $tag, array( 'BODY', 'HTML' ), true ) ) { 128 continue; 129 } 130 131 $attributes = ''; 132 foreach ( (array) $processor->get_attribute_names_with_prefix( '' ) as $name ) { 133 $value = $processor->get_attribute( $name ); 134 $attributes .= true === $value ? ' ' . $name : sprintf( ' %s="%s"', $name, esc_attr( $value ) ); 135 } 136 $id = (string) $processor->get_attribute( 'id' ); 137 $class = ' ' . $processor->get_attribute( 'class' ) . ' '; 138 $stack[] = array( 139 'tag' => $tag, 140 'html' => sprintf( '<%s%s>', strtolower( $tag ), $attributes ), 141 'header' => 'HEADER' === $tag || in_array( $id, array( 'masthead', 'site-header', 'header' ), true ) || false !== strpos( $class, ' site-header ' ), 142 ); 143 } 144 145 $wrappers = array_slice( $stack, (int) $boundary ); 146 foreach ( $wrappers as &$wrapper ) { 147 $wrapper['tag'] = strtolower( $wrapper['tag'] ); 148 unset( $wrapper['header'] ); 149 } 150 unset( $wrapper ); 151 152 /** 153 * Filters the content wrappers of the theme reopened after the plugin's header on pages the theme renders. 154 * 155 * @param array[] $wrappers array( array( 'tag' => 'div', 'html' => '<div id="content">' ), … ). 156 * @param string $html Output of the theme's header.php. 157 */ 158 return (array) apply_filters( 'tbfe/theme_support/content_wrappers', $wrappers, $html ); 159 } 160 161 /** 162 * Classic themes that print their header on wp_body_open or their footer on wp_footer (not in header.php / 163 * footer.php), like the Envo themes: those callbacks are removed while the plugin's header or footer is shown 164 * and on canvas pages. 165 */ 166 public static function remove_theme_part( $location ) { 167 $prefix = str_replace( '-', '_', get_template() ); 168 $parts = array( 169 'header' => array( array( 'wp_body_open', $prefix . '_body_header_code' ) ), 170 'footer' => array( array( 'wp_footer', $prefix . '_wp_footer_code' ) ), 171 ); 172 173 /** 174 * Filters the callbacks of the theme that print its header or footer outside header.php / footer.php. 175 * 176 * @param array $callbacks array( array( hook, callback ), … ). 177 * @param string $location header or footer. 178 */ 179 $callbacks = apply_filters( 'tbfe/theme_support/theme_part_callbacks', $parts[ $location ], $location ); 180 181 foreach ( (array) $callbacks as $callback ) { 182 list( $hook, $function ) = $callback; 183 $priority = has_action( $hook, $function ); 184 if ( false !== $priority ) { 185 remove_action( $hook, $function, $priority ); 186 } 187 } 65 188 } 66 189 … … 123 246 */ 124 247 public static function page_start() { 248 self::$plugin_page = true; 125 249 if ( ! self::is_block_theme() ) { 126 250 get_header(); -
theme-builder-for-elementor/trunk/readme.txt
r3783817 r3789508 5 5 Tested up to: 7.1 6 6 Requires PHP: 7.4 7 Stable tag: 2.0. 07 Stable tag: 2.0.1 8 8 License: GPLv2 or later 9 9 License URI: https://www.gnu.org/licenses/gpl-2.0.html … … 139 139 == Changelog == 140 140 141 = 2.0.1 = 142 * Fix: after a Websites Import the buttons in sliders, section templates and post cards link to your site, not to the demo site. 143 * Fix: the Breadcrumbs widget uses the breadcrumbs of Yoast SEO or Rank Math only when they are switched on there, otherwise its own trail. 144 * Fix: Single and Archive templates for the blog are no longer used for WooCommerce products, the shop and product categories. 145 * Fix: themes that print their own header or footer through hooks (e.g. Envo One) no longer show it next to the header or footer of the plugin. 146 * Fix: header, footer and content of the plugin are no longer changed by theme styles (e.g. Royal Elementor Kit, PopularFX). 147 * Fix: on pages the theme renders, its content container is kept with the header and footer of the plugin. 148 * Fix: post cards of the Posts widget are no longer boxed again by the theme (e.g. Astra). 149 141 150 = 2.0.0 = 142 151 * New: completely rewritten plugin with a new administration. -
theme-builder-for-elementor/trunk/templates/archive.php
r3783780 r3789508 37 37 the_post(); 38 38 ?> 39 <article id="post-<?php the_ID(); ?>" <?php post_class( 'tbfe-archive__item' ); ?>>39 <article id="post-<?php the_ID(); ?>" class="<?php echo esc_attr( implode( ' ', Renderer::post_class( 'tbfe-archive__item' ) ) ); ?>"> 40 40 <?php Renderer::render_template( $tbfe_id ); ?> 41 41 </article> -
theme-builder-for-elementor/trunk/templates/canvas.php
r3783780 r3789508 8 8 9 9 defined( 'ABSPATH' ) || exit; 10 11 // No header and footer of the theme either. 12 TBFE\Render\Theme_Support::remove_theme_part( 'header' ); 13 TBFE\Render\Theme_Support::remove_theme_part( 'footer' ); 10 14 11 15 require __DIR__ . '/parts/document-start.php'; -
theme-builder-for-elementor/trunk/templates/full-width.php
r3783780 r3789508 7 7 */ 8 8 9 use TBFE\Render\Renderer; 9 10 use TBFE\Render\Theme_Support; 10 11 … … 18 19 the_post(); 19 20 ?> 20 <div <?php post_class( 'tbfe-page' ); ?>>21 <div class="<?php echo esc_attr( implode( ' ', Renderer::post_class( 'tbfe-page' ) ) ); ?>"> 21 22 <?php the_content(); ?> 22 23 </div> -
theme-builder-for-elementor/trunk/templates/single.php
r3783780 r3789508 22 22 } 23 23 ?> 24 <article id="post-<?php the_ID(); ?>" <?php post_class( 'tbfe-single' ); ?>>24 <article id="post-<?php the_ID(); ?>" class="<?php echo esc_attr( implode( ' ', Renderer::post_class( 'tbfe-single' ) ) ); ?>"> 25 25 <?php Renderer::render_location( 'single' ); ?> 26 26 </article> -
theme-builder-for-elementor/trunk/theme-builder-for-elementor.php
r3783780 r3789508 4 4 * Plugin URI: https://blocks-wp.com/theme-builder-for-elementor/ 5 5 * Description: Build the header, footer, single posts and pages, archives and the 404 page of any theme with the free Elementor. 6 * Version: 2.0. 06 * Version: 2.0.1 7 7 * Requires at least: 6.5 8 8 * Requires PHP: 7.4 … … 20 20 defined( 'ABSPATH' ) || exit; 21 21 22 define( 'TBFE_VERSION', '2.0. 0' );22 define( 'TBFE_VERSION', '2.0.1' ); 23 23 define( 'TBFE_FILE', __FILE__ ); 24 24 define( 'TBFE_PATH', plugin_dir_path( __FILE__ ) );
Note:
See TracChangeset
for help on using the changeset viewer.
![(please configure the [header_logo] section in trac.ini)](/chrome/site/your_project_logo.png)