Toggle out of stock items on front end - woocommerce - wordpress

I wish to include a button on the website so that users can toggle out of stock items on and off.
By default, I want the out of stock items to be false. When the user browses around I need the setting he applies to be consistent. Is this possible?
This is what I have till now:
/*
* ADDING A SIMPLE BUTTON TO SHOW OR HIDE SOLD PRODUCTS
* source: https://www.offshorly.com/news/woocommerce-show-hide-sold-products-toggle/
*/
function hide_sold_products_param() {
global $wp;
$wp->add_query_var('hide_sold_products');
}
add_filter('init', 'hide_sold_products_param');
add_action('pre_get_posts', 'hide_sold_products_query', 10);
function hide_sold_products_query($query){
if($query->get('hide_sold_products') == 'true'){
$query->set('meta_query', array(
array(
'key' => '_stock',
'value' => '0',
'compare' => '>'
)
));
}
}
I also have a button on the sidebar to toggle the status.
Currently, it is not consistent
The default is not hiding out of stock items
Any help is greatly appreciated.

I looked more into this and came up with a solution, it is not ideal but it does work the way that I wanted it too. I think your biggest issue is you need to store the toggle on/off into the users session so that it gets saved as they navigate it. In header.php I added:
if (isset($_GET['hide_sold_products']) && $_GET['hide_sold_products'] === 'true') {
WC()->session->set( 'hide_sold_products', 1 );
}
if (isset($_GET['hide_sold_products']) && $_GET['hide_sold_products'] === 'false') {
WC()->session->set( 'hide_sold_products', 0 );
}
This stores the users hide/show value from the ?hide_sold_products= url variable.
Again the following is not ideal but I'll share, also added this to header.php
<?php
if($wp->request == 'store'){
$url = $wp->request;
} else {
$url = strstr($wp->request, '/', true);
}
if(!isset($_GET['hide_sold_products']) && $url == 'store'){
$currentUrl = "http://" . $_SERVER['HTTP_HOST'];
$hide_sold_products = WC()->session->get( 'hide_sold_products' );
if($hide_sold_products == 1){
$hide_sold_products_text = 'true';
} else {
$hide_sold_products_text = 'false';
}
?>
<script>
window.location = "<?php echo $currentUrl . '/' . $wp->request . '/?hide_sold_products=' . $hide_sold_products_text; ?>";
</script>
<?php } ?>
This checks to see if the user is trying to access the /store/ url in woocommerce and then will redirect them and add ?hide_sold_products= with the true/false from the session value then the url calls functions.php script. Also on your toggle button/text on the front end the show toggle needs to have this appended to it: ?hide_sold_products=false
Other than the JS redirection this works well for me. I tried the wp_redirect() but ran into the headers already sent issue since the code is in the header.php

Related

Woocommerce add img tag on order admin details page

I have a wordpress website where customers make an image with text and icons, once processed thru woocommerce and payed for that image name 12345.png is saved as Customer_product_image
function add_order_item_meta($item_id, $values) {
$key = 'customer_product_image'; // Define your key here
$value = $values['user_img']; // Get your value here
woocommerce_add_order_item_meta($item_id, $key, $value);
}
And i works great, but now i'm banning my head against the wall! When the purchased image is displayed on the Order admin detail page, it shows up as CUSTOMER_PRODUCT_IMAGE: 1234.png how on earth would i go about wrapping that within an image tag so the image is displayed there?
I've searched high and low on google but haven't been able to find anything, its probably that i dont know what do actually search for....
This did the trick for me!
First i added this snippet for removing the custom meta item on order detail render:
add_filter( 'woocommerce_hidden_order_itemmeta', 'hide_order_item_meta_fields' );
function hide_order_item_meta_fields( $fields ) {
$fields[] = 'current_view';
$fields[] = 'custom_image';//Add all meta keys to this array,so that it will not be displayed in order meta box
return $fields;
}
second i added it back with this, and with the desired text and image tag:
add_action( 'woocommerce_after_order_itemmeta', 'order_meta_customized_display',10, 3 );
function order_meta_customized_display( $item_id, $item, $product ){
$all_meta_data=get_metadata( 'order_item', $item_id, "", "");
$useless = array(
"_qty","_tax_class","_variation_id","_product_id","_line_subtotal","_line_total","_line_subtotal_tax","_line_tax","_line_tax_data"
);// Add key values that you want to ignore
$customized_array= array();
foreach($all_meta_data as $data_meta_key => $value) {
if(!in_array($data_meta_key,$useless)){
$newKey = ucwords(str_replace('_'," ",$data_meta_key ));//To remove underscrore and capitalize
$customized_array[$newKey]=ucwords(str_replace('_'," ",$value[0])); // Pushing each value to the new array
}
}
if (!empty($customized_array)) {
foreach($customized_array as $data_meta_key => $value){
echo "<div class='product_container'><span>Produkt Billede: </span><img src='".wp_upload_dir()['baseurl'].'/flapper/'. $value ."' /> </div>";
}
}
}
i found the answer to this question on this page
You can use the filter woocommerce_order_item_display_meta_value to output the image. Place this code in your functions.php file, you'll need to modify the src attribute of the img tag to include the appropriate URL before the filename value. You can also modify the display label with the filter woocommerce_order_item_display_meta_key
add_filter( 'woocommerce_order_item_display_meta_value', 'modify_order_item_display_value' , 10, 3 );
function modify_order_item_display_value( $display_value, $meta, $wc_order_item ) {
$meta_data = $meta->get_data();
if( $meta_data['key'] === 'customer_product_image' ) {
return '<img src="' . $meta_data['value'] . '">';
}
return $display_value;
}
add_filter('woocommerce_order_item_display_meta_key', 'modify_order_item_display_key', 10, 3);
function modify_order_item_display_key( $display_key, $meta, $wc_order_item ) {
$meta_data = $meta->get_data();
if( $meta_data['key'] === 'customer_product_image' ) {
return 'Customer Image';
}
return $display_key;
}

