Creating a wordpress virtual page with a function and page template - php

I'm trying to create a virtual contact page on wordpress. All the necessary data will be stored in a page template. But in my function I don't know how to link to the file.
When the user does to domain.com/contact I would like to redirect him to the contact.php file.
So far I got this function to work and show content from this line $post->post_content = 'page template: contact.php'; but I would like to show the content from templates/contact.php
add_filter( 'the_posts', 'generate_contact_page', -10 );
function generate_contact_page( $posts ) {
global $wp, $wp_query;
$url_slug = 'contact'; // URL slug of the contact page
if ( ! defined( 'CONTACT_PAGE' ) && ( strtolower( $wp->request ) == $url_slug ) ) {
// stop interferring with other $posts arrays on this page (only works if the sidebar is rendered *after* the main page)
define( 'CONTACT_PAGE', true );
// create a contact virtual page
$post = new stdClass;
$post->post_author = 1;
$post->post_name = $url_slug;
$post->guid = home_url() . '/' . $url_slug;
$post->post_title = 'Contact page';
$post->post_content = 'page template: contact.php';
$post->ID = -999;
$post->post_type = 'page';
$post->post_status = 'static';
$post->comment_status = 'closed';
$post->ping_status = 'open';
$post->comment_count = 0;
$post->post_date = current_time( 'mysql' );
$post->post_date_gmt = current_time( 'mysql', 1 );
$posts = NULL;
$posts[] = $post;
// make wpQuery believe this is a real page too
$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;
}
return $posts;
}
How can I achieve something like this? Maybe you know a better solution ?

So for template output you can try this function
function get_template_output($slug = '', $name = '') {
ob_start();
get_template_part($lug, $name);
return ob_get_clean();
}
And then to assign content you will use
$content = get_template_output('templates/', 'contact');

Related

WordPress Virtual Page - "Trying to get property 'post_type' of non-object"

I'm building a WordPress plugin that uses a virtual page to display the data fetched from the API.
The setup is relatively simple. I have a rewrite rule for the URLs on which the plugin is meant to work and when I hit specific query_vars I start the virtual page.
public function __construct()
{
require_once plugin_dir_path(__FILE__).'vendor/autoload.php';
add_action('init', [$this, 'rewrite_rule'], 1);
// add query vars
add_action('query_vars', [$this, 'add_query_vars_filter'], 1);
// virtual page init
add_filter('the_posts', [$this, 'virtual_page'], 1);
}
public function virtual_page($posts)
{
global $wp, $wp_query;
if (!empty(get_query_var('plugin'))) {
$plugin = get_query_var('plugin');
}
if (!empty($plugin)) {
$post = new stdClass();
$post->post_author = 1;
$post->post_name = 'lorem ipsum';
$post->guid = get_bloginfo('wpurl').'/';
$post->post_title = 'title';
$post->post_content = 'content';
$post->ID = -999;
$post->post_type = 'page';
$post->post_status = 'static';
$post->comment_status = 'closed';
$post->ping_status = 'open';
$post->comment_count = 0;
$post->post_date = current_time('mysql');
$post->post_date_gmt = current_time('mysql', 1);
$posts = NULL;
$posts[] = $post;
$wp_query->is_page = true;
$wp_query->is_single = false;
$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;
remove_filter('the_content', 'wpautop');
remove_filter('the_excerpt', 'wpautop');
return $posts;
}
}
This code does what is expected which is display the Virtual Page with content I need but I get a warning in PHP 8.0 :
"Attempt to read property "post_type" on null"
I believe the execution order is wrong here because I get empty $post & $wp_query in xdebug. I'm guessing that the virtual page function is being executed too early.
I was trying to debug this issue for a long time but unfortunately I'm lacking backend / WordPress knowledge.
If anyone could help I'm going to be more thankful.
If You try to work with a Virtual Page in WP 6.1 you cannot have a post ID anymore. This line was causing it to break.
$post->ID = -999;

Change subcategory URL(slug) in Wordpress

