Search code examples
phpwordpresstemplates

WordPress virtual page render as blog instead of page


I have a problem in a class that generates virtual pages using the generate_rewrite_rules... I use the filter the_content instead of template_redirect or templete_include so the content is ok regardless of the theme/site.

The virtual page is almost working...I can see my page loaded but the page is loading as archive blog page instead of single page. How can I force wordpress to render the page as page?

Here is the class:

<?php
namespace Magana\CShorts\Components\VP;

use Magana\Plugins\Core\Configuration;

defined( 'ABSPATH' ) || exit;
class SingleContact
{
    public function __construct()
    {
        add_filter( 'generate_rewrite_rules', [$this,'rewriteRules'] );
        add_filter( 'query_vars', [$this,'queryVars'] );
        add_action( 'pre_get_posts', [$this,'resetQuery'], 1 );
        add_filter( 'the_content', [$this, 'contactContent']  );
        add_filter( 'wp_title', [$this, 'contactTitle']  );
        add_filter( 'the_title', [$this, 'hideTitle'] );

    }
    public function rewriteRules( $wp_rewrite )
    {
        $wp_rewrite->rules = array_merge(
            ['country/(.*?)/(.*?)/?$' => 'index.php?country=$matches[1]&contact_id=$matches[2]'],
            $wp_rewrite->rules
        );
    }

    public function queryVars( $query_vars )
    {
        $query_vars[] = 'country';
        $query_vars[] = 'contact_id';
        return $query_vars;
    }
    public function resetQuery( $query )
    {
        $id = get_query_var( 'contact_id' );
        $country = get_query_var( 'country' );
        if($id && $country && $query->is_main_query()){
            $page_id = url_to_postid('hex-single-contact');
            $query->set( 'post__in', [$page_id] );
            $query->set( 'posts_per_page', '1' );
            $query->set('post_type', 'page');
            $query=[];
        }
    }

    function contactTitle($title)
    {
        $id = get_query_var( 'contact_id' );
        $country = get_query_var( 'country' );
        if ($id && $country){
            return __("Contact");
        }
        return $title;
    }
    function contactContent($content)
    {
        $id = get_query_var( 'contact_id' );
        $country = get_query_var( 'country' );
        if ($id && $country){
            $ga = Configuration::get("ga");
            $new_template = locate_template(['single-contact.php']) ?: HEX_CSHORTS_ABSPATH . '/App/templates/single-contact.php';
            if (!$new_template) {
                wp_die("Template 'single-contact' not found");
            }
            require $new_template;
            return false;
        }
        return $content;
    }
    public function hideTitle( $title ) {
        $id = get_query_var( 'contact_id' );
        $country = get_query_var( 'country' );
        if ($id && $country && in_the_loop())
            $title = false;
        return $title;
    }
}

Solution

  • The solution was to modify the $wp_query variable

    public function resetQuery( $query )
    {
        global $wp_query;
        $id = get_query_var( 'contact_id' );
        $country = get_query_var( 'country' );
        if($id && $country && $query->is_main_query()){
            $page_id = url_to_postid('hex-single-contact');
            $query->set( 'post__in', [$page_id] );
            $query->set( 'posts_per_page', '1' );
            $query->set('post_type', 'page');
            $wp_query->is_page = TRUE;
            $wp_query->is_singular = TRUE;
            $wp_query->is_home = FALSE;
            $wp_query->is_archive = FALSE;
            $wp_query->is_category = FALSE;
            unset($wp_query->query['error']);
            $wp_query->query_vars['error'] = '';
            $wp_query->is_404 = FALSE;
        }
    }