Add action in theme quick view Wordpress Woocommerce - php

Got stucked. I need to insert a code in theme quick view - the action is : do_action( 'iworks_omnibus_wc_lowest_price_message' );
THE CODE IS:
<?php
/**
* Display product quickview.
*
* #package Razzi
* #version 1.0.0
*/
use Razzi\Helper;
if ( ! defined( 'ABSPATH' ) ) {
exit; // Exit if accessed directly
}
global $product;
$classes = wc_get_product_class( '', $product );
if ( Helper::get_option( 'product_add_to_cart_ajax' ) ) {
$classes[] = 'product-add-to-cart-ajax';
}
if ( get_option( 'rz_buy_now' ) == 'yes' ) {
$classes[] = 'has-buy-now';
}
$classes[] = 'product-is-quickview';
do_action('woocommerce_before_single_product');
?>
<div class="<?php echo esc_attr( implode( ' ', $classes ) ); ?>">
<div class="entry-thumbnail">
<?php
/**
* Hook: razzi_woocommerce_product_quickview_thumbnail
*
* #hooked woocommerce_show_product_sale_flash - 5
* #hooked woocommerce_show_product_images - 10
* #hooked product_quick_view_more_info_button - 15
*
*/
do_action( 'razzi_woocommerce_product_quickview_thumbnail' );
?>
</div>
<div class="summary entry-summary razzi-scrollbar">
<?php
/**
* Hook: razzi_woocommerce_product_quickview_summary
*
* #hooked woocommerce_template_single_rating - 10
* #hooked woocommerce_template_single_title - 20
* #hooked open_price_box_wrapper - 30
* #hooked woocommerce_template_single_price - 40
* #hooked product_availability - 50
* #hooked close_price_box_wrapper - 60
* #hooked woocommerce_template_single_excerpt - 70
* #hooked woocommerce_template_single_add_to_cart - 80
* #hooked woocommerce_template_single_meta - 90
*
*/
do_action( 'razzi_woocommerce_product_quickview_summary' );
?>
</div>
</div>
<?php
and
<?php
/**
* WooCommerce Quick View template hooks.
*
* #package Razzi
*/
namespace Razzi\WooCommerce\Modules;
use Razzi\Helper;
if ( ! defined( 'ABSPATH' ) ) {
exit; // Exit if accessed directly.
}
/**
* Class of Product Quick View
*/
class Quick_View {
/**
* Instance
*
* #var $instance
*/
protected static $instance = null;
/**
* Initiator
*
* #since 1.0.0
* #return object
*/
public static function instance() {
if ( is_null( self::$instance ) ) {
self::$instance = new self();
}
return self::$instance;
}
/**
* Instantiate the object.
*
* #since 1.0.0
*
* #return void
*/
public function __construct() {
// Quick view modal.
add_action( 'wc_ajax_product_quick_view', array( $this, 'quick_view' ) );
add_action( 'razzi_woocommerce_product_quickview_thumbnail', 'woocommerce_show_product_images', 10 );
add_action( 'razzi_woocommerce_product_quickview_thumbnail', array(
$this,
'product_quick_view_more_info_button'
) );
add_action( 'razzi_woocommerce_product_quickview_summary', 'woocommerce_template_single_rating', 10 );
add_action( 'razzi_woocommerce_product_quickview_summary', 'woocommerce_template_single_title', 20 );
add_action( 'razzi_woocommerce_product_quickview_summary', array(
$this,
'open_price_box_wrapper'
), 30 );
if ( apply_filters( 'razzi_product_show_price', true ) ) {
add_action( 'razzi_woocommerce_product_quickview_summary', 'woocommerce_template_single_price', 40 );
}
add_action( 'razzi_woocommerce_product_quickview_summary', array(
\Razzi\WooCommerce\Helper::instance(),
'product_availability'
), 50 );
add_action( 'razzi_woocommerce_product_quickview_summary', array(
$this,
'close_price_box_wrapper'
), 60 );
add_action( 'razzi_woocommerce_product_quickview_summary', 'woocommerce_template_single_excerpt', 70 );
add_action( 'razzi_woocommerce_product_quickview_summary', 'woocommerce_template_single_add_to_cart', 80 );
add_action( 'razzi_woocommerce_product_quickview_summary', 'woocommerce_template_single_meta', 90 );
add_action( 'wp_footer', array( $this, 'quick_view_modal' ), 40 );
}
/**
* Open button wrapper
*
* #since 1.0.0
*
* #return void
*/
public function open_price_box_wrapper() {
echo '<div class="summary-price-box">';
}
/**
* Close button wrapper
*
* #since 1.0.0
*
* #return void
*/
public function close_price_box_wrapper() {
echo '</div>';
}
/**
* Product quick view template.
*
* #since 1.0.0
*
* #return void
*/
public function quick_view() {
if ( empty( $_POST['product_id'] ) ) {
wp_send_json_error( esc_html__( 'No product.', 'razzi' ) );
exit;
}
$post_object = get_post( $_POST['product_id'] );
if ( ! $post_object || ! in_array( $post_object->post_type, array(
'product',
'product_variation',
true
) ) ) {
wp_send_json_error( esc_html__( 'Invalid product.', 'razzi' ) );
exit;
}
$GLOBALS['post'] = $post_object;
wc_setup_product_data( $post_object );
ob_start();
wc_get_template( 'content-product-quickview.php', array(
'post_object' => $post_object,
) );
wp_reset_postdata();
wc_setup_product_data( $GLOBALS['post'] );
$output = ob_get_clean();
wp_send_json_success( $output );
exit;
}
/**
* Quick view modal.
*
* #since 1.0.0
*
* #return void
*/
public function quick_view_modal() {
if( Helper::is_cartflows_template() ) {
return;
}
$featured_icons = (array) Helper::get_option( 'product_loop_featured_icons' );
if ( ! in_array( 'qview', $featured_icons ) ) {
return;
}
?>
<div id="quick-view-modal" class="quick-view-modal rz-modal single-product">
<div class="off-modal-layer"></div>
<div class="modal-content container woocommerce">
<div class="button-close active">
<?php echo \Razzi\Icon::get_svg( 'close' ) ?>
</div>
<div class="product"></div>
</div>
<div class="razzi-posts__loading">
<div class="razzi-loading"></div>
</div>
</div>
<?php
}
/**
* Quick view more info button
*
* #since 1.0.0
*
* #return void
*/
public function product_quick_view_more_info_button() {
printf(
'<a href="%s" class="product-more-infor">
<span class="product-more-infor__text">%s</span>%s
</a>',
is_customize_preview() ? '#' : esc_url( get_permalink() ),
apply_filters( 'product_quick_view_more_infor_text', esc_html__( 'More Product Info', 'razzi' ) ),
\Razzi\Icon::get_svg( 'infor', '', 'shop' )
);
}
}
Got many errors making customizations on that. Thanks in advance.
I was trying to show omnibus price from the plugin called Omnibus — show the lowest price by Marcin Pietrzak in the theme quick view.