I have problem with slug(URL) in category/subcategory. Now i have: http://my-page.pl/animal-category/animal-subcategory. How can i delete "animal-category" for every subcategory ?
It should look like that:
http://my-page.pl/animal-category/
http://my-page.pl/animal-subcategory/
http://my-page.pl/animal-subcategory/single-page
Maybe it's simple question, but I cant find answer anywhere :)
Check below code it will help you
// Add 'cat_redirect' query variable in query_vars
add_filter('query_vars', 'no_parent_cat_query_vars');
function no_parent_cat_query_vars($query_vars) {
$query_vars[] = 'cat_redirect';
return $query_vars;
}
// Redirect if 'cat_redirect' is set
add_filter('request', 'no_parent_cat_request');
function no_parent_cat_request($query_vars) {
if(isset($query_vars['cat_redirect'])) {
$cat_link = trailingslashit(get_option( 'home' )) . user_trailingslashit( $query_vars['cat_redirect'], 'category' );
status_header(301);
header("Location: $cat_link");
exit();
}
return $query_vars;
}
// Remove category
add_filter('category_link', 'category_url_without_parent',1000,2);
function category_url_without_parent($cat_link, $cat_id)
{
$category = &get_category( $cat_id );
if ( is_wp_error( $category ) ) return $category;
$catname = $category->slug;
$cat_link = trailingslashit(get_option( 'home' )) . user_trailingslashit( $catname, 'category' );
return $cat_link;
}
// Add custom category rewrite rule
add_filter('category_rewrite_rules', 'remove_category_parent_rule');
function remove_category_parent_rule($cat_rewrite) {
global $wp_rewrite;
$cat_rewrite=array();
$cat_list=get_categories(array('hide_empty'=>false));
foreach($cat_list as $category) {
$catname = $category->slug;
$cat_rewrite['('.$catname.')/(?:feed/)?(feed|rdf|rss|rss2|atom)/?$'] = 'index.php?category_name=$matches[1]&feed=$matches[2]';
$cat_rewrite['('.$catname.')/page/?([0-9]{1,})/?$'] = 'index.php?category_name=$matches[1]&paged=$matches[2]';
$cat_rewrite['('.$catname.')/?$'] = 'index.php?category_name=$matches[1]';
}
$old_base = $wp_rewrite->get_category_permastruct();
$old_base = str_replace( '%category%', '(.+)', $old_base );
$old_base = trim($old_base, '/');
$cat_rewrite[$old_base.'$'] = 'index.php?cat_redirect=$matches[1]';
return $cat_rewrite;
}

ACF get_field() returns empty

I'm developing an application through custom post type with custom fields using ACF plugin. When the custom post type is saved, it will create a blog in my network which works great however, when trying to copy the custom fields from the custom post type to the newly created blog's homepage with same acf custom fields, the acf custom fields are not saved.
I tested, $station_description = 'Not Empty'; and it does save/copied to its specific field without a problem. Its just that when i use, get_field() it does not save/copied to the new created blog.
What's wrong with my code?
function myy_acf_save_post( $post_id ) {
$post = get_post($post_id);
if( $post->post_type == 'network_directory' ) {
$title = $post->post_title;
$post_slug = $post->post_name;
$client_username = get_field('client_username', $post_id);
$station_server = get_field('station_server', $post_id);
$station_location = get_field('station_location', $post_id);
// $station_description = get_field('station_description', $post_id);
$station_description = 'Not Empty';
$language = get_field('language', $post_id);
$station_email = get_field('station_email', $post_id);
$station_website = get_field('station_website', $post_id);
$station_port = get_field('station_port', $post_id);
$station_logo = get_field('station_logo', $post_id);
// $station_logo_url = wp_get_attachment_url( $station_logo );
// $subdomain = get_field('subdomain', $post->ID);
$main_site = 'domain.com';
$subdomain_install = true;
# Create a new user
$check_user_id = get_user_id_from_string( $station_email );
if ($check_user_id !== null) {
$user_id = get_user_id_from_string( $station_email );
} else {
$rand_number = rand( 1, 2000 );
$username = 'user-' . $rand_number;
$password = wp_generate_password( 12, false );
$email = $station_email;
$user_id = wpmu_create_user( $username, $password, $email );
}
// wp_new_user_notification( $user_id, $password );
# Create site
if( $subdomain_install )
{
$newdomain = "{$post_slug}.$main_site";
$path = '/';
}
$the_blog_id = wpmu_create_blog( $newdomain, $path, $title, $user_id , array( 'public' => 1 ) );
if ( ! add_post_meta( $post_id, 'blog_id_meta_key', $the_blog_id, true ) ) {
update_post_meta( $post_id, 'blog_id_meta_key', $the_blog_id );
}
switch_to_blog( $the_blog_id );
$homepage_id = get_option( 'page_on_front' );
// $station_logo_new_src = media_sideload_image($station_logo_url, $homepage_id, 'Station Logo','src');
// $station_logo_new_id = get_attachment_id_from_src($station_logo_new_src);
update_field('client_username', $client_username, $homepage_id);
update_field('station_server', $station_server, $homepage_id);
update_field('station_location', $station_location, $homepage_id);
update_field('language', $language, $homepage_id);
update_field('station_email', $station_email, $homepage_id);
update_field('station_website', $station_website, $homepage_id);
update_field('station_port', $station_port, $homepage_id);
// update_field('station_logo', $station_logo_new_id, $homepage_id);
update_field('station_description', $station_description, $homepage_id);
restore_current_blog();
}
}
add_action('acf/save_post', 'myy_acf_save_post', 9999);
throwing print_r(get_post_meta(get_the_ID())) in your template will output fields that are available, which can be useful debugging. In my case, after re-ordering modules on a page i noticed that get_post_meta output was unexpected, which then helped me see that i had forgotten to reset a query higher up the page using wp_reset_postdata().
fount it.
using get_post_meta to retrieve values is way better than get_field