Show Post Title and how many days ago it got published in Wordpress

I want to customize my archive-list on my WordPress page so it displays something like this:
POST TITLE - 2 days ago
POST TITLE - 4 days ago
etc...
So far I only managed to display the post title with following code:
<?php wp_get_archives( array( 'type' => 'postbypost', 'limit' => 16) ); ?>
I have no idea how to move forward from this, any help?
The function wp_get_archives calls the function get_archives_link to prepare the output. The last step done in that function is to apply the filter by the same name as the function (i.e., get_archives_link). So to modify as you desire, define your own filter function and add that filter in your functions.php file.
For example, the following code would add a class to the output of the function get_archives_link.
function example_get_archives_link($link_html) {
if (is_day() || is_month() || is_year()) {
if (is_day()) {
$data = get_the_time('Y/m/d');
} elseif (is_month()) {
$data = get_the_time('Y/m');
} elseif (is_year()) {
$data = get_the_time('Y');
}
// Link to archive page
$link = home_url($data);
// Check if the link is in string
$strpos = strpos($link_html, $link);
// Add class if link has been found
if ($strpos !== false) {
$link_html = str_replace('<li>', '<li class="current-archive">', $link_html);
}
}
return $link_html;
}
add_filter("get_archives_link", "example_get_archives_link");
You can find more info about the filter in the Codex.

Wordpress get_permalink - always return the first post instead of the parent page?

I have set a custom page 'myblog' as 'Posts page' in 'Reading Settings', but why I always get the first post article of 'myblog' instead of 'myblog' itself?
var_dump(get_permalink()); // "http://xxxx.com/myblog/hello-world/"
It should be:
"http://xxxx.com/myblog/"
Any idea why and how I can fix this?
You can do something like this to get the permalink for your blog page (page_for_posts). Below has a couple conditionals checks for fallback, but really the call get_permalink() on the page_for_posts option is what you need.
function get_my_blogpage_permalink() {
if( 'page' == get_option( 'show_on_front' ) ) {
return get_permalink( get_option('page_for_posts' ) );
} else {
return home_url();
}
}
var_dump(get_my_blogpage_permalink());

Wordpress Menu not showing

I'm using a theme called hotheme(dot co) which seems not working properly. I added some links to my menu in the backend and linked it to "main menu" but on the frontend the inspector shows an empty
Here's the code for the menu from the header.php
`
global $wpdb;
$tablename = $wpdb->prefix.'terms'; // use always table prefix
// language support
switch ($lang){
case '':
case '1':
$menu_name = 'default';
break;
case '2':
$menu_name = 'secondary';
break;
}
$menu_id = $wpdb->get_results(
"
SELECT term_id
FROM ".$tablename."
WHERE name= '".$menu_name."'
"
);
// Empty check
if($menu_id != null){
// results in array
foreach($menu_id as $menu):
$menu_id = $menu->term_id;
endforeach;
$items = wp_get_nav_menu_items( $menu_id );
$numItems = count($items);
$i = 0;
foreach($items as $item)
{
if(++$i === $numItems) {
echo "<li class='reservation-btn custom-color-btn-back'><a href='".$item->url.$lang_link.$lang."'>".$item->title."<br /><span class='grey'>".$item->description."</span></a></li>";
$_SESSION['reservation_url'] = $item->url;
} else {
echo "<li><a href='".$item->url.$lang_link.$lang."'>".$item->title."<br /><span class='grey'>".$item->description."</span></a></li>";
}
}
} // end: empty check
?>`
Could it be possile, that the code is deprecated?
Any help would be great! Thanks
That seems like a lot of unneeded code. I am going to give you some code (alters slightly) that I wrote for a theme framework that I am working on. You can add it to the theme and see if a menu shows up or not.
Add to functions.php
function ao_register_menus() {
register_nav_menu( 'primary', 'Primary Navigation');
}
add_action( 'init', 'ao_register_menus' );
function ao_primary_nav() {
echo '<nav class="primary-navigation">';
wp_nav_menu(array(
'theme-location' => 'primary',
'container_class' => 'primary-nav-container',
'menu_class' => 'primary-nav',
));
echo '</nav>';
}
add_action('ao-primary-nav', 'ao_primary_nav');
Then after that, you should be able to add the following to replace all of the code that you showed from header.php with this:
do_action('ao-primary-nav');
Warning: Doing this will destroy the styles attached to your theme's navigation. So don't erase the code the is already there, but instead simply use this to check to see if the navigation functionality is still existent. From here we can see if the theme overall is outdated or if there are bigger underlying issues. This is not a permanent solution. However, if this works and you see A NAVIGATION then it is a good sign that we can dig into the theme further to see what exactly is going on.
You could also always check the changelog of the theme to see when it was last updated and that could be a good sign of whether or not you should use it.
Menu is working fine in Hotheme. You have to read the documentation provided in http://www.hotheme.co/page-documentation.php#doc-3-1. In Menu topic they have mentioned, name the menu as "default".