Related

Call to undefined function apply_filters in wordpress

I have a problem with index.php
When I made a program running for the page on the server
I found a message.
This template works well on WordPress, but when I run it on the server, a message appears
Fatal error: Uncaught Error: Call to undefined function apply_filters() in C:\xampp\htdocs\mysite\index.php:15 Stack trace: #0 {main} thrown in C:\xampp\htdocs\mysite\index.php on line 15
<?php
/**
* Index template.
*
* #package Neve
*/
/**
* Filters the container classes.
*
* #param string $classes Container classes.
*
* #since 1.0.0
*/
$container_class = apply_filters( 'neve_container_class_filter', 'container', 'blog-archive' );
get_header();
?>
<div class="<?php echo esc_attr( $container_class ); ?> archive-container">
<div class="row">
<?php
/**
* Executes the rendering function for the sidebar.
*
* #param string $context Sidebar context.
* #param string $position Sidebar position.
*
* #since 1.0.0
*/
do_action( 'neve_do_sidebar', 'blog-archive', 'left' );
?>
<div class="nv-index-posts blog col">
<?php
/**
* Executes actions before the posts loop start.
*
* #since 2.4.0
*/
do_action( 'neve_before_loop' );
/**
* Executes the rendering function for the page header.
*
* #param string $context Header display page.
*
* #since 2.3.10
*/
do_action( 'neve_page_header', 'index' );
/**
* Executes actions before the post loop.
*
* #since 2.3.10
*/
do_action( 'neve_before_posts_loop' );
$current_post_type = get_post_type();
$should_add_hook = ! in_array( $current_post_type, array( 'post', 'page', 'product' ) );
if ( have_posts() ) {
/* Start the Loop. */
echo '<div class="posts-wrapper row">';
$pagination_type = get_theme_mod( 'neve_pagination_type', 'number' );
if ( $pagination_type !== 'infinite' ) {
global $wp_query;
$posts_on_current_page = $wp_query->post_count;
$hook_after_post = -1;
if ( $posts_on_current_page >= 2 ) {
$hook_after_post = (int) ceil( $posts_on_current_page / 2 );
}
$post_index = 1;
}
if ( $should_add_hook ) {
/**
* Executes actions before a post loop.
*
* The dynamic portion of the hook name, $current_post_type, refers to the post type slug.
* This hook is not available for the following post types: post, page, product.
*
* Possible action names include:
* - neve_loop_attachment_before
* - neve_loop_acme_product_before
*
* #since 2.11
*/
do_action( 'neve_loop_' . $current_post_type . '_before' );
}
while ( have_posts() ) {
the_post();
if ( $should_add_hook ) {
/**
* Executes actions before a post loop entry.
*
* The dynamic portion of the hook name, $current_post_type, refers to the post type slug.
* This hook is not available for the following post types: post, page, product.
*
* Possible action names include:
* - neve_loop_attachment_entry_before
* - neve_loop_acme_product_entry_before
*
* #since 2.11
*/
do_action( 'neve_loop_' . $current_post_type . '_entry_before' );
}
/**
* Executes actions before rendering the post content.
*
* #since 2.11
*/
do_action( 'neve_loop_entry_before' );
get_template_part( 'template-parts/content', get_post_type() );
if ( $pagination_type !== 'infinite' ) {
if ( $post_index === $hook_after_post && $hook_after_post !== - 1 ) {
/**
* Executes actions in the middle of the loop.
*
* The actions only fires if the pagination is not set as "infinite scroll".
*
* #since 2.3.10
*/
do_action( 'neve_middle_posts_loop' );
}
$post_index ++;
}
/**
* Executes actions after rendering the post content.
*
* #since 2.11
*/
do_action( 'neve_loop_entry_after' );
if ( $should_add_hook ) {
/**
* Executes actions after a post loop entry.
*
* The dynamic portion of the hook name, $current_post_type, refers to the post type slug.
* This hook is not available for the following post types: post, page, product.
*
* Possible action names include:
* - neve_loop_attachment_entry_after
* - neve_loop_acme_product_entry_after
*
* #since 2.11
*/
do_action( 'neve_loop_' . $current_post_type . '_entry_after' );
}
}
echo '</div>';
if ( ! is_singular() ) {
/**
* Executes the rendering function for the pagination.
*
* #param string $context Pagination location context.
*/
do_action( 'neve_do_pagination', 'blog-archive' );
}
} else {
get_template_part( 'template-parts/content', 'none' );
}
?>
<div class="w-100"></div>
<?php
/**
* Executes actions after the post loop.
*
* #since 2.3.10
*/
do_action( 'neve_after_posts_loop' );
if ( $should_add_hook ) {
/**
* Executes actions after a post loop.
*
* The dynamic portion of the hook name, $current_post_type, refers to the post type slug.
* This hook is not available for the following post types: post, page, product.
*
* Possible action names include:
* - neve_loop_attachment_after
* - neve_loop_acme_product_after
*
* #since 2.11
*/
do_action( 'neve_loop_' . $current_post_type . '_after' );
}
?>
</div>
<?php
do_action( 'neve_do_sidebar', 'blog-archive', 'right' );
?>
</div>
</div>
<?php
get_footer();

