<?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 . ' – ' . 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'));