• Resolved chiucs123

    (@chiucs123)


    Hi Michael,

    I hope this post finds you well.

    We are having trouble getting a template to show for a custom post type created in ACF. The template is a page template in Elementor and is created using the widgets provided in the plugin. The connection seems to store and saved in database correctly and the underlying source code shows that the post type-template association is indeed registered.

    We tried looking into the matter and it seems insider function miga_custom_posts_rewrite_rules(), while $posts contained user configurations, the $postName checking is fixed to “post” while the loop returns the targeted post type slug, which will always be different from “post”. The same logic is also applied in templates/post.php.

    In case this is related, we’re using Polylang. The get_post_id_by_slug() inside the ‘request’ filter is working so I’m not too worried if that’s impacting.

    Would you please help?

    Thank you and have a wonderful day!

    Best regards,
    Jason

Viewing 8 replies - 1 through 8 (of 8 total)
  • Plugin Author Michael

    (@migaweb)

    Hi Jason, I’ll have a look soon and test it with CPT.

    Best, Michael

    Plugin Author Michael

    (@migaweb)

    I’ve tested it and it still works fine. The “post” part just relates to posts, in your case the add_filter(“request”) is the part that is setting the template. When you say “The template is a page template in Elementor” you are saying it’s not a normal page but a Elementor – Editor – Templates – Page template? Try using a normal page.

    Thread Starter chiucs123

    (@chiucs123)

    Hi Michael,

    Thank you for following up with us. We really appreciate it.

    Yes, it is an Elementor template page instead of a normal page. The reason for doing that is for ease of management and compatibility considerations with some other plugin that follows Elementor’s template architecture.

    We dove deeper into the code. We understand that the way it currently works is to trick WordPress into thinking rendering a normal page instead by manipulating the query vars to have “pagename”, which triggers a page render instead of a post render, thus the rendering context has been changed from rendering a post of custom type to a single page render, and that created problems where other plugins that focuses on rendering by post type would not work with the suggested page method.

    I guess we need to brainstorm solutions ourselves based on this. Thanks for clarifying the post part for us. Have a wonderful day!

    Best regards,
    Jason

    Plugin Author Michael

    (@migaweb)

    This plugin is only useful for smaller pages where you’ll need a quick way to display e.g. news. It e.g. won’t show correct SEO tags or other special stuff when it renders your custom template.

    I use custom single-[].php templates in my child theme to render pages. Or of course get Elementor Pro šŸ™‚ I’ve uploaded an update to fix some code parts but in the long term it needs to be rewritten to make it a proper template engine

    Thread Starter chiucs123

    (@chiucs123)

    Hi Michael,

    We have modified parts the code to solve the issue. Elementor page templates is now supported. Hopefully this can be useful.

    miga_custom_posts.php

    <?php

    /**
    * Plugin Name
    *
    * @package PluginPackage
    * @author Michael Gangolf
    * @copyright 2022 Michael Gangolf
    * @license GPL-2.0-or-later
    *
    * @wordpress-plugin
    * Plugin Name: Custom post type templates for Elementor
    * Description: With the help of this plug-in you can link a custom post type to a normal Elementor page. In that Elementor page you can use the included elements (post title, post image, post content) to create a template.
    * Version: 3.0.2
    * Requires at least: 5.2
    * Requires PHP: 7.2
    * Author: Michael Gangolf
    * Author URI: https://www.migaweb.de/
    * License: GPL v2 or later
    * License URI: http://www.gnu.org/licenses/gpl-2.0.txt
    * Text Domain: miga_custom_posts
    * Elementor tested up to: 4.1
    */

    use Elementor\Plugin;

    function change_post_type_template($single_template)
    {
    if (!class_exists('Elementor\Plugin')) {
    return $single_template;
    }
    $elementor_preview_active = \Elementor\Plugin::$instance->preview->is_preview_mode();
    if (stripos($single_template, "/single.php") > -1 && !$elementor_preview_active) {
    $single_template = plugin_dir_path(__FILE__) . 'templates/post.php';
    }
    return $single_template;
    }

    function miga_custom_posts_register_settings()
    {
    add_option('miga_custom_posts', "");
    register_setting('miga_custom_posts_option_group', 'miga_custom_posts', 'sanitize_values');
    }

    function miga_enqueue_style()
    {
    wp_register_style('miga_custom_posts_style', plugins_url('styles/main.css', __FILE__));
    wp_register_script('miga_custom_posts_script', plugins_url('scripts/main.js', __FILE__), array('wp-i18n'), '', true);
    wp_enqueue_style('miga_custom_posts_style');
    wp_enqueue_script('miga_custom_posts_script');

    wp_localize_script('miga_custom_posts_script', 'objectL10n', array(
    'postText' => __('The following post type', 'miga_custom_posts'),
    'pageText' => __('should be rendered in this page template', 'miga_custom_posts'),
    ));
    }

    function miga_custom_posts_rewrite_rules()
    {
    $posts = get_option('miga_custom_posts');
    if (!empty($posts) && is_array($posts)) {
    foreach ((array) $posts as $name => $element) {
    $postId = $element[0];
    $postName = $element[1];
    // Apply single template filter for mapped custom post types
    if (!empty($postName) && !is_admin()) {
    add_filter('single_template', 'change_post_type_template');
    }
    }
    }
    }

    function get_post_id_by_slug($slug, $posttype)
    {
    $post = get_page_by_path($slug, OBJECT, $posttype);
    if ($post) {
    return $post->ID;
    } else {
    return null;
    }
    }

    add_filter('request', function ($query_vars) {
    if (is_admin()) {
    return $query_vars;
    }

    if (!class_exists('Elementor\Plugin')) {
    return $query_vars;
    }

    $elementor_preview_active = \Elementor\Plugin::$instance->preview->is_preview_mode();
    if (!$elementor_preview_active) {
    $posts = get_option('miga_custom_posts');
    if (!empty($posts) && is_array($posts)) {
    foreach ((array) $posts as $name => $element) {
    $template_id = $element[0];
    $postName = $element[1];

    if (!empty($template_id) && !empty($postName) && $template_id == (int)$template_id
    && (isset($query_vars["post_type"]) && $query_vars["post_type"] == $postName) && isset($query_vars["name"])) {

    $post_id = get_post_id_by_slug($query_vars["name"], $query_vars["post_type"]);

    if (!empty($post_id) && stripos($_SERVER["REQUEST_URI"], "elementor-preview") === false) {
    // Check if the template is an Elementor Library item or a normal Page
    $template_post_type = get_post_type($template_id);

    $query_vars["page"] = "";
    $query_vars["custompost"] = "";
    $query_vars["name"] = "";
    $query_vars["pid"] = $post_id;
    $query_vars["ptype"] = $postName;
    $query_vars["template_id"] = $template_id; // Pass down the precise template ID

    if ($template_post_type === 'elementor_library') {
    // Trick core into thinking it is loading a library element post type
    $query_vars["post_type"] = "elementor_library";
    $query_vars["p"] = $template_id;
    } else {
    // Fallback for normal pages
    $query_vars["post_type"] = "";
    $query_vars["pagename"] = get_post_field('post_name', $template_id);
    }
    }
    }
    }
    }
    }
    return $query_vars;
    });

    function miga_custom_posts_query_vars($vars)
    {
    $vars[] = 'pid';
    $vars[] = 'ptype';
    $vars[] = 'template_id';
    return $vars;
    }

    function miga_custom_posts_addMenu()
    {
    add_submenu_page(
    'elementor',
    __('Custom post pages', 'miga_custom_posts'),
    __('Custom post pages', 'miga_custom_posts'),
    'manage_options',
    'miga-custom-posts-detailpage',
    'miga_custom_posts_detailpage',
    100
    );
    }

    function miga_custom_posts_detailpage()
    {
    echo '<form class="miga_custom_posts" method="post" action="options.php">';

    $posts = get_option('miga_custom_posts');

    printf("<h3>%s</h3>", __('Custom post pages:', 'miga_custom_posts'));
    printf("<p>%s</p>", __('Link custom post types to show up in normal Elementor pages. You can use the included elements to output the posts title, content or image.', 'miga_custom_posts'));
    printf("<h4>%s</h4>", __('How to use it', 'miga_custom_posts'));
    echo '<ol>';
    printf("<li>%s</li>", __('create a custom post type', 'miga_custom_posts'));
    printf("<li>%s</li>", __('create an Elementor page', 'miga_custom_posts'));
    printf("<li>%s</li>", __('use the included elements to output title, text or image', 'miga_custom_posts'));
    printf("<li>%s</li>", __('create a connection between the post type and the page below', 'miga_custom_posts'));
    printf("<li>%s</li>", __('save it and open the post detail page', 'miga_custom_posts'));
    echo '</ol>';

    printf("<h4>%s</h4>", __('Create the connections', 'miga_custom_posts'));
    echo '<div class="boxes">';
    $i = 0;

    $custom_post_ids = get_posts([
    'fields' => 'ids',
    'post_type' => 'elementor_library',
    'post_status' => 'publish',
    'numberposts' => -1,
    'elementor_library_type' => 'page',
    'order' => 'ASC'
    ]);

    $page_ids = get_all_page_ids();
    $page_ids = array_merge($page_ids, $custom_post_ids);
    $args = array('public' => true);
    $post_types = get_post_types($args, 'names', 'and');

    $emptyOptions1 = "";
    $emptyOptions2 = "";
    $runOnce = false;

    if (!empty($posts) && is_array($posts)) {
    foreach ($posts as $key => $post) {
    $options = '';
    foreach ($page_ids as $id) {
    $sel = ($id == $post[0]) ? 'selected="selected"' : '';
    $options .= '<option value="'.$id.'" '.$sel.'>'.get_the_title($id).'</option>';
    if (!$runOnce) {
    $emptyOptions1 .= '<option value="'.$id.'">'.get_the_title($id).'</option>';
    }
    }

    $options_pt = "";
    if ($post_types) {
    foreach ($post_types as $post_type) {
    $sel = ($post_type == $post[1]) ? 'selected="selected"' : '';
    $options_pt .= '<option value="'.$post_type.'" '.$sel.'>'.$post_type.'</option>';
    if (!$runOnce) {
    $emptyOptions2 .= '<option value="'.$post_type.'">'.$post_type.'</option>';
    }
    }
    }

    echo '<div class="box" id="box_'.esc_attr($i).'">';
    printf("<p>%s</p>", __('The following post type', 'miga_custom_posts'));
    echo '<select id="miga_custom_post_type_'.esc_attr($i).'" name="miga_custom_posts['.esc_attr($i).'][1]">'.$options_pt.'</select>';
    printf("<p>%s</p>", __('should be rendered in this page template', 'miga_custom_posts'));
    echo '<select id="miga_custom_post_id_'.esc_attr($i).'" name="miga_custom_posts['.esc_attr($i).'][0]">'.$options.'</select>';
    echo '<button onclick="miga_custom_posts_remove('.esc_attr($i).')" class="remove"><i class="eicon-trash-o"></i>';
    echo '</button></div>';

    $i++;
    $runOnce = true;
    }
    } else {
    foreach ($page_ids as $id) {
    $emptyOptions1 .= '<option value="'.$id.'">'.get_the_title($id).'</option>';
    }
    if ($post_types) {
    foreach ($post_types as $post_type) {
    $emptyOptions2 .= '<option value="'.$post_type.'">'.$post_type.'</option>';
    }
    }
    }
    echo '</div>';
    settings_fields('miga_custom_posts_option_group');
    echo '<button class="add" onclick="miga_custom_posts_addElement(); return false;"><i class="eicon-plus-square"></i>';
    _e("add", 'miga_custom_posts');
    echo '</button>';
    submit_button();

    echo '</form>';
    echo '<select id="selectPages" class="hidden">'.wp_kses($emptyOptions1, ["option" => array("value" => array())]).'</select>';
    echo '<select id="selectPosts" class="hidden">'.wp_kses($emptyOptions2, ["option" => array("value" => array())]).'</select>';
    }

    function miga_custom_posts_flush_rewrite_rules() { flush_rewrite_rules(); }
    add_action('update_option_miga_custom_posts', 'miga_custom_posts_flush_rewrite_rules');
    add_action('add_option_miga_custom_posts', 'miga_custom_posts_flush_rewrite_rules');

    function miga_custom_posts_register_widgets($widgets_manager)
    {
    require_once(__DIR__ . '/includes/search.php');
    require_once(__DIR__ . '/widgets/PostTitle.php');
    require_once(__DIR__ . '/widgets/PostDate.php');
    require_once(__DIR__ . '/widgets/PostImage.php');
    require_once(__DIR__ . '/widgets/PostContent.php');
    require_once(__DIR__ . '/widgets/PostACF.php');
    require_once(__DIR__ . '/widgets/PostsList.php');
    $widgets_manager->register(new \Elementor_Widget_miga_post_title());
    $widgets_manager->register(new \Elementor_Widget_miga_post_image());
    $widgets_manager->register(new \Elementor_Widget_miga_post_content());
    $widgets_manager->register(new \Elementor_Widget_miga_post_acf());
    $widgets_manager->register(new \Elementor_Widget_miga_posts());
    $widgets_manager->register(new \Elementor_Widget_miga_post_date());
    }
    add_action('elementor/widgets/register', 'miga_custom_posts_register_widgets');

    function miga_custom_posts_add_category($elements_manager)
    {
    $elements_manager->add_category(
    'miga_custom_posts',
    [
    'title' => __('Custom post page', 'miga_custom_posts'),
    'icon' => 'fa fa-plug',
    ]
    );
    }

    function sanitize_values($input)
    {
    $new_input = array();
    foreach ((array) $input as $name => $element) {
    foreach ($element as $index => $value) {
    if (! empty($value)) {
    $new_input[ $name ][ $index ] = esc_attr($value);
    }
    }
    }
    return $new_input;
    }

    function ctmfe_scripts()
    {
    wp_register_style('ctmfe_styles', plugins_url('styles/frontend.css', __FILE__));
    wp_enqueue_style('ctmfe_styles');
    }

    add_action('wp_enqueue_scripts', 'ctmfe_scripts');
    add_action('admin_init', 'miga_custom_posts_register_settings');
    add_action('init', 'miga_custom_posts_rewrite_rules');
    add_action('admin_menu', 'miga_custom_posts_addMenu', 999);
    add_action('admin_enqueue_scripts', 'miga_enqueue_style');
    add_action('elementor/elements/categories_registered', 'miga_custom_posts_add_category');
    add_filter('query_vars', 'miga_custom_posts_query_vars');
    // ajax search
    add_action('wp_ajax_miga_custom_post_filter', 'miga_custom_posts_ajax_functions');
    add_action('wp_ajax_nopriv_miga_custom_post_filter', 'miga_custom_posts_ajax_functions');


    function custom_title($title_parts)
    {
    $id = get_query_var("pid");
    if (!empty($id)) {
    $title_parts['title'] = esc_attr(get_the_title($id));
    }
    return $title_parts;
    }
    add_filter('document_title_parts', 'custom_title');

    // Setup postdata based on our custom post item execution
    add_action('wp', function () {
    $pid = get_query_var('pid');
    $ptype = get_query_var('ptype');
    if (empty($pid) || empty($ptype)) {
    return;
    }
    $original_post = get_post((int) $pid);
    if (!$original_post) {
    return;
    }

    global $post;
    $post = $original_post;
    setup_postdata($post);

    global $wp_query;
    $wp_query->queried_object = $original_post;
    $wp_query->queried_object_id = $original_post->ID;
    });

    templates/post.php

    <?php

    if (!defined("ABSPATH")) {
    exit();
    }

    // Retrieve custom values populated during our 'request' intercept filter
    $pid = get_query_var('pid');
    $ptype = get_query_var('ptype');
    $template_id = get_query_var('template_id');

    // Fallback search logic if direct query execution context variables drop off
    if (empty($template_id)) {
    $posts = get_option("miga_custom_posts");
    if (!empty($posts) && is_array($posts) && !empty($ptype)) {
    foreach ((array) $posts as $name => $element) {
    if ($element[1] == $ptype) {
    $template_id = $element[0];
    break;
    }
    }
    }
    }

    if (!empty($template_id)) {
    // Inject themes classes if Astra or standard structures are present
    \Elementor\Plugin::$instance->frontend->add_body_class(
    "ast-page-builder-template"
    );

    get_header();

    // Renders the element layout markup engine output for the Elementor Template ID
    echo \Elementor\Plugin::instance()->frontend->get_builder_content_for_display(
    $template_id
    );

    get_footer();
    } else {
    // Hard fallback if no mapping configuration was matched
    if (have_posts()) {
    while (have_posts()) {
    the_post();
    the_content();
    }
    }
    }

    Have a wonderful day!

    Best regards,
    Jason

    Thread Starter chiucs123

    (@chiucs123)

    Just realized that we need to add Polylang support as well, so we did just that too.

    miga_custom_posts.php

    add_filter('request', function ($query_vars) {
    // ....
    if (!empty($post_id) && stripos($_SERVER["REQUEST_URI"], "elementor-preview") === false) {
    // ....
    if (function_exists('pll_get_post')) {
    $translated_template_id = pll_get_post($template_id);
    if (!empty($translated_template_id)) {
    $template_id = $translated_template_id;
    }
    }
    // ....
    }
    // ....
    }

    templates/post.php


    // ....

    if (!empty($template_id) && function_exists('pll_get_post')) {
    $translated_template_id = pll_get_post($template_id);
    if (!empty($translated_template_id)) {
    $template_id = $translated_template_id;
    }
    }

    if (!empty($template_id)) {

    // ...
    Plugin Author Michael

    (@migaweb)

    Thanks for the info and the code! Will add those in the next release

    Plugin Author Michael

    (@migaweb)

    polylang update is online

Viewing 8 replies - 1 through 8 (of 8 total)

You must be logged in to reply to this topic.