How to call a functions/classes without using shortcodes | Wordpress?

So i have a question - regarding WordPress plugins specifically shortcodes
Additional Info >
CMS : Wordpress (5.7.1)
Language : PHP 7< , JS
Plugin : Ultimate Member
i looking for a way to call the profile functions outside the plugin __DIR__ into the wordpress theme ( 2021 theme ) without using the plugin shortcodes (ultimate member )
-just to call it manually in custom template in theme folder
why ?
i built a custom JS,HTML5,CSS webpage and i want to call
[ username , email , user account information ]
profile shortcode ( ultimate member ) == " [ultimatemember form_id="76"] "
OUTPUT :
A Picture Of The Profile Portal
Everything works okay
Now how can i call that profile portal without the short code ?
here's what i tried to do
UMDIR = Ultimate Member Plugin Directory
UMDIR : wp-content\plugins\ultimate-member\includes\core\class-shortcodes.php
# Shortcode
558: function ultimatemember( $args = array() ) {
559:
560: return $this->load( $args );
561: }
return $this->load( $args );
This Line Is Responsible to load the functions that Ultimate Member Need to run the profile portal
#Load a module with global function
569: function load( $args ) {
570: $defaults = array();
571: $args = wp_parse_args( $args, $defaults );
572:
573: // when to not continue
$this->form_id = isset( $args['form_id'] ) ? $args['form_id'] : null;
if ( ! $this->form_id ) {
return;
}
$this->form_status = get_post_status( $this->form_id );
if ( $this->form_status != 'publish' ) {
return;
}
// get data into one global array
$post_data = UM()->query()->post_data( $this->form_id );
$args = array_merge( $args, $post_data );
ob_start();
/**
* UM hook
*
* #type filter
* #title um_pre_args_setup
* #description Change arguments on load shortcode
* #input_vars
* [{"var":"$post_data","type":"string","desc":"$_POST data"}]
* #change_log
* ["Since: 2.0"]
* #usage
* <?php add_filter( 'um_pre_args_setup', 'function_name', 10, 1 ); ?>
* #example
* <?php
* add_filter( 'um_pre_args_setup', 'my_pre_args_setup', 10, 1 );
* function my_pre_args_setup( $post_data ) {
* // your code here
* return $post_data;
* }
* ?>
*/
$args = apply_filters( 'um_pre_args_setup', $args );
if ( ! isset( $args['template'] ) ) {
$args['template'] = '';
}
if ( isset( $post_data['template'] ) && $post_data['template'] != $args['template'] ) {
$args['template'] = $post_data['template'];
}
if ( ! $this->template_exists( $args['template'] ) ) {
$args['template'] = $post_data['mode'];
}
if ( ! isset( $post_data['template'] ) ) {
$post_data['template'] = $post_data['mode'];
}
if ( 'directory' == $args['mode'] ) {
wp_enqueue_script( 'um_members' );
if ( is_rtl() ) {
wp_enqueue_style( 'um_members_rtl' );
} else {
wp_enqueue_style( 'um_members' );
}
}
if ( 'directory' != $args['mode'] ) {
$args = array_merge( $post_data, $args );
if ( empty( $args['use_custom_settings'] ) ) {
$args = array_merge( $args, $this->get_css_args( $args ) );
} else {
$args = array_merge( $this->get_css_args( $args ), $args );
}
}
// filter for arguments
/**
* UM hook
*
* #type filter
* #title um_shortcode_args_filter
* #description Change arguments on load shortcode
* #input_vars
* [{"var":"$args","type":"string","desc":"Shortcode arguments"}]
* #change_log
* ["Since: 2.0"]
* #usage
* <?php add_filter( 'um_shortcode_args_filter', 'function_name', 10, 1 ); ?>
* #example
* <?php
* add_filter( 'um_shortcode_args_filter', 'my_shortcode_args', 10, 1 );
* function my_shortcode_args( $args ) {
* // your code here
* return $args;
* }
* ?>
*/
$args = apply_filters( 'um_shortcode_args_filter', $args );
/**
* #var string $mode
*/
extract( $args, EXTR_SKIP );
//not display on admin preview
if ( empty( $_POST['act_id'] ) || $_POST['act_id'] != 'um_admin_preview_form' ) {
if ( 'register' == $mode && is_user_logged_in() ) {
ob_get_clean();
return __( 'You are already registered', 'ultimate-member' );
}
}
// for profiles only
if ( $mode == 'profile' && um_profile_id() ) {
//set requested user if it's not setup from permalinks (for not profile page in edit mode)
if ( ! um_get_requested_user() ) {
um_set_requested_user( um_profile_id() );
}
if ( ! empty( $args['use_custom_settings'] ) ) { // Option "Apply custom settings to this form"
if ( ! empty( $args['role'] ) ) { // Option "Make this profile form role-specific"
// show the first Profile Form with role selected, don't show profile forms below the page with other role-specific setting
if ( empty( $this->profile_role ) ) {
$current_user_roles = UM()->roles()->get_all_user_roles( um_profile_id() );
if ( empty( $current_user_roles ) ) {
ob_get_clean();
return '';
} elseif ( is_array( $args['role'] ) ) {
if ( ! count( array_intersect( $args['role'], $current_user_roles ) ) ) {
ob_get_clean();
return '';
}
} else {
if ( ! in_array( $args['role'], $current_user_roles ) ) {
ob_get_clean();
return '';
}
}
$this->profile_role = $args['role'];
} else {
ob_get_clean();
return '';
}
}
}
}
/**
* UM hook
*
* #type action
* #title um_pre_{$mode}_shortcode
* #description Action pre-load form shortcode
* #input_vars
* [{"var":"$args","type":"array","desc":"Form shortcode pre-loading"}]
* #change_log
* ["Since: 2.0"]
* #usage add_action( 'um_pre_{$mode}_shortcode', 'function_name', 10, 1 );
* #example
* <?php
* add_action( 'um_pre_{$mode}_shortcode', 'my_pre_shortcode', 10, 1 );
* function my_pre_shortcode( $args ) {
* // your code here
* }
* ?>
*/
do_action( "um_pre_{$mode}_shortcode", $args );
/**
* UM hook
*
* #type action
* #title um_before_form_is_loaded
* #description Action pre-load form shortcode
* #input_vars
* [{"var":"$args","type":"array","desc":"Form shortcode pre-loading"}]
* #change_log
* ["Since: 2.0"]
* #usage add_action( 'um_before_form_is_loaded', 'function_name', 10, 1 );
* #example
* <?php
* add_action( 'um_before_form_is_loaded', 'my_pre_shortcode', 10, 1 );
* function my_pre_shortcode( $args ) {
* // your code here
* }
* ?>
*/
do_action( "um_before_form_is_loaded", $args );
/**
* UM hook
*
* #type action
* #title um_before_{$mode}_form_is_loaded
* #description Action pre-load form shortcode
* #input_vars
* [{"var":"$args","type":"array","desc":"Form shortcode pre-loading"}]
* #change_log
* ["Since: 2.0"]
* #usage add_action( 'um_before_{$mode}_form_is_loaded', 'function_name', 10, 1 );
* #example
* <?php
* add_action( 'um_before_{$mode}_form_is_loaded', 'my_pre_shortcode', 10, 1 );
* function my_pre_shortcode( $args ) {
* // your code here
* }
* ?>
*/
do_action( "um_before_{$mode}_form_is_loaded", $args );
$this->template_load( $template, $args );
$this->dynamic_css( $args );
if ( um_get_requested_user() || $mode == 'logout' ) {
um_reset_user();
}
/**
* UM hook
*
* #type action
* #title um_after_everything_output
* #description Action after load shortcode content
* #change_log
* ["Since: 2.0"]
* #usage add_action( 'um_after_everything_output', 'function_name', 10 );
* #example
* <?php
* add_action( 'um_after_everything_output', 'my_after_everything_output', 10 );
* function my_after_everything_output() {
* // your code here
* }
* ?>
*/
do_action( 'um_after_everything_output' );
$output = ob_get_clean();
813: return $output;
814: }
And just to clearfiy all of them inside a namespace called
namespace um\core;
and inside a class Shortcodes
so when i try and call ( still testing in the same folder ) ( inside the class )
ultimatemember();
this error shows up
syntax error, unexpected identifier "ultimatemember", expecting "function" or "const" in
HOW ?
expecting "function"
Isn't ultimatemember(); a function ??
and if i called it outside the class it return as undefined function
Uncaught Error: Call to undefined function um\core\ultimatemember()
This question has been answered by #amarinediary
You have to call the class variable name before the method
like this
class Shortcode{
function runme{
//code
}}
this is how you call it
$classin = new Shortcodes();
$classin-> ultimatemember();