Body class on forum page

I'm using this code to show category on body class.
But now I'm facing problems on BBPress forum page. I'm getting Notices "non-object, undefined offset..."
How to exclude BBPress pages from this? I need to have just normal body classes when on forum pages.
add_filter('body_class','top_cat_body_class');
function top_cat_body_class($classes) {
if( is_single() ) :
global $post;
$cats = get_the_category( $post->ID );
if( count( $cats ) > 1 ) {
return array('genericClass');
}
else {
$cat_anc = get_ancestors( $cats[0]->term_id, 'category' );
$top_cat = array_merge( array($cats[0]->term_id), $cat_anc );
$top_cat = array_pop( $top_cat );
return array(get_category($top_cat)->slug);
}
elseif( is_category() ) :
$cat_anc = get_ancestors( get_query_var('cat'), 'category' );
$top_cat = array_merge( array(get_query_var('cat')), $cat_anc );
$top_cat = array_pop( $top_cat );
return array(get_category($top_cat)->slug);
else :
return $classes;
endif;
}
You can use bbPress Conditional Tags and add to the beginning of your top_cat_body_class function code something like
if (function_exists('is_bbpress') AND is_bbpress()) return $classes;
Hope it helps!

How to generate custom page names in wordpress?

I lost my old website's code and am trying to recreate a function I had created ages ago.
I have custom pages in my Wordpress blog: about, work, contact, news as well as posts and subpages.
I am trying to manipulate the value of <h1 class="site-title"><?php bloginfo( 'name' ); ?></h1> to display those different page tiles for those pages and their children so that it would look something like this:
if( $show == 'name' )
{
if( is_page('work') ) $output = 'Work';
if( is_page('contact') ) $output = 'Contact';
if( is_page('about') ) $output = 'About';
}
return $output;
And as for all the rest of the pages, I just want it to display the default site value so somewhere along the line there would be an
else $output = "Site Name";
So I kind of understand the logic because I have done it in the past but cannot remember how the syntax went.
Could anyone refresh my memory?
You could put the following in your functions.php file:
function so20527793_sitename()
{
$output = get_bloginfo( 'name' );
if( is_page( 'work' ) ) $output = 'Work';
if( is_page( 'contact' ) ) $output = 'Contact';
if( is_page( 'about' ) ) $output = 'About';
return $output;
}
Usage:
<h1 class="site-title"><?php echo so20527793_sitename(); ?></h1>
Well I did not get much help in the end so I had to figure it out by googling and combining functions. Here is the result:
function is_child($page_id_or_slug) {
global $post;
if(!is_int($page_id_or_slug)) {
$page = get_page_by_path($page_id_or_slug);
$page_id_or_slug = $page->ID;
}
if(is_page() && $post->post_parent == $page_id_or_slug ) {
return true;
} else {
return false;
}
}
function Custom_PageName(){
$output = get_bloginfo( 'name' );
if (is_page('about') || is_child('about')) $output = 'About title';
if (is_page('work') || is_child('work')) $output = 'Work Page';
if (is_page('contact') || is_child('contact')) $output = 'Contact';
return $output;
}

Categories