Change status of woocommerce products by php function - php

I have a function which help me to make a redirect of a product if that product doesn't exist anymore in my affiliate xml.
What I want now is to put the product on draft but to redirect his link to a "This products doesnt exist anymore page" - for seo purposes
I didn't try something because I dont know what.
I saw something here and I think my answear is here but i don't know how to apply it:
Change product status if prices are updated in Woocommerce 3
function my_is_post_to_delete( $is_post_to_delete, $post_id, $import ) {
$redirect_url = "https://stackoverflow.com";
if ( $import->id == 72 ) {
$redirects = get_option( '301_redirects', array() );
$redirects = maybe_unserialize( $redirects );
$url_for_post = get_the_permalink( $post_id );
$url = parse_url( $url_for_post );
if ( $url ) {
if ( ! array_key_exists( $url['path'], $redirects ) ) {
$redirects[ $url['path'] ] = $redirect_url;
update_option( '301_redirects', $redirects );
}
}
return false;
}
}
add_filter( 'wp_all_import_is_post_to_delete', 'my_is_post_to_delete', 10, 3 );
I expect that my code to remove the product from my website feed and redirect his link to a page of my website.
For seo purposes I cannot delete the product for all I just need to hide it from my shop but keep the link for google (also the pictures).

You can use WordPress function to update the status of the product where your logic of product doesn't exist anymore in my affiliate xml. exists.
function my_is_post_to_delete( $is_post_to_delete, $post_id, $import ) {
$redirect_url = "https://stackoverflow.com";
if ( $import->id == 72 ) {
/* Start Here*/
$my_product = array(
'ID' => $import->id,
'post_status' => 'draft',
);
wp_update_post( $my_product );
/* End Here*/
$redirects = get_option( '301_redirects', array() );
$redirects = maybe_unserialize( $redirects );
$url_for_post = get_the_permalink( $post_id );
$url = parse_url( $url_for_post );
if ( $url ) {
if ( ! array_key_exists( $url['path'], $redirects ) ) {
$redirects[ $url['path'] ] = $redirect_url;
update_option( '301_redirects', $redirects );
}
}
return false;
}
}
add_filter( 'wp_all_import_is_post_to_delete', 'my_is_post_to_delete', 10, 3 );

Related

Custom conditional redirections after WooCommerce checkout payment