WooCommerce: Disable product loop without touching the template

I want to remove the product loop on some archive pages.
In my case if the current archive is a vendor archive. But I guess the why isn't too important.
At the moment I'm using a custom archive-product.php.
I added and if/else condition around this part of the template code:
if ( woocommerce_product_loop() ) {
/**
* Hook: woocommerce_before_shop_loop.
*
* #hooked woocommerce_output_all_notices - 10
* #hooked woocommerce_result_count - 20
* #hooked woocommerce_catalog_ordering - 30
*/
do_action( 'woocommerce_before_shop_loop' );
woocommerce_product_loop_start();
if ( wc_get_loop_prop( 'total' ) ) {
while ( have_posts() ) {
the_post();
/**
* Hook: woocommerce_shop_loop.
*/
do_action( 'woocommerce_shop_loop' );
wc_get_template_part( 'content', 'product' );
}
}
woocommerce_product_loop_end();
/**
* Hook: woocommerce_after_shop_loop.
*
* #hooked woocommerce_pagination - 10
*/
do_action( 'woocommerce_after_shop_loop' );
} else {
/**
* Hook: woocommerce_no_products_found.
*
* #hooked wc_no_products_found - 10
*/
do_action( 'woocommerce_no_products_found' );
}
It works but I had to edit the theme file.
I saw that there is an if/else for the loop itself:
if ( woocommerce_product_loop() ) {
Can I hook this part to disable the loop without touching the archive-product.php?

Create couple of unique classes repeating in a loop Woocommerce shop loop

I want to make couple of unique classes, like class1, class2 up to 6 or 7 added to 6 or 7 products in the shop loop.
I'd like to make these 6/7 products with unique class doubled to make it 12/14 products on the page in shop catalague.
I tried editing content-product.php file and archive-page.php.
I added this code to content product file:
<?php
$x = 1;
?>
<li class="columns class<?php echo esc_attr($x++); ?>">
But it does not add any extra number to another product.
It only add +1 if there is another div class inside that li with this php code:
<?php echo esc_attr($x++); ?>">
added to the class, but it does not apply to another li with the next product.
Any ideas how to achieve that?
Ok I found the solution.
<?php
$x = 1;
?>
<li class="columns class<?php echo esc_attr($x++); ?>">
this code only works within one file of php so I needed to keep everything in one php file,
exactly in archive-product.php
Instead of keeping this reference to another php file
<?php wc_get_template_part( 'content', 'product' ); ?>
I took all the content from the content product and added it in archive-product.php
so $x code could work.
That's how the code of archive-product.php looks like and it works perfectly:
defined( 'ABSPATH' ) || exit;
get_header( 'shop' );
do_action( 'woocommerce_before_main_content' );
?>
<header class="woocommerce-products-header">
<?php if ( apply_filters( 'woocommerce_show_page_title', true ) ) : ?>
<h1 class="woocommerce-products-header__title page-title"><?php
woocommerce_page_title(); ?></h1>
<?php endif; ?>
<?php
/**
* Hook: woocommerce_archive_description.
*
* #hooked woocommerce_taxonomy_archive_description - 10
* #hooked woocommerce_product_archive_description - 10
*/
do_action( 'woocommerce_archive_description' );
?>
</header>
<?php
if ( woocommerce_product_loop() ) {
/**
* Hook: woocommerce_before_shop_loop.
*
* #hooked woocommerce_output_all_notices - 10
* #hooked woocommerce_result_count - 20
* #hooked woocommerce_catalog_ordering - 30
*/
do_action( 'woocommerce_before_shop_loop' );
}
?>
<div class="products">
<?php
$one = 1;
$args = array(
'post_type' => 'product',
'posts_per_page' => 12
);
$loop = new WP_Query( $args );
if ( $loop->have_posts() ) {
while ( $loop->have_posts() ) : $loop->the_post();
?>
<div class="columns product<?php echo esc_attr($one++); ?>">
<div class="column is-one-third">
<?php
defined( 'ABSPATH' ) || exit;
global $product;
// Ensure visibility.
if ( empty( $product ) || ! $product->is_visible() ) {
return;
}
/**
* Hook: woocommerce_before_shop_loop_item.
*
* #hooked woocommerce_template_loop_product_link_open - 10
*/
do_action( 'woocommerce_before_shop_loop_item' );
/**
* Hook: woocommerce_before_shop_loop_item_title.
*
* #hooked woocommerce_show_product_loop_sale_flash - 10
* #hooked woocommerce_template_loop_product_thumbnail - 10
*/
do_action( 'woocommerce_before_shop_loop_item_title' );
/**
*
* close link
*/
do_action( 'woocommerce_shop_loop_close_link' );
?>
</div>
<div class="column">
<?php
/**
* Hook: woocommerce_before_shop_loop_item.
*
* #hooked woocommerce_template_loop_product_link_open - 10
*/
do_action( 'woocommerce_before_shop_loop_item' );
/**
* Hook: woocommerce_shop_loop_item_title.
*
* #hooked woocommerce_template_loop_product_title - 10
*/
do_action( 'woocommerce_shop_loop_item_title' );
/**
* Hook: woocommerce_after_shop_loop_item_title.
*
* #hooked woocommerce_template_loop_rating - 5
* #hooked woocommerce_template_loop_price - 10
*/
do_action( 'woocommerce_after_shop_loop_item_title' );
/**
* Hook: woocommerce_after_shop_loop_item.
*
* #hooked add to cart
*/
do_action( 'woocommerce_after_shop_loop_item' );
/**
*
* close link
*/
do_action( 'woocommerce_shop_loop_close_link' );
?>
</div>
</div>
<?php
endwhile;
} else {
echo __( 'Nie znaleziono produktów' );
}
wp_reset_postdata();
?>
</div><!--/.products-->
<?php
do_action( 'woocommerce_after_shop_loop' );
get_footer( 'shop' );
Actually my final awnser is a bit different.
Previous one did not work with select/options for order by and probably for more than that. The proper solution for archive-page.php is:
defined( 'ABSPATH' ) || exit;
get_header( 'shop' );
/**
* Hook: woocommerce_before_main_content.
*
* #hooked woocommerce_output_content_wrapper - 10 (outputs opening
divs for the content)
* #hooked woocommerce_breadcrumb - 20
* #hooked WC_Structured_Data::generate_website_data() - 30
*/
do_action( 'woocommerce_before_main_content' );
?>
<header class="woocommerce-products-header">
<?php if ( apply_filters( 'woocommerce_show_page_title', true ) ) : ?>
<h1 class="woocommerce-products-header__title page-title"><?php woocommerce_page_title(); ?></h1>
<?php endif; ?>
<?php
/**
* Hook: woocommerce_archive_description.
*
* #hooked woocommerce_taxonomy_archive_description - 10
* #hooked woocommerce_product_archive_description - 10
*/
do_action( 'woocommerce_archive_description' );
?>
</header>
<?php
woocommerce_product_loop_start();
$one = 1;
if ( wc_get_loop_prop( 'total' ) ) {
while ( have_posts() ) {
the_post();
?>
<div class="columns product<?php echo esc_attr($one++); ?>">
<?php
/**
* Hook: woocommerce_shop_loop.
*
* #hooked WC_Structured_Data::generate_product_data() - 10
*/
do_action( 'woocommerce_shop_loop' );
wc_get_template_part( 'content', 'product' );
}
}
woocommerce_product_loop_end();
?>
</div>
<?php
/**
* Hook: woocommerce_after_shop_loop.
*
* #hooked woocommerce_pagination - 10
*/
do_action( 'woocommerce_after_shop_loop' );
} else {
/**
* Hook: woocommerce_no_products_found.
*
* #hooked wc_no_products_found - 10
*/
do_action( 'woocommerce_no_products_found' );
}
/**
* Hook: woocommerce_after_main_content.
*
* #hooked woocommerce_output_content_wrapper_end - 10 (outputs closing divs for the
content)
*/
do_action( 'woocommerce_after_main_content' );
/**
* Hook: woocommerce_sidebar.
*
* #hooked woocommerce_get_sidebar - 10
*/
do_action( 'woocommerce_sidebar' );
get_footer( 'shop' );