Get Woocommerce to Manage Stock as a default

Is there a hook that would allow setting the Inventory > Manage Stock checkbox in woocommerce globally?
All my products are single item quantity, so it seems pretty counter-D.R.Y to always have to remember to check it, especially for other employees.
Although this is quite late, since you asked about a hook: although there doesn't appear to be a hook, action or function specifically for turning on the Manage Stock option, you can still hook into the post save function and auto-enable it that way, since it is just a post_meta value:
add_action('save_post', 'myWoo_savePost', 10, 2);
function myWoo_savePost($postID, $post) {
if (isset($post->post_type) && $post->post_type == 'product') {
update_post_meta($post->ID, '_manage_stock', 'yes');
}
}
Note that stock levels will always default to 0, so you may also want to add the line:
update_post_meta($post->ID, '_stock', '1');
...which will update your stock quantity to 1. Do be aware that this will happen every time a product is saved, though.
I'm unsure as to whether this has knock-on effects elsewhere in WooCommerce for larger stock quantities, but as you're dealing with single-quantity items, I'd guess you're probably okay.
Update (with $update):
As of Wordpress 3.7, a third parameter was added to save_post so you can easily tell if it's a new post being created or an existing post being updated. As such, you can fire the function above only when creating a new post (which is arguably the desired effect):
add_action('save_post_product', 'myWoo_savePost', 10, 3);
function myWoo_savePost($postID, $post, $update) {
if (!$update) {
// $update is false if we're creating a new post
update_post_meta($post->ID, '_manage_stock', 'yes');
update_post_meta($post->ID, '_stock', '1');
}
}
(Thanks to Dylan for the reminder about post-type specific saves)
A little late, but here's how for anyone else needing to do this... I found most of this code somewhere else, but I don't have the link anymore to where I found it. Tweaked it a little and this is what I ended up with (add to functions.php):
add_action( 'admin_enqueue_scripts', 'wc_default_variation_stock_quantity' );
function wc_default_variation_stock_quantity() {
global $pagenow, $woocommerce;
$default_stock_quantity = 1;
$screen = get_current_screen();
if ( ( $pagenow == 'post-new.php' || $pagenow == 'post.php' || $pagenow == 'edit.php' ) && $screen->post_type == 'product' ) {
?>
<!-- uncomment this if jquery if it hasn't been included
<script src="//ajax.googleapis.com/ajax/libs/jquery/1.8.2/jquery.min.js"></script>
-->
<script type="text/javascript">
jQuery(document).ready(function(){
if ( !jQuery( '#_manage_stock' ).attr('checked') ) {
jQuery( '#_manage_stock' ).attr('checked', 'checked');
}
if ( '' === jQuery( '#_stock' ).val() ) {
jQuery( '#_stock' ).val(<?php echo $default_stock_quantity; ?>);
}
});
</script>
<?php
}
}
Woocommerce now has it's own hook for saving a product. For a simple product it's woocommerce_process_product_meta_simple.
Before updating the meta, we should first check that the _manage_stock is empty i.e. the checkbox has not been checked, so that it only triggers on products which have not already been set.
Then toggle the manage stock and set the default stock number.
function manage_stock_default( $post_id ) {
if (empty($_POST['_manage_stock'])) {
update_post_meta($post_id, '_manage_stock', 'yes');
update_post_meta($post_id, '_stock', '1');
}
}
add_action( 'woocommerce_process_product_meta_simple', 'manage_stock_default');

Resources