I'm posting this question as I'm having a little trouble adding the author info to my post hero on my website.
I'm using the Genesis framework with Wordpress, so what I did is removing the post info from the post and adding it back in the post hero. That all works, except that the author name is not being shown anymore as it's not yet fetched in the post loop.
// Remove entry title
remove_action( 'genesis_entry_header', 'genesis_do_post_title' );
// Remove post info
remove_action( 'genesis_entry_header', 'genesis_post_info', 12 );
// Add page title
add_action( 'hero-info', 'genesis_do_post_title' );
// Add page info
add_action( 'hero-info', 'genesis_post_info', 12 );
To be able to add the post author info back in the post hero, I've looked up stackoverflow and found a link where the OP was able to fix it by creating a shortcode for it and running it in the hero-info
function author_shortcode() {
global $post;
$author_id=$post->post_author;
the_author_meta( 'display_name', $author_id );
}
add_shortcode('author', 'author_shortcode');
This shortcode [author] is then added into
add_filter( 'genesis_post_info', 'custom_post_info' );
function custom_post_info( $post_info ) {
if ( is_archive() || is_home() ) {
$post_info = __( 'Article by [author] [post_author_posts_link] on [post_date] - [post_comments zero="Leave a Comment" one="1 Comment" more="% Comments" hide_if_off="disabled"]', 'tcguy' );
return $post_info;
}
}
This is the result now: http://imgur.com/a/6lX5J
It is shown in the wrong place for some reason. Anybody knows how this can be?
The site can be found here: http://websforlocals.com/business/
Hope I gave enough info, and that someone with the same problem can be helped out.
It is issue in your ShortCode registering php code.
When adding short-code we should not ECHO anything as this way it will not be echoed at the place we want to but at the top of the post content.
So always return the output in short code function, and then echo the short-code function.
Now WordPress have a convention for functions which echo the result and which returns the result, i.e. the_author_meta vs get_the_author_meta (first one which you are using will display/echo the result, however get_ functions will return the values).
We need to use get_the_author_meta instead of the_author_meta in your shortcode registering block and it will solve your displaying location issue.
function author_shortcode() {
global $post;
$author_id=$post->post_author;
return get_the_author_meta( 'display_name', $author_id );
}
add_shortcode('author', 'author_shortcode');
Related
I changed the permalinks of my posts using post_link, adding "/test/" to it.
So for example www.website.com/this-is-fun/ is now having the permalink www.website.com/test/this-is-fun/
This permalink is correctly showing in the admin, when editing a post, and also on the website the link to the post is the new one.
However, when I open this link it is not working, I get a 404. I was able to fix that with a add_rewrite_rule, but now my problem is that BOTH urls exist. I want only the new one to exist.
Am I making a mistake in the post_link part, is there a way you can automatically disable the original link and make the new one work? Or should I use add_rewrite_rule to disable the original? Or is there another way?
This is my code:
add_filter( 'post_link', 'custom_permalink', 10, 3 );
function custom_permalink( $permalink, $post, $leavename ) {
$permalink = home_url('/test/' . $post->post_name .'/' );
return $permalink;
}
add_action( 'init', 'custom_rewrite_rules' );
function custom_rewrite_rules() {
add_rewrite_rule(
'test/([^/]+)(?:/([0-9]+))?/?$',
'index.php?name=$matches[1]',
'top'
);
}
add_action( 'init','flush_rewrite_rules' );
I know I can change the permalink in the settings btw, but this new permalink will not be for all posts, so I need to do it this way.
I need to output a certain product page on the homepage. add_rewrite_rule doesn't work for homepage for any reason (
there are actually no rewrite rules for the homepage in the database, WordPress seems to use some other functions to
query the homepage):
//works fine
add_rewrite_rule( 'certainproductpage/?$',
'index.php?post_type=product&name=certainproduct',
'top'
);
//does not work
add_rewrite_rule( '', //tried everything like "/", "/?$" etc
'index.php?post_type=product&name=certainproduct',
'top'
);
After spending way too much time looking through wp / wc core code and stackoverflow I came across an alternative. I can
simply add a shortcode in the content of the page I need to be the homepage and a product page at the same
time: [product_page id=815]. Indeed it works great, but only if the shortcode is added in the admin editor or is
stored in the database (post_content). If I try to call the shortcode manually on the page template (
page-certainproductpage.php) then it outputs the product page without some necessary stuff (PayPal, PhotoSwipe and
Gallery js). Weirdly enough, if I keep the shortcode in the content (via Gutenberg / Code Editor) but don't
call the_content and only echo the shortcode then everything works fine:
if ( ! defined( 'ABSPATH' ) ) {
exit;
}
get_header( 'shop' );
//works fine only if the same shortcode is within the certainproductpage's content
echo do_shortcode("[product_page id='815']");
//the_content();
get_footer( 'shop' );
Also when I try to add the shortcode via the_content filter hook before the do_shortcode function is applied in core's
default-filters.php ($priority < 11), then I get only the error:
NOTICE: PHP message: PHP Fatal error: Maximum execution time of 30 seconds exceeded in /var/www/html/wp-includes/functions.php on line 5106
Unfortunately there is no stack trace logged. And the function around line 5107 is wp_ob_end_flush_all which is called on shutdown from default-filters.php
echo do_shortcode(apply_filters('the_content', "[product_page id=815]")); did not help either (same incomplete output as
with echo do_shortcode("[product_page id=815]");)
Also totally weird:
When I compare the string of the content from the editor and the string of the shortcode added programmatically it is
equal!:
add_filter( "the_content", function ( $content ){
$wtf = "<!-- wp:paragraph -->
<p>[product_page id=815]</p>
<!-- /wp:paragraph -->";
$result = $wtf === $content;
?><pre><?php var_dump($result)?></pre><?php
return $content;
}, 1 );
But if I replace return $content with return $wtf - I get the maximimum exucution time exceeded error.
So how can I properly output a product page on the homepage ("/") or how can I get the same result with the shortcode
when applied within the the_content filter as when just adding the shortcode in the (Gutenberg) editor?
Update
Tested it with a simple custom shortcode outputting only a heading tag and it works fine with the_content filter. Also tried it on an absolutely clean site with only WooCommerce and PayPal installed - with the same results. Seems to be a bug on the WooCommerce side. Gonna run it through xDebug some day this week.
Ok, found a bit of a hacky solution. I just check on every page load whether the homepage is currently queried or not. Then I get the page content and check if it already contains the shortcode. If not then the page content gets updated in the database with the shortcode appended.
//it has to be a hook which loads everything needed for the wp_update_post function
//but at the same time has not global $post set yet
//if global $post is already set, the "certainproductpage" will load content not modified by the following code
add_action( "wp_loaded", function () {
//check if homepage
//there seems to be no other simple method to check which page is currently queried at this point
if ( $_SERVER["REQUEST_URI"] === "/" ) {
$page = get_post(get_option('page_on_front'));
$product = get_page_by_path( "certainproduct", OBJECT, "product" );
if ( $page && $product ) {
$page_content = $page->post_content;
$product_id = $product->ID;
$shortcode = "[product_page id=$product_id]";
//add shortcode to the database's post_content if not already done
$contains_shortcode = strpos( $page_content, $shortcode ) > - 1;
if ( ! $contains_shortcode ) {
$shortcode_block = <<<EOT
<!-- wp:shortcode -->
{$shortcode}
<!-- /wp:shortcode -->
EOT;
$new_content = $page_content . $shortcode_block;
wp_update_post( array(
'ID' => $page->ID,
'post_content' => $new_content,
'post_status' => "publish"
) );
}
}
}
} );
I'd recommend one step at a time. First of all, does this work?
add_filter( "the_content", function ( $content ) {
$content .= do_shortcode( '[product_page id=815]' );
return $content;
}, 1 );
This should append a product page to every WordPress page/post.
If it works, then you need to limit it to the homepage only, by using is_front_page() conditional in case it's a static page:
add_filter( "the_content", function ( $content ) {
if ( is_front_page() ) {
$content .= do_shortcode( '[product_page id=815]' );
}
return $content;
}, 1 );
If this works too, then we'll see how to return a Gutenberg paragraph block, but not sure why you'd need that, so maybe give us more context
I'm writing a tiny custom plugin to add a meta box so I can freely interface with EasyPost. It's included in the Edit Order page. I'm trying to use wc_get_order to get basic order details and the page is bombing. This looks like it should work flawlessly and be very simple, but I can't find the answer anywhere.
I'm using this code in:
/wp-content/plugins/custom-easypost/jens-custom-easypost.php
Sorry if this is a dumb question, but I'm stumped.
This code is NOT WORKING:
$order = wc_get_order( $order_id );
This code IS working:
// Add meta box
add_action( 'add_meta_boxes', 'jens_epbox' );
function jens_epbox() {
add_meta_box(
'jens-epbox-modal',
'Jens EP Box',
'jens_meta_box_callback',
'shop_order',
'side',
'high'
);
}
// Callback
function jens_meta_box_callback( $post )
{
echo 'Get Label ' . $post->ID. '';
}
I’m trying to set a sidebar in the single product page that show all products of the same categories as the product displayed.
That's how I proceed:
1) First I’ve created a sidebar called “Products_of_same_Category” to put in there a widget to show what I needed, then in function.php of my child theme I added the following snippet to execute php code in text widget:
// Enable PHP in widgets
add_filter('widget_text','execute_php',100);
function execute_php($html){
if(strpos($html,"<"."?php")!==false){
ob_start();
eval("?".">".$html);
$html=ob_get_contents();
ob_end_clean();
}
return $html;
}
2) Then when I saw that the snippet runs ok I added that code to test it:
<?php
$prod=get_the_term_list( $post->ID, 'product_cat');
echo $prod;
?>
And all worked fine, it gave me the exact name of the current category of the product displayed in the single product page.
3) So I've tried another test, deleting the previous code, to view if a shortcode translated in php should works in a widget too (writing at this time the exact category name requested, in this case "towels" - in the code below I substitute it with THE-CATEGORY-I-LIKE):
<?php echo do_shortcode('[product_category category=“THE-CATEGORY-I-LIKE” per_page="20" columns="1" orderby="title" order="desc"]'); ?>`
And all was again well done!
4) Finally I mixed all in this code to show the list of products of same categories but something goes wrong:
<?php $prod=get_the_term_list( $post->ID, 'product_cat', '', '', '' );
echo do_shortcode('[product_category category="'.$prod.'" per_page="20" columns="1" orderby="title" order="desc"]'); ?>
In last case the code doesn't display anything. I don't understand where I made mistakes, the syntax is wrong or the solving approach is illogical?
I really appreciate any help about this.
The problem is how you get the category slug. get_the_term_list will give you a formatted linked list of the categories, so it will display category names, not category slugs, which are different things. "Towels" would be your category name, but the category slug would be "towels". And product_category shortcode expect a slug, not a name.
The correct approach to get the category product slug is the following:
$terms = get_the_terms($post, 'product_cat');
if($terms && ! is_wp_error($terms)) {
foreach($terms as $term) {
echo do_shortcode('[product_category category="'.$term->slug.'" per_page="20" columns="1" orderby="title" order="desc"]');
}
}
This will display the products of all the categories associated to your product. See get_the_terms doc for reference.
In order to remove from the results the current product shown, you can make use of the woocommerce_shortcode_products_query filter. It isn't documented, but you can find it by looking at the product_category shortcode code located in includes/class-wc-shortcodes.php. In the product_category() method you will find the following line:
$return = self::product_loop( $query_args, $atts, 'product_cat' );
Where $query_args is a WP_Query parameters array. In the same class you will find the method product_loop() called here and see the following:
$products = new WP_Query( apply_filters( 'woocommerce_shortcode_products_query', $query_args, $atts ) );
So the query arguments are filtered - you will be able to work with that to add the desirated behavour. What you want to do is to use the post__not_in parameter to the query like this:
function remove_current_product_from_wc_shortcode($args, $atts) {
if(is_product()) { // check if we're on a single product page
$args['post__not_in'] = array(get_queried_object_id());
}
return $args;
}
add_filter('woocommerce_shortcode_products_query', 'remove_current_product_from_wc_shortcode');
This code should go in your theme functions.php - please not this is untested, so if it doesn't work look at the get_queried_object_id() return if it contain the current product ID.
In WordPress with the publish_{post_type} (http://codex.wordpress.org/Post_Status_Transitions) you can hook into the loop if a post with custom type is published. But publish_{post_type} is also triggers if a a post is updated.
I am basically looking for a way to check the old and new status, within the publish_post_type hook. Does anyone have a nifty idea as to how to accomplish that?
I am doing this:
function doStuff( $post_ID ) {
// do stuff
return $post_ID;
}
add_action( 'publish_ttplaned', 'doStuff' );
So basically I need to check the old and new status of the post within the fuction doStuff().
In case someone else is looking for the aswer. I ended up using Williams solution.
add_action( 'draft_to_publish', 'doStuff', 10, 1 );
add_action( 'pending_to_publish', 'doStuff', 10, 1 );
function doStuff( $post ) {
if ( get_post_type( $post ) == "my_custom_post_type" ){
// do stuff
}
}
This works since a new post starts out as a draft even if you publish it right away.
As #rnevius says, there's no hook in WordPress core called publish_post_type.
There is also publish_post - which I've just tested it to make sure it only runs when the post is first published, not when it's subsequently edited.
So you can do something like:
function my_function($post_ID, $post) {
if ("foo" == $post->post_type) {
// do something
}
}
add_action( 'publish_post', 'my_function', 10, 2 );
There is also the wp_transition_post_status(), which calls several actions:
transition_post_status with $new_status, $old_status, $post
or, if you want to do it the other way around:
{$old_status}_to_{$new_status} and passes a WP_Post object as the only parameter.