Add Shipping Email On Woocommerce Checkout And Send Email Notification

I want to add a extra email filed on woocommerce checkout page in the shipping area and send a order copy to that email, is it possible to do?
Was trying for quit long time to solve this but couldn't find a solution. Hope anyone can help me on this
Ah yes, I had forgotten that I posted that. Here is the complete, updated plugin. Newer versions of WooCommerce require the email recipients to be a comma-separated spring. The old version of my plugin was returning an array, which WooCommerce could not process.
<?php
/*
Plugin Name: WooCommerce Shipping Email
Plugin URI: https://gist.github.com/helgatheviking/d2975aa4d190a5b55922#
Description: Add a shipping email field to checkout and notify of new orders
Version: 1.0.1
Author: Kathy Darling
Author URI: http://kathyisawesome.com
Requires at least: 4.0
Tested up to: 4.0
Copyright: © 2014 Kathy Darling.
License: GNU General Public License v3.0
License URI: http://www.gnu.org/licenses/gpl-3.0.html
*/
/**
* The Main WC_Shipping_Email class
**/
if ( ! class_exists( 'WC_Shipping_Email' ) ) :
class WC_Shipping_Email {
/**
* #var WC_Shipping_Email - the single instance of the class
* #since 1.0
*/
protected static $_instance = null;
/**
* Main WC_Shipping_Email Instance
*
* Ensures only one instance of WC_Shipping_Email is loaded or can be loaded.
*
* #static
* #see WC_Shipping_Email()
* #return WC_Shipping_Email - Main instance
* #since 1.0
*/
public static function instance() {
if ( is_null( self::$_instance ) ) {
self::$_instance = new self();
}
return self::$_instance;
}
/**
* Cloning is forbidden.
*
* #since 1.0
*/
public function __clone() {
_doing_it_wrong( __FUNCTION__, __( 'Cheatin’ huh?', 'woocommerce-mix-and-match' ), '2.0' );
}
/**
* Unserializing instances of this class is forbidden.
*
* #since 1.0
*/
public function __wakeup() {
_doing_it_wrong( __FUNCTION__, __( 'Cheatin’ huh?', 'mix-and-match' ), '2.0' );
}
/**
* WC_Shipping_Email Constructor
*
* #access public
* #return WC_Shipping_Email
* #since 1.0
*/
public function __construct() {
$this->id = 'email';
$this->meta = '_shipping_email';
$this->label = __( 'Shipping Email', 'woocommerce-shipping-email' );
// add email field to checkout
add_filter( 'woocommerce_shipping_fields' , array( $this, 'add_shipping_fields' ) );
add_filter( 'woocommerce_admin_shipping_fields' , array( $this, 'admin_shipping_fields' ) );
// add recipient to specific emails
add_filter( 'woocommerce_email_recipient_customer_processing_order' , array( $this, 'add_recipient' ), 20, 2 );
add_filter( 'woocommerce_email_recipient_customer_completed_order' , array( $this, 'add_recipient' ), 20, 2 );
add_filter( 'woocommerce_email_recipient_customer_note' , array( $this, 'add_recipient' ), 20, 2 );
// display meta key in order overview
add_action( 'woocommerce_order_details_after_customer_details' , array( $this, 'after_customer_details' ) );
// display meta key in email
add_action( 'woocommerce_before_template_part' , array( $this, 'before_email_addresses' ), 10, 4 );
}
/*-----------------------------------------------------------------------------------*/
/* Plugin Functions */
/*-----------------------------------------------------------------------------------*/
/**
* Add email to front-end shipping fields
*
* #var array $fields
* #return array
* #since 1.0
*/
function add_shipping_fields( $fields ) {
$fields['shipping_' . $this->id] = array(
'label' => $this->label,
'required' => true,
'class' => array( 'form-row-first' ),
'validate' => array( 'email' ),
);
return $fields;
}
/**
* Add email to Admin Order overview
*
* #var array $fields
* #return array
* #since 1.0
*/
function admin_shipping_fields( $fields ) {
$fields[$this->id] = array(
'label' => $this->label
);
return $fields;
}
/**
* Add recipient to emails
*
* #var string $email
* #return string
* #since 1.0
*/
function add_recipient( $email, $order ) {
$additional_email = get_post_meta( $order->id, $this->meta, true );
if( $additional_email && is_email( $additional_email )){
if( is_array( $email ) ){
$email = explode( ',', $email );
array_push( $email, $additional_email );
$email = implode( ',', $email );
} elseif( is_string( $email ) ){
$email .= "," . $additional_email;
}
}
return $email;
}
/**
* Display meta in my-account area Order overview
*
* #var object $order
* #return null
* #since 1.0
*/
public function after_customer_details( $order ){
$value = get_post_meta( $order->id, $this->meta, true );
if( $value ){
echo '<dt>' . $this->label . ':</dt><dd>' . $value . '</dd>';
}
}
/**
* Display meta in my-account area Order overview
*
* #var array $fields
* #return array
* #since 1.0
*/
public function before_email_addresses( $template_name, $template_path, $located, $args ){
if( $template_name == 'emails/email-addresses.php' && isset( $args['order' ] ) && ( $value = get_post_meta( $args['order']->id, $this->meta, true ) ) ){
if ( isset( $args['plain_text'] ) && $args['plain_text'] ){
echo $this->label . ': ' . $value . "\n";
} else {
echo '<p><strong>' . $this->label . ':</strong> ' . $value . '</p>';
}
}
}
} //end class: do not remove or there will be no more guacamole for you
endif; // end class_exists check
/**
* Returns the main instance of WC_Shipping_Email to prevent the need to use globals.
*
* #since 2.0
* #return WooCommerce
*/
function WC_Shipping_Email() {
return WC_Shipping_Email::instance();
}
// Launch the whole plugin
WC_Shipping_Email();
NB: This only sends to the shipping email for the customer_processing_order, customer_completed_order, and customer_note emails.

Categories