I use Lirox One theme on Wordpress with WooCommerce. I want make custom redirections after payment:
If a customer buy product ID 333, It will be redirected to product 444 (for example).
I have make some custom code but it doesn't works, I get an error 500 (and debug is empty).
What I am doing wrong and how can I make it work?
This is my code:
add_action( 'woocommerce_thankyou', 'check_order_product_id', 1 );
function check_order_product_id( $order_id ){
$order = new WC_Order( $order_id );
$items = $order->get_items();
foreach ( $items as $item ) {
$product_id = $item['product_id'];
//* single product id
if ( $product_id == 399 ) {
// Content Title line
$url = 'http://yoursite.com/custom-url1';
}
if ( $product_id == 358 ) {
$url = 'http://yoursite.com/custom-url2';
}
if ( $product_id == 398 ) {
$url = 'http://yoursite.com/custom-url3';
}
if ( $product_id == 357) {
$url = 'http://yoursite.com/custom-url5';
}
if ( $product_id == 356) {
$url = 'http://yoursite.com/custom-url6';
}
if ( $product_id == 335) {
$url = 'http://yoursite.com/custom-url';
}
if ( $order->status != 'failed' ) {
wp_redirect($url);
exit;
}
For redirections, use a custom function hooked in WordPress template_redirect action hook, to avoid errors 500…
I have changed your code as you will see, to match your requirements. This code is made for WooCommerce version 3+:
add_action( 'template_redirect', 'conditional_redirection_after_payment');
function conditional_redirection_after_payment(){
// When "thankyou" order-received page is reached …
if ( is_wc_endpoint_url( 'order-received' ) ) {
global $wp;
// Get the order ID from the browser url
$order_id = intval( str_replace( 'checkout/order-received/', '', $wp->request ) );
// Get an instance of the WC_Order object
$order = wc_get_order( $order_id );
// If the order status is 'failed' we stop the function
if( $order->has_status( 'failed' ) ) return;
// HERE set in the array for each product ID the coresponding url final path
$product_id_url_paths = array(
'399' => '/custom-url1',
'358' => '/custom-url2',
'398' => '/custom-url3',
'357' => '/custom-url4',
'356' => '/custom-url5',
'335' => '/custom-url6',
);
// Iterating through each order items
foreach( $order->get_items() as $item_id => $item_values ){
// The Product ID
$product_id = $item_values->get_product_id();
foreach( $product_id_url_paths as $key_id => $url_path ){
if( $key_id == $product_id ){
// Product is found and ID match: we got our path url. We redirect
wp_redirect( home_url( $url_path ) );
exit(); // always exit
}
}
}
}
}
Code goes in function.php file of your active child theme (or theme) or also in any plugin file.
Code is tested and works on WC 3+
Note: In your Code you have to remove the exit which you have used after the wp_redirect. Other all will work fine. Some more References are provided below in order to have better understanding of the Concept.
Explanation: Then you Provide Redirect only for the Particular Product
ID alone not For all the Product IDS since it may lead you to the
Internal Server Error as it is in the Foreach Loop.
It is Fine using wp_redirect() for the redirection purpose.
It is correct what have you checked for the Product ID. The Thing is that you have to follow another method if the URL are to be explicitly passed.
// We don't know for sure whether this is a URL for this site,
// so we use wp_safe_redirect() to avoid an open redirect.
wp_safe_redirect( $url );
// We are trying to redirect to another site, using a hard-coded URL.
wp_redirect( 'https://example.com/some/page' );
Some More Reference:
<?php wp_redirect( home_url() ); exit; ?>
Redirects can also be external, and/or use a “Moved Permanently” code :
<?php wp_redirect( 'http://www.example-one.com', 301 ); exit; ?>
The code below redirects to the parent post URL which can be used to redirect attachment pages back to the parent.
<?php wp_redirect( get_permalink( $post->post_parent ) ); exit; ?>
Reference: https://developer.wordpress.org/reference/functions/wp_redirect/
Th accepted answer works for Woocommerce 3+, for older versions (I'm using 2.6.4) it does not. For anyone else using this version, try the following code:
add_action( 'template_redirect', 'conditional_redirection_after_payment');
function conditional_redirection_after_payment(){
// When "thankyou" order-received page is reached …
if ( is_wc_endpoint_url( 'order-received' ) ) {
global $wp;
$order_id = intval( str_replace( 'checkout/order-received/', '', $wp->request ) );
// Get an instance of the WC_Order object
$order = new WC_Order( $order_id );
// If the order status is 'failed' we stop the function
if( $order->has_status( 'failed' ) ) return;
// HERE set in the array for each product ID the coresponding url final path
$product_id_url_paths = array(
'1234' => '/your-path/'
);
// Iterating through each order items
foreach( $order->get_items() as $item){
// echo $item_id;
// The Product ID
$product_id = $item['product_id'];
foreach( $product_id_url_paths as $key_id => $url_path ){
if( $key_id == $product_id ){
// Product is found and ID match: we got our path url. We redirect
wp_redirect( home_url( $url_path ) );
exit(); // always exit
}
}
}
}
}

Conditionally Add to Cart redirect based on products IDs

I am trying to get all products to redirect to one custom page EXCEPT for 3 products which go to Checkout (this part works).
function my_custom_add_to_cart_redirect( $url ) {
if ( ! isset( $_REQUEST['add-to-cart'] ) || ! is_numeric( $_REQUEST['add-to-cart'] ) ) {
$url = get_permalink( 16 ); // URL page ID to redirect for all pages but below mentioned
return $url;
}
$product_id = apply_filters( 'woocommerce_add_to_cart_product_id', absint( $_REQUEST['add-to-cart'] ) );
// Only redirect the product IDs in the array to the checkout
if ( in_array( $product_id, array( 999, 997, 872) ) ) {
$url = WC()->cart->get_checkout_url();
}
return $url;
}
add_filter( 'woocommerce_add_to_cart_redirect', 'my_custom_add_to_cart_redirect' );
To make your code working as expected, is very simple. Below I have change a little bit your code:
add_filter( 'woocommerce_add_to_cart_redirect', 'my_custom_add_to_cart_redirect', 10, 1 );
function my_custom_add_to_cart_redirect( $url ) {
$product_id = apply_filters( 'woocommerce_add_to_cart_product_id', absint( $_REQUEST['add-to-cart'] ) );
// Only redirect the product IDs in the array to the checkout
if ( in_array( $product_id, array( 999, 997, 872) ) ) {
// This is more correct to get the checkout URL
$url = get_permalink( get_option('woocommerce_checkout_page_id') );
} else {
// All other products that are not in your array will be redirected to this URL
$url = get_permalink( 16 ); // URL page ID to redirect for all pages but below mentioned
}
return $url;
}
This code goes in function.php file of your active child theme (or theme) or also in any plugin file.
This code is tested and works.

Woocommerce. Add product SKU to url before slug

I am trying to add the woocommerce product SKU to the URL of the product. I have followed this guide (http://www.themelocation.com/how-to-add-sku-to-product-url-in-woocommerce/) which works, however I need the SKU to come before the slug.
Like this:
http://test.com/shop/category/sku-product
I have amended the code in the above link to successfully get this order in the wordpress admin area, however as you might predict, it is causing all the products to 404.
How do I go about fixing this? Some kind of htaccess redirect rule?
Here is my amended code:
function custom_meta_permalink( $link, $post ){
$post_meta = get_post_meta( $post->ID, '_sku', true );
if( empty( $post_meta ) || !is_string( $post_meta ) )
$post_meta = '';
$link = str_replace( '!!custom_field_placeholder!!', $post_meta, $link );
return $link;
}
add_filter( 'post_link', 'custom_meta_permalink', 10, 2 );
function append_sku_string( $link, $post ) {
$post_meta = get_post_meta( $post->ID, '_sku', true );
if ( 'product' == get_post_type( $post ) ) {
$end = substr($link, strrpos($link, '/') + 1);
$beg = substr($link, 0, strrpos( $link, '/' ));
$link = $beg . '/' .$post_meta.'-'.$end;
return $link;
}
}
add_filter( 'post_type_link', 'append_sku_string', 1, 2 );

Wordpress custom post type rewrite rule matches all pages

I've created a custom post type with a rewrite to use the grandparent relationship as the URL like so:
function cpt_child(){
$args = array(
//code
'rewrite' => array( 'slug' => '%grandparent%/%parent%', 'with_front' => false),
);
register_post_type( 'child', $args );
}
add_action( 'init', 'cpt_child' );
Then I update the permalink:
add_filter( 'post_type_link', 'filter_the_post_type_link', 1, 2 );
function filter_the_post_type_link( $post_link, $post ) {
switch( $post->post_type ) {
case 'child':
$post_link = get_bloginfo( 'url' );
$relationship_child = p2p_type('children_to_parents')->get_adjacent_items($post->ID);
$parent = $relationship['parent']->post_name;
$relationship_parent = p2p_type('parents_to_grandparents')->get_adjacent_items($parent['parent']->ID);
$grandparent = $relationship_parent['parent']->post_name;
$post_link .= "/{$grandparent}/";
$post_link .= "{$parent}/";
$post_link .= "{$post->post_name}";
break;
}
return $post_link;
}
This all works great, but unfortunately the rewrite rule matches regular pages as well which makes them 404.
I can prevent this by adding a custom slug, for example 'relationship': http://example.com/relationship/grandparent/parent/child
But I'd really like to use http://example.com/grandparent/parent/child and have it not break regular pages.
I might have to resort to using non native Wordpress rewrites using htaccess.
Thanks in advance!
I managed to find a solution thanks to Milo's previous answers on other related questions. I found this particular post Remove base slug in CPT & CT, use CT in permalink to be extremely helpful.
My initial CPT with grandparent relationship rewrite remains the same:
function cpt_child(){
$args = array(
//code
'rewrite' => array( 'slug' => '%grandparent%/%parent%', 'with_front' => false),
);
register_post_type( 'child', $args );
}
add_action( 'init', 'cpt_child' );
Then I update the permalink:
add_filter( 'post_type_link', 'filter_the_post_type_link', 1, 2 );
function filter_the_post_type_link( $post_link, $post ) {
switch( $post->post_type ) {
case 'child':
$post_link = get_bloginfo( 'url' );
$relationship_child = p2p_type('children_to_parents')->get_adjacent_items($post->ID);
$parent = $relationship['parent']->post_name;
$relationship_parent = p2p_type('parents_to_grandparents')->get_adjacent_items($parent['parent']->ID);
$grandparent = $relationship_parent['parent']->post_name;
$post_link .= "/{$grandparent}/";
$post_link .= "{$parent}/";
$post_link .= "{$post->post_name}";
break;
}
return $post_link;
}
Hooked into request and changed query based on request vars that match my needs. Added is_admin() check to prevent request filter from changing the CPT's back end.
// URL rewrite pages 404 fix
if ( ! is_admin() ) {
function svbr_fix_requests( $request ){
// if it's not a section request and request is not empty treat request as page or post
if( ( ! array_key_exists( 'section' , $request ) ) && ( ! empty($request) ) ){
$request['post_type'] = array( 'post', 'page' );
}
// return request vars
return $request;
}
add_filter( 'request', 'svbr_fix_requests' );
}
Because we changed the query vars we have to add template functionality.
// Use single_template filter to properly redirect to page.php and custom page templates
function svbr_get_template_file($single_template) {
global $post;
$page_custom_template = get_post_meta( $post->ID, '_wp_page_template', true );
if ($post->post_type == 'page') {
if($page_custom_template != 'default') {
// We are using a child theme, so get_stylesheet_directory()
$single_template = get_stylesheet_directory() . '/' . $page_custom_template;
}
else {
$single_template = get_template_directory() . '/page.php';
}
}
return $single_template;
}
add_filter( 'single_template', 'svbr_get_template_file' );
Last but not least we have to add the template class to the body for styling purposes.
// Add template class to body
add_filter( 'body_class', 'template_class_name' );
function template_class_name( $classes ) {
global $post;
$page_custom_template = get_post_meta( $post->ID, '_wp_page_template', true );
$page_custom_template = str_replace('.php','',$page_custom_template);
$page_custom_template = 'page-template-' . $page_custom_template;
// add 'class-name' to the $classes array
$classes[] = $page_custom_template;
// return the $classes array
return $classes;
}

If has_term, load other Wordpress theme

This is what I want to accomplish. In Wordpress I've created a taxonomy called categorie with the terms app, web and branding. When a project has the term app, I want to load another theme / blog. When a project has the term web or branding, I want to load single.php. The last one works just fine.
This is my code so far
function load_single_template($template) {
$new_template = '';
if( is_single() ) {
global $post;
if( has_term('app', 'categorie', $post) ) {
$new_template = get_theme_roots('themeApp');
} else {
$new_template = locate_template(array('single.php' ));
}
}
return ('' != $new_template) ? $new_template : $template;
}
add_action('template_include', 'load_single_template');
So when a project has the term app, I want to load the theme themeApp. Any suggestions? Thanks in advance.
We had to accomplish a similar task in our plugin, AppPresser. You can see our solution here: https://github.com/WebDevStudios/AppPresser/blob/master/inc/theme-switcher.php
Basically, you need to change the theme name in 3 filters: 'template', 'option_template', 'option_stylesheet'.
Getting the category is not so simple though, because the template check happens early enough in the WordPress process that the global $post and $wp_query objects are not available.
Here is one way that can be accomplished:
<?php
add_action( 'setup_theme', 'maybe_theme_switch', 10000 );
function maybe_theme_switch() {
// Not on admin
if ( is_admin() )
return;
$taxonomy = 'category';
$term_slug_to_check = 'uncategorized';
$post_type = 'post';
// This is one way to check if we're on a category archive page
if ( false !== stripos( $_SERVER['REQUEST_URI'], $taxonomy ) ) {
// Remove the taxonomy and directory slashes and it SHOULD leave us with just the term slug
$term_slug = str_ireplace( array( '/', $taxonomy ), '', $_SERVER['REQUEST_URI'] );
// If the term slug matches the one we're checking, do our switch
if ( $term_slug == $term_slug_to_check ) {
return yes_do_theme_switch();
}
}
// Try to get post slug from the URL since the global $post object isn't available this early
$post = get_page_by_path( $_SERVER['REQUEST_URI'], OBJECT, $post_type );
if ( ! $post )
return;
// Get the post's categories
$cats = get_the_terms( $post, $taxonomy );
if ( ! $cats )
return;
// filter out just the category slugs
$term_slugs = wp_list_pluck( $cats, 'slug' );
if ( ! $term_slugs )
return;
// Check if our category to check is there
$is_app_category = in_array( $term_slug_to_check, $term_slugs );
if ( ! $is_app_category )
return;
yes_do_theme_switch();
}
function yes_do_theme_switch( $template ) {
// Ok, switch the current theme.
add_filter( 'template', 'switch_to_my_app_theme' );
add_filter( 'option_template', 'switch_to_my_app_theme' );
add_filter( 'option_stylesheet', 'switch_to_my_app_theme' );
}
function switch_to_my_app_theme( $template ) {
// Your theme slug
$template = 'your-app-theme';
return $template;
}

Categories