chiucs123
Forum Replies Created
-
Just realized that we need to add Polylang support as well, so we did just that too.
miga_custom_posts.phpadd_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)) {
// ...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,
JasonHi 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,
JasonHi @robindelmundo ,
Please note that the bug has been identified as a URL construction issue for missing a'/'slash towards the end of thehome_url().
Inspecting file:src\Framework\Routes\Router.php:136
The linehome_url()is used, which returns the current site under a subfolder without'/'at the end, yet the code still attempts to add query parameters regardless it’s pointing to the root directory instead of the subfolder thus nobody can get their forms directed correctly back to WordPress handling if their sites on a subfolder.
A possible quick fix would be:rtrim(home_url(), '/').'/'
This way we’re adding a single'/'regardless of whether there’s one from thehome_url()function, which should work for all root, subdomain and subfolder cases and assuming you have .htaccess setup correctly, you may advise your team to check against WordPress permalinks settings before apply this'/'to the URL and provide this as an user option.
You’re welcome.
chiucs123.Hi @niksebastian,
Thank you for your suggestion.
For our use case, we would like to alert the user on more than one matter, to assist our users better, we want to display the error message right next to the spot where they need to take action, hence we do not want to place it on the header.
Is native support for that subfield available, rather than placing the error message somewhere potentially unrelated?
We understand code customization is beyond the scope, so we would like to see if there is an appropriate setting to achieve this before heading to custom code this part. We prefer the official/suggested way for sustainability considerations.
Best regards,
Jason- This reply was modified 3 years, 9 months ago by chiucs123.