<?php defined('ABSPATH') || exit; class WC_Template_Loader { private static $shop_page_id = 0; private static $in_content_filter = false; private static $theme_support = false; public static function init() { self::$theme_support = current_theme_supports('woocommerce'); self::$shop_page_id = wc_get_page_id('shop'); if (self::$theme_support) { add_filter('template_include', array(__CLASS__, 'template_loader')); add_filter('comments_template', array(__CLASS__, 'comments_template_loader')); } else { add_action('template_redirect', array(__CLASS__, 'unsupported_theme_init')); } } public static function template_loader($template) { if (is_embed()) { return $template; } $default_file = self::get_template_loader_default_file(); if ($default_file) { $search_files = self::get_template_loader_files($default_file); $template = locate_template($search_files); if (!$template || WC_TEMPLATE_DEBUG_MODE) { if (false !== strpos($default_file, 'product_cat') || false !== strpos($default_file, 'product_tag')) { $cs_template = str_replace('_', '-', $default_file); $template = WC()->plugin_path() . '/templates/' . $cs_template; } else { $template = WC()->plugin_path() . '/templates/' . $default_file; } } } return $template; } private static function has_block_template($template_name) { if (!$template_name) { return false; } return is_readable(get_stylesheet_directory() . '/block-templates/' . $template_name . '.html'); } private static function get_template_loader_default_file() { if (is_singular('product') && !self::has_block_template('single-product')) { $default_file = 'single-product.php'; } elseif (is_product_taxonomy()) { $object = get_queried_object(); if (is_tax('product_cat') || is_tax('product_tag')) { if (self::has_block_template('taxonomy-' . $object->taxonomy)) { $default_file = ''; } else { $default_file = 'taxonomy-' . $object->taxonomy . '.php'; } } elseif (!self::has_block_template('archive-product')) { $default_file = 'archive-product.php'; } } elseif ((is_post_type_archive('product') || is_page(wc_get_page_id('shop'))) && !self::has_block_template('archive-product')) { $default_file = self::$theme_support ? 'archive-product.php' : ''; } else { $default_file = ''; } return $default_file; } private static function get_template_loader_files($default_file) { $templates = apply_filters('woocommerce_template_loader_files', array(), $default_file); $templates[] = 'woocommerce.php'; if (is_page_template()) { $page_template = get_page_template_slug(); if ($page_template) { $validated_file = validate_file($page_template); if (0 === $validated_file) { $templates[] = $page_template; } else { error_log("WooCommerce: Unable to validate template path: \"{$page_template}\". Error Code: {$validated_file}."); } } } if (is_singular('product')) { $object = get_queried_object(); $name_decoded = urldecode($object->post_name); if ($name_decoded !== $object->post_name) { $templates[] = "single-product-{$name_decoded}.php"; } $templates[] = "single-product-{$object->post_name}.php"; } if (is_product_taxonomy()) { $object = get_queried_object(); $templates[] = 'taxonomy-' . $object->taxonomy . '-' . $object->slug . '.php'; $templates[] = WC()->template_path() . 'taxonomy-' . $object->taxonomy . '-' . $object->slug . '.php'; $templates[] = 'taxonomy-' . $object->taxonomy . '.php'; $templates[] = WC()->template_path() . 'taxonomy-' . $object->taxonomy . '.php'; if (is_tax('product_cat') || is_tax('product_tag')) { $cs_taxonomy = str_replace('_', '-', $object->taxonomy); $cs_default = str_replace('_', '-', $default_file); $templates[] = 'taxonomy-' . $object->taxonomy . '-' . $object->slug . '.php'; $templates[] = WC()->template_path() . 'taxonomy-' . $cs_taxonomy . '-' . $object->slug . '.php'; $templates[] = 'taxonomy-' . $object->taxonomy . '.php'; $templates[] = WC()->template_path() . 'taxonomy-' . $cs_taxonomy . '.php'; $templates[] = $cs_default; } } $templates[] = $default_file; if (isset($cs_default)) { $templates[] = WC()->template_path() . $cs_default; } $templates[] = WC()->template_path() . $default_file; return array_unique($templates); } public static function comments_template_loader($template) { if (get_post_type() !== 'product') { return $template; } $check_dirs = array(trailingslashit(get_stylesheet_directory()) . WC()->template_path(), trailingslashit(get_template_directory()) . WC()->template_path(), trailingslashit(get_stylesheet_directory()), trailingslashit(get_template_directory()), trailingslashit(WC()->plugin_path()) . 'templates/'); if (WC_TEMPLATE_DEBUG_MODE) { $check_dirs = array(array_pop($check_dirs)); } foreach ($check_dirs as $dir) { if (file_exists(trailingslashit($dir) . 'single-product-reviews.php')) { return trailingslashit($dir) . 'single-product-reviews.php'; } } } public static function unsupported_theme_init() { if (0 < self::$shop_page_id) { if (is_product_taxonomy()) { self::unsupported_theme_tax_archive_init(); } elseif (is_product()) { self::unsupported_theme_product_page_init(); } else { self::unsupported_theme_shop_page_init(); } } } private static function unsupported_theme_shop_page_init() { add_filter('the_content', array(__CLASS__, 'unsupported_theme_shop_content_filter'), 10); add_filter('the_title', array(__CLASS__, 'unsupported_theme_title_filter'), 10, 2); add_filter('comments_number', array(__CLASS__, 'unsupported_theme_comments_number_filter')); } private static function unsupported_theme_product_page_init() { add_filter('the_content', array(__CLASS__, 'unsupported_theme_product_content_filter'), 10); add_filter('post_thumbnail_html', array(__CLASS__, 'unsupported_theme_single_featured_image_filter')); add_filter('woocommerce_product_tabs', array(__CLASS__, 'unsupported_theme_remove_review_tab')); remove_action('woocommerce_before_main_content', 'woocommerce_output_content_wrapper', 10); remove_action('woocommerce_after_main_content', 'woocommerce_output_content_wrapper_end', 10); add_theme_support('wc-product-gallery-zoom'); add_theme_support('wc-product-gallery-lightbox'); add_theme_support('wc-product-gallery-slider'); } private static function unsupported_theme_tax_archive_init() { global $wp_query, $post; $queried_object = get_queried_object(); $args = self::get_current_shop_view_args(); $shortcode_args = array('page' => $args->page, 'columns' => $args->columns, 'rows' => $args->rows, 'orderby' => '', 'order' => '', 'paginate' => true, 'cache' => false); if (is_product_category()) { $shortcode_args['category'] = sanitize_title($queried_object->slug); } elseif (taxonomy_is_product_attribute($queried_object->taxonomy)) { $shortcode_args['attribute'] = sanitize_title($queried_object->taxonomy); $shortcode_args['terms'] = sanitize_title($queried_object->slug); } elseif (is_product_tag()) { $shortcode_args['tag'] = sanitize_title($queried_object->slug); } else { return; } if (!empty($queried_object->description) && (empty($_GET['product-page']) || 1 === absint($_GET['product-page']))) { $prefix = '<div class="term-description">' . wc_format_content(wp_kses_post($queried_object->description)) . '</div>'; } else { $prefix = ''; } add_filter('woocommerce_shortcode_products_query', array(__CLASS__, 'unsupported_archive_layered_nav_compatibility')); $shortcode = new WC_Shortcode_Products($shortcode_args); remove_filter('woocommerce_shortcode_products_query', array(__CLASS__, 'unsupported_archive_layered_nav_compatibility')); $shop_page = get_post(self::$shop_page_id); $dummy_post_properties = array('ID' => 0, 'post_status' => 'publish', 'post_author' => $shop_page->post_author, 'post_parent' => 0, 'post_type' => 'page', 'post_date' => $shop_page->post_date, 'post_date_gmt' => $shop_page->post_date_gmt, 'post_modified' => $shop_page->post_modified, 'post_modified_gmt' => $shop_page->post_modified_gmt, 'post_content' => $prefix . $shortcode->get_content(), 'post_title' => wc_clean($queried_object->name), 'post_excerpt' => '', 'post_content_filtered' => '', 'post_mime_type' => '', 'post_password' => '', 'post_name' => $queried_object->slug, 'guid' => '', 'menu_order' => 0, 'pinged' => '', 'to_ping' => '', 'ping_status' => '', 'comment_status' => 'closed', 'comment_count' => 0, 'filter' => 'raw'); $post = new WP_Post((object) $dummy_post_properties); $wp_query->post = $post; $wp_query->posts = array($post); $wp_query->post_count = 1; $wp_query->is_404 = false; $wp_query->is_page = true; $wp_query->is_single = true; $wp_query->is_archive = false; $wp_query->is_tax = true; $wp_query->max_num_pages = 0; setup_postdata($post); remove_all_filters('the_content'); remove_all_filters('the_excerpt'); add_filter('template_include', array(__CLASS__, 'force_single_template_filter')); } public static function unsupported_archive_layered_nav_compatibility($query) { foreach (WC()->query->get_layered_nav_chosen_attributes() as $taxonomy => $data) { $query['tax_query'][] = array('taxonomy' => $taxonomy, 'field' => 'slug', 'terms' => $data['terms'], 'operator' => 'and' === $data['query_type'] ? 'AND' : 'IN', 'include_children' => false); } return $query; } public static function force_single_template_filter($template) { $possible_templates = array('page', 'single', 'singular', 'index'); foreach ($possible_templates as $possible_template) { $path = get_query_template($possible_template); if ($path) { return $path; } } return $template; } private static function get_current_shop_view_args() { return (object) array('page' => absint(max(1, absint(get_query_var('paged')))), 'columns' => wc_get_default_products_per_row(), 'rows' => wc_get_default_product_rows_per_page()); } public static function unsupported_theme_title_filter($title, $id) { if (self::$theme_support || !$id !== self::$shop_page_id) { return $title; } if (is_page(self::$shop_page_id) || is_home() && 'page' === get_option('show_on_front') && absint(get_option('page_on_front')) === self::$shop_page_id) { $args = self::get_current_shop_view_args(); $title_suffix = array(); if ($args->page > 1) { $title_suffix[] = sprintf(esc_html__('Page %d', 'woocommerce'), $args->page); } if ($title_suffix) { $title = $title . ' &ndash; ' . implode(', ', $title_suffix); } } return $title; } public static function unsupported_theme_shop_content_filter($content) { global $wp_query; if (self::$theme_support || !is_main_query() || !in_the_loop()) { return $content; } self::$in_content_filter = true; remove_filter('the_content', array(__CLASS__, 'unsupported_theme_shop_content_filter')); if (is_page(self::$shop_page_id)) { $args = self::get_current_shop_view_args(); $shortcode = new WC_Shortcode_Products(array_merge(WC()->query->get_catalog_ordering_args(), array('page' => $args->page, 'columns' => $args->columns, 'rows' => $args->rows, 'orderby' => '', 'order' => '', 'paginate' => true, 'cache' => false)), 'products'); add_action('pre_get_posts', array(WC()->query, 'product_query')); $content = $content . $shortcode->get_content(); remove_action('pre_get_posts', array(WC()->query, 'product_query')); WC()->query->remove_ordering_args(); } self::$in_content_filter = false; return $content; } public static function unsupported_theme_product_content_filter($content) { global $wp_query; if (self::$theme_support || !is_main_query() || !in_the_loop()) { return $content; } self::$in_content_filter = true; remove_filter('the_content', array(__CLASS__, 'unsupported_theme_product_content_filter')); if (is_product()) { $content = do_shortcode('[product_page id="' . get_the_ID() . '" show_title=0 status="any"]'); } self::$in_content_filter = false; return $content; } public static function unsupported_theme_comments_number_filter($comments_number) { if (is_page(self::$shop_page_id)) { return ''; } return $comments_number; } public static function in_content_filter() { return (bool) self::$in_content_filter; } public static function unsupported_theme_single_featured_image_filter($html) { if (self::in_content_filter() || !is_product() || !is_main_query()) { return $html; } return ''; } public static function unsupported_theme_remove_review_tab($tabs) { unset($tabs['reviews']); return $tabs; } } add_action('init', array('WC_Template_Loader', 'init'));