· 6 years ago · Mar 09, 2019, 02:36 PM
1<?php
2// get woocommerce version number
3function porto_get_woo_version_number() {
4 // If get_plugins() isn't available, require it
5 if ( ! function_exists( 'get_plugins' ) ) {
6 require_once( ABSPATH . 'wp-admin/includes/plugin.php' );
7 }
8 // Create the plugins folder and file variables
9 $plugin_folder = get_plugins( '/' . 'woocommerce' );
10 $plugin_file = 'woocommerce.php';
11 // If the plugin version number is set, return it
12 if ( isset( $plugin_folder[ $plugin_file ]['Version'] ) ) {
13 return $plugin_folder[ $plugin_file ]['Version'];
14 } else {
15 // Otherwise return null
16 return null;
17 }
18}
19// remove actions
20remove_action( 'woocommerce_before_main_content', 'woocommerce_breadcrumb', 20 );
21remove_action( 'woocommerce_before_shop_loop', 'woocommerce_result_count', 20 );
22remove_action( 'woocommerce_before_shop_loop_item_title', 'woocommerce_template_loop_product_thumbnail', 10 );
23remove_action( 'woocommerce_before_shop_loop_item', 'woocommerce_template_loop_product_link_open', 10 );
24remove_action( 'woocommerce_after_shop_loop_item', 'woocommerce_template_loop_product_link_close', 5 );
25remove_action( 'woocommerce_before_subcategory', 'woocommerce_template_loop_category_link_open', 10 );
26remove_action( 'woocommerce_after_subcategory', 'woocommerce_template_loop_category_link_close', 10 );
27remove_action( 'woocommerce_shop_loop_subcategory_title', 'woocommerce_template_loop_category_title', 10 );
28remove_action( 'woocommerce_shop_loop_item_title', 'woocommerce_template_loop_product_title', 10 );
29remove_action( 'woocommerce_before_single_product', 'wc_print_notices', 10 );
30remove_action( 'woocommerce_after_single_product_summary', 'woocommerce_output_related_products', 20 );
31
32// add actions
33add_action( 'woocommerce_before_shop_loop', 'porto_woocommerce_open_before_clearfix_div', 11 );
34add_action( 'woocommerce_before_shop_loop', 'porto_woocommerce_close_before_clearfix_div', 80 );
35add_action( 'woocommerce_after_shop_loop', 'porto_woocommerce_open_after_clearfix_div', 1 );
36add_action( 'woocommerce_after_shop_loop', 'porto_woocommerce_close_after_clearfix_div', 999 );
37add_action( 'woocommerce_before_shop_loop', 'porto_grid_list_toggle', 40 );
38add_action( 'woocommerce_before_shop_loop', 'woocommerce_pagination', 50 );
39add_action( 'woocommerce_before_shop_loop_item_title', 'porto_loop_product_thumbnail', 10 );
40add_action( 'woocommerce_after_shop_loop_item_title', 'porto_woocommerce_single_excerpt', 9 );
41add_action( 'woocommerce_archive_description', 'porto_woocommerce_category_image', 2 );
42add_action( 'woocommerce_shop_loop_item_title', 'porto_woocommerce_shop_loop_item_title_open', 1 );
43add_action( 'woocommerce_shop_loop_item_title', 'porto_woocommerce_shop_loop_item_title_close', 100 );
44//add_action( 'woocommerce_single_product_summary', 'woocommerce_template_single_price', 25 );
45add_action( 'porto_woocommerce_before_shop_loop_item_title', 'porto_woocommerce_shop_loop_item_title_rating', 1 );
46add_action( 'woocommerce_shop_loop_item_title', 'porto_woocommerce_shop_loop_item_title' );
47add_action( 'porto_before_content', 'porto_wc_print_notices', 10 );
48
49remove_action( 'woocommerce_single_product_summary', 'woocommerce_template_single_meta', 40 );
50add_action( 'woocommerce_single_product_summary', 'woocommerce_template_single_meta', 26 );
51add_action( 'woocommerce_single_product_summary', 'porto_woocommerce_sale_product_period', 15 );
52add_action( 'woocommerce_before_shop_loop_item_title', 'porto_woocommerce_sale_product_period', 20 );
53
54add_filter( 'woocommerce_available_variation', 'porto_woocommerce_get_sale_end_date', 100, 3 );
55
56add_action( 'porto_after_content_bottom', 'porto_woocommerce_output_related_products', 10 );
57function porto_woocommerce_output_related_products() {
58 if ( is_singular( 'product' ) ) {
59 woocommerce_output_related_products();
60 }
61}
62
63// add filters
64add_filter( 'woocommerce_show_page_title', 'porto_woocommerce_show_page_title' );
65add_filter( 'woocommerce_layered_nav_link', 'porto_layered_nav_link' );
66add_filter( 'loop_shop_per_page', 'porto_loop_shop_per_page' );
67add_filter( 'woocommerce_available_variation', 'porto_woocommerce_available_variation', 10, 3 );
68add_filter( 'woocommerce_related_products_args', 'porto_remove_related_products', 10 );
69add_filter( 'woocommerce_add_to_cart_fragments', 'porto_woocommerce_header_add_to_cart_fragment' );
70add_filter( 'woocommerce_show_admin_notice', 'porto_woocommerce_hide_update_notice', 10, 2 );
71
72// message
73function porto_wc_print_notices() {
74 if ( is_singular( 'product' ) && function_exists( 'wc_print_notices' ) ) {
75 wc_print_notices();
76 }
77}
78
79// rating
80function porto_woocommerce_shop_loop_item_title_rating() {
81 global $woocommerce_loop, $porto_woocommerce_loop;
82 if ( isset( $porto_woocommerce_loop['widget'] ) && $porto_woocommerce_loop['widget'] ) {
83 return;
84 }
85 if ( isset( $woocommerce_loop['addlinks_pos'] ) && ( 'outimage_q_onimage' == $woocommerce_loop['addlinks_pos'] || 'outimage_q_onimage_alt' == $woocommerce_loop['addlinks_pos'] || 'outimage' == $woocommerce_loop['addlinks_pos'] ) ) {
86 remove_action( 'woocommerce_after_shop_loop_item_title', 'woocommerce_template_loop_rating', 5 );
87 add_action( 'porto_woocommerce_before_shop_loop_item_title', 'woocommerce_template_loop_rating', 5 );
88 }
89}
90// change action position
91add_action( 'woocommerce_share', 'porto_woocommerce_share' );
92function porto_woocommerce_share() {
93 global $porto_settings;
94 $share = porto_get_meta_value( 'product_share' );
95 if ( $porto_settings['share-enable'] && 'no' !== $share && ( 'yes' === $share || ( 'yes' !== $share && $porto_settings['product-share'] ) ) ) {
96 echo '<div class="product-share">';
97 echo '<label>';
98 esc_html_e( 'Share', 'porto' );
99 echo '</label>';
100 get_template_part( 'share' );
101 echo '</div>';
102 }
103}
104// hide woocommer page title
105function porto_woocommerce_show_page_title( $args ) {
106 return false;
107}
108
109function porto_woocommerce_open_before_clearfix_div() {
110 global $porto_shop_filter_layout;
111 if ( ( ! isset( $porto_shop_filter_layout ) || 'horizontal2' != $porto_shop_filter_layout ) && ( ( function_exists( 'wc_get_loop_prop' ) && ! wc_get_loop_prop( 'is_paginated' ) ) || ! woocommerce_products_will_display() ) ) {
112 return;
113 }
114 echo '<div class="shop-loop-before clearfix">';
115}
116
117function porto_woocommerce_open_after_clearfix_div() {
118 if ( ( function_exists( 'wc_get_loop_prop' ) && ! wc_get_loop_prop( 'is_paginated' ) ) || ! woocommerce_products_will_display() ) {
119 return;
120 }
121 global $porto_settings;
122 $class_suffix = '';
123 if ( isset( $porto_settings['product-infinite'] ) && 'infinite_scroll' == $porto_settings['product-infinite'] ) {
124 $class_suffix = ' d-none';
125 } elseif ( isset( $porto_settings['product-infinite'] ) && 'load_more' == $porto_settings['product-infinite'] ) {
126 $class_suffix = ' load-more-wrap';
127 }
128 echo '<div class="shop-loop-after clearfix' . $class_suffix . '">';
129}
130
131function porto_woocommerce_close_before_clearfix_div() {
132 global $porto_shop_filter_layout;
133 if ( ( ! isset( $porto_shop_filter_layout ) || 'horizontal2' != $porto_shop_filter_layout ) && ( ( function_exists( 'wc_get_loop_prop' ) && ! wc_get_loop_prop( 'is_paginated' ) ) || ! woocommerce_products_will_display() ) ) {
134 return;
135 }
136 echo '</div>';
137}
138
139function porto_woocommerce_close_after_clearfix_div() {
140 if ( ( function_exists( 'wc_get_loop_prop' ) && ! wc_get_loop_prop( 'is_paginated' ) ) || ! woocommerce_products_will_display() ) {
141 return;
142 }
143 echo '</div>';
144}
145
146// show grid/list toggle buttons
147function porto_grid_list_toggle() {
148 global $porto_woocommerce_loop;
149 if ( ( function_exists( 'wc_get_loop_prop' ) && ! wc_get_loop_prop( 'is_paginated' ) ) || ! woocommerce_products_will_display() || isset( $porto_woocommerce_loop['view'] ) ) {
150 return;
151 }
152 ?>
153 <div class="gridlist-toggle">
154 <a href="#" id="grid" title="<?php esc_attr_e( 'Grid View', 'porto' ); ?>"></a><a href="#" id="list" title="<?php esc_attr_e( 'List View', 'porto' ); ?>"></a>
155 </div>
156 <?php
157 global $porto_settings, $porto_shop_filter_layout;
158 if ( isset( $porto_shop_filter_layout ) && ( 'horizontal' === $porto_shop_filter_layout || 'horizontal2' === $porto_shop_filter_layout ) ) {
159 woocommerce_result_count();
160 }
161 if ( isset( $porto_shop_filter_layout ) && 'horizontal2' === $porto_shop_filter_layout ) {
162 //remove_action( 'woocommerce_before_shop_loop', 'woocommerce_pagination', 50 );
163 }
164}
165// get product count per page
166function porto_loop_shop_per_page() {
167 global $porto_settings;
168 // replace it with theme option
169 if ( $porto_settings['category-item'] ) {
170 $per_page = explode( ',', $porto_settings['category-item'] );
171 } else {
172 $per_page = explode( ',', '12,24,36' );
173 }
174 $item_count = isset( $_GET['count'] ) && ! empty( $_GET['count'] ) ? $_GET['count'] : $per_page[0];
175 return $item_count;
176}
177// add thumbnail image parameter
178function porto_woocommerce_available_variation( $variations, $product, $variation ) {
179 if ( has_post_thumbnail( $variation->get_id() ) ) {
180 $attachment_id = get_post_thumbnail_id( $variation->get_id() );
181 $image_thumb_link = wp_get_attachment_image_src( $attachment_id, 'shop_thumbnail' );
182 $variations = array_merge( $variations, array( 'image_thumb' => $image_thumb_link[0] ) );
183 $image_thumb_link = wp_get_attachment_image_src( $attachment_id, 'shop_single' );
184 $variations = array_merge( $variations, array( 'image_src' => $image_thumb_link[0] ) );
185 $image_thumb_link = wp_get_attachment_image_src( $attachment_id, 'full' );
186 $variations = array_merge( $variations, array( 'image_link' => $image_thumb_link[0] ) );
187 } elseif ( has_post_thumbnail() ) {
188 $attachment_id = get_post_thumbnail_id();
189 $image_thumb_link = wp_get_attachment_image_src( $attachment_id, 'shop_thumbnail' );
190 $variations = array_merge( $variations, array( 'image_thumb' => $image_thumb_link[0] ) );
191 $image_thumb_link = wp_get_attachment_image_src( $attachment_id, 'shop_single' );
192 $variations = array_merge( $variations, array( 'image_src' => $image_thumb_link[0] ) );
193 $image_thumb_link = wp_get_attachment_image_src( $attachment_id, 'full' );
194 $variations = array_merge( $variations, array( 'image_link' => $image_thumb_link[0] ) );
195 }
196 return $variations;
197}
198// add sort order parameter
199function porto_layered_nav_link( $link ) {
200 if ( isset( $_GET['orderby'] ) && ! empty( $_GET['orderby'] ) ) {
201 $link = esc_url( str_replace( '#038;', '&', add_query_arg( 'orderby', $_GET['orderby'], $link ) ) );
202 }
203 if ( isset( $_GET['count'] ) && ! empty( $_GET['count'] ) ) {
204 $link = esc_url( str_replace( '#038;', '&', add_query_arg( 'count', $_GET['count'], $link ) ) );
205 }
206 return $link;
207}
208// change product thumbnail in products list page
209function porto_loop_product_thumbnail() {
210 global $porto_settings, $porto_woocommerce_loop, $porto_settings_optimize;
211 $id = get_the_ID();
212 $size = 'shop_catalog';
213 $gallery = get_post_meta( $id, '_product_image_gallery', true );
214 $attachment_image = '';
215 if ( ! empty( $gallery ) && $porto_settings['category-image-hover'] ) {
216 $gallery = explode( ',', $gallery );
217
218 $show_hover_img = get_post_meta( $id, 'product_image_on_hover', true );
219 $show_hover_img = empty( $show_hover_img ) || ( 'yes' === $show_hover_img );
220 if ( $show_hover_img ) {
221 $first_image_id = $gallery[0];
222
223 if ( isset( $porto_settings_optimize['lazyload'] ) && $porto_settings_optimize['lazyload'] ) {
224 $attachment_image = wp_get_attachment_image_src( $first_image_id, $size );
225 if ( $attachment_image && is_array( $attachment_image ) && count( $attachment_image ) >= 3 ) {
226 $thumb_classes = 'hover-image';
227 $thumb_attr = '';
228 $placeholder = porto_generate_placeholder( $attachment_image[1] . 'x' . $attachment_image[2] );
229 if ( 'products-slider' == $porto_woocommerce_loop['view'] ) {
230 $thumb_classes .= ' owl-lazy';
231 $thumb_attr = ' data-src="' . esc_url( $attachment_image[0] ) . '" src="' . esc_url( $placeholder[0] ) . '"';
232 } else {
233 $thumb_classes .= ' porto-lazyload';
234 $thumb_attr = ' data-original="' . esc_url( $attachment_image[0] ) . '" src="' . esc_url( $placeholder[0] ) . '"';
235 }
236 $alt_text = get_post_meta( $first_image_id, '_wp_attachment_image_alt', true );
237 $attachment_image = '<img ' . $thumb_attr . ' width="' . esc_attr( $attachment_image[1] ) . '" height="' . esc_attr( $attachment_image[2] ) . '" class="' . esc_attr( $thumb_classes ) . '" alt="' . esc_attr( $alt_text ) . '" />';
238 }
239 } else {
240 $attachment_image = wp_get_attachment_image( $first_image_id, $size, false, array( 'class' => 'hover-image' ) );
241 }
242 }
243 }
244
245 $thumb_image = '';
246 if ( isset( $porto_settings_optimize['lazyload'] ) && $porto_settings_optimize['lazyload'] ) {
247 $thumb_image = wp_get_attachment_image_src( get_post_thumbnail_id(), $size );
248 if ( $thumb_image && is_array( $thumb_image ) && count( $thumb_image ) >= 3 ) {
249 $thumb_classes = '';
250 $thumb_attr = '';
251 $placeholder = porto_generate_placeholder( $thumb_image[1] . 'x' . $thumb_image[2] );
252 if ( 'products-slider' == $porto_woocommerce_loop['view'] ) {
253 $thumb_classes .= 'owl-lazy';
254 $thumb_attr = ' data-src="' . esc_url( $thumb_image[0] ) . '" src="' . esc_url( $placeholder[0] ) . '"';
255 } else {
256 $thumb_classes .= 'porto-lazyload';
257 $thumb_attr = ' data-original="' . esc_url( $thumb_image[0] ) . '" src="' . esc_url( $placeholder[0] ) . '"';
258 }
259 $alt_text = get_post_meta( get_post_thumbnail_id(), '_wp_attachment_image_alt', true );
260 $thumb_image = '<img ' . $thumb_attr . ' width="' . esc_attr( $thumb_image[1] ) . '" height="' . esc_attr( $thumb_image[2] ) . '" class="' . esc_attr( $thumb_classes ) . '" alt="' . esc_attr( $alt_text ) . '" />';
261 }
262 } else {
263 $thumb_image = get_the_post_thumbnail( $id, $size, array( 'class' => '' ) );
264 }
265
266 if ( ! $thumb_image ) {
267 if ( wc_placeholder_img_src() ) {
268 $thumb_image = wc_placeholder_img( $size );
269 }
270 }
271
272 echo '<div class="inner' . ( ( $attachment_image ) ? ' img-effect' : '' ) . '">';
273 // show images
274 echo porto_filter_output( $thumb_image );
275 echo porto_filter_output( $attachment_image );
276 echo '</div>';
277}
278// change product thumbnail in products widget
279function porto_widget_product_thumbnail() {
280 global $porto_settings;
281 $id = get_the_ID();
282 $size = 'widget-thumb-medium';
283 $gallery = get_post_meta( $id, '_product_image_gallery', true );
284 $attachment_image = '';
285 if ( ! empty( $gallery ) && $porto_settings['category-image-hover'] ) {
286 $gallery = explode( ',', $gallery );
287
288 $show_hover_img = get_post_meta( $id, 'product_image_on_hover', true );
289 $show_hover_img = empty( $show_hover_img ) || ( 'yes' === $show_hover_img );
290 if ( $show_hover_img ) {
291 $first_image_id = $gallery[0];
292 $attachment_image = wp_get_attachment_image( $first_image_id, $size, false, array( 'class' => 'hover-image ' ) );
293 }
294 }
295 $thumb_image = get_the_post_thumbnail( $id, $size, array( 'class' => '' ) );
296 if ( ! $thumb_image ) {
297 if ( wc_placeholder_img_src() ) {
298 $thumb_image = wc_placeholder_img( $size );
299 }
300 }
301 echo '<div class="inner' . ( ( $attachment_image ) ? ' img-effect' : '' ) . '">';
302 // show images
303 echo porto_filter_output( $thumb_image );
304 echo porto_filter_output( $attachment_image );
305 echo '</div>';
306}
307// remove related products
308function porto_remove_related_products( $args ) {
309 global $porto_settings;
310 if ( isset( $porto_settings['product-related'] ) && ! $porto_settings['product-related'] ) {
311 return array();
312 }
313 return $args;
314}
315// add ajax cart fragment
316function porto_woocommerce_header_add_to_cart_fragment( $fragments ) {
317 global $porto_settings;
318 $minicart_type = porto_get_minicart_type();
319 if ( 'minicart-inline' == $minicart_type ) {
320 $_cart_total = WC()->cart->get_cart_subtotal();
321 /* translators: %s: Cart quantity */
322 $fragments['#mini-cart .cart-subtotal'] = '<span class="cart-subtotal">' . sprintf( esc_html__( 'Cart %s', 'porto' ), $_cart_total ) . '</span>';
323 } else {
324 $_cart_qty = WC()->cart->cart_contents_count;
325 $_cart_qty = ( $_cart_qty > 0 ? $_cart_qty : '0' );
326 $fragments['#mini-cart .cart-items'] = '<span class="cart-items">' . $_cart_qty . '</span>';
327 /* translators: %s: Cart items */
328 $fragments['#mini-cart .cart-items-text'] = '<span class="cart-items-text">' . sprintf( _n( '%d item', '%d items', $_cart_qty, 'porto' ), $_cart_qty ) . '</span>';
329 }
330 return $fragments;
331}
332// remove update notice
333function porto_woocommerce_hide_update_notice( $flag, $notice ) {
334 if ( 'update' === $notice ) {
335 return false;
336 }
337 return $flag;
338}
339// ajax remove cart item
340add_action( 'wp_ajax_porto_cart_item_remove', 'porto_cart_item_remove' );
341add_action( 'wp_ajax_nopriv_porto_cart_item_remove', 'porto_cart_item_remove' );
342function porto_cart_item_remove() {
343 check_ajax_referer( 'porto-nonce', 'nonce' );
344 $cart = WC()->instance()->cart;
345 $cart_id = sanitize_text_field( $_POST['cart_id'] );
346 $cart_item_id = $cart->find_product_in_cart( $cart_id );
347 if ( $cart_item_id ) {
348 $cart->set_quantity( $cart_item_id, 0 );
349 }
350 $cart_ajax = new WC_AJAX();
351 $cart_ajax->get_refreshed_fragments();
352 exit();
353}
354// refresh cart fragment
355add_action( 'wp_ajax_porto_refresh_cart_fragment', 'porto_refresh_cart_fragment' );
356add_action( 'wp_ajax_nopriv_porto_refresh_cart_fragment', 'porto_refresh_cart_fragment' );
357function porto_refresh_cart_fragment() {
358 check_ajax_referer( 'porto-nonce', 'nonce' );
359 $cart_ajax = new WC_AJAX();
360 $cart_ajax->get_refreshed_fragments();
361 exit();
362}
363function porto_get_products_by_ids( $product_ids ) {
364 $product_ids = explode( ',', $product_ids );
365 $product_ids = array_map( 'trim', $product_ids );
366 $args = array(
367 'post_type' => 'product',
368 'post_status' => 'publish',
369 'ignore_sticky_posts' => 1,
370 'posts_per_page' => -1,
371 'post__in' => $product_ids,
372 );
373 // @codingStandardsIgnoreStart
374 $args['tax_query'] = WC()->query->get_tax_query();
375 // @codingStandardsIgnoreEnd
376 $query = new WP_Query( $args );
377 return $query;
378}
379function porto_get_rating_html( $product, $rating = null ) {
380 if ( get_option( 'woocommerce_enable_review_rating' ) == 'no' ) {
381 return '';
382 }
383 if ( ! is_numeric( $rating ) ) {
384 $rating = $product->get_average_rating();
385 }
386 $rating_html = '<div class="star-rating" title="' . esc_attr( $rating ) . '">';
387 $rating_html .= '<span style="width:' . ( ( $rating / 5 ) * 100 ) . '%"><strong class="rating">' . $rating . '</strong> ' . __( 'out of 5', 'woocommerce' ) . '</span>';
388 $rating_html .= '</div>';
389 return $rating_html;
390}
391// Wrap gravatar in reviews
392add_action( 'woocommerce_review_before', 'porto_woo_review_display_gravatar_wrap_start', 9 );
393add_action( 'woocommerce_review_before', 'porto_woo_review_display_gravatar_wrap_end', 11 );
394function porto_woo_review_display_gravatar_wrap_start() {
395 echo '<div class="img-thumbnail">';
396}
397function porto_woo_review_display_gravatar_wrap_end() {
398 echo '</div>';
399}
400add_filter( 'woocommerce_review_gravatar_size', 'porto_woo_review_gravatar_size' );
401function porto_woo_review_gravatar_size( $size ) {
402 return '80';
403}
404// Quick View Html
405add_action( 'wp_ajax_porto_product_quickview', 'porto_product_quickview' );
406add_action( 'wp_ajax_nopriv_porto_product_quickview', 'porto_product_quickview' );
407function porto_product_quickview() {
408 check_ajax_referer( 'porto-nonce', 'nonce' );
409
410 global $post, $product;
411 $post = get_post( (int) $_REQUEST['pid'] );
412 $product = wc_get_product( $post->ID );
413 if ( post_password_required() ) {
414 echo get_the_password_form();
415 die();
416 return;
417 }
418 ?>
419 <div class="quickview-wrap quickview-wrap-<?php echo esc_attr( $post->ID ); ?> single-product">
420 <div class="product product-summary-wrap">
421 <div class="row">
422 <div class="col-lg-6 summary-before">
423 <?php
424 do_action( 'woocommerce_before_single_product_summary' );
425 ?>
426 </div>
427 <div class="col-lg-6 summary entry-summary">
428 <?php
429
430 do_action( 'woocommerce_single_product_summary' );
431 ?>
432 <script>
433 <?php
434 $suffix = defined( 'SCRIPT_DEBUG' ) && SCRIPT_DEBUG ? '' : '.min';
435 $assets_path = esc_url( str_replace( array( 'http:', 'https:' ), '', WC()->plugin_url() ) ) . '/assets/';
436 $frontend_script_path = $assets_path . 'js/frontend/';
437 ?>
438 var wc_add_to_cart_variation_params =
439 <?php
440 echo array2json(
441 apply_filters(
442 'wc_add_to_cart_variation_params',
443 array(
444 'wc_ajax_url' => WC_AJAX::get_endpoint( '%%endpoint%%' ),
445 'i18n_no_matching_variations_text' => esc_js( __( 'Sorry, no products matched your selection. Please choose a different combination.', 'woocommerce' ) ),
446 'i18n_make_a_selection_text' => esc_js( __( 'Select product options before adding this product to your cart.', 'woocommerce' ) ),
447 'i18n_unavailable_text' => esc_js( __( 'Sorry, this product is unavailable. Please choose a different combination.', 'woocommerce' ) ),
448 )
449 )
450 )
451 ?>
452 ;
453 jQuery(document).ready(function($) {
454 $.getScript('<?php echo porto_filter_output( $frontend_script_path . 'add-to-cart-variation' . $suffix . '.js' ); ?>');
455 });
456 </script>
457 </div><!-- .summary -->
458 </div>
459 </div>
460 </div>
461 <?php
462 die();
463}
464function porto_woocommerce_category_image() {
465 if ( is_product_category() ) {
466 $term = get_queried_object();
467 if ( $term ) {
468 $image = esc_url( get_metadata( $term->taxonomy, $term->term_id, 'category_image', true ) );
469 if ( $image ) {
470 echo '<img src="' . $image . '" class="category-image" alt="' . esc_attr( $term->name ) . '" />';
471 }
472 }
473 }
474}
475function porto_woocommerce_shop_loop_item_title_open() {
476 global $porto_settings;
477 $more_link = apply_filters( 'the_permalink', get_permalink() );
478 $more_target = '';
479 if ( isset( $porto_settings['catalog-enable'] ) && $porto_settings['catalog-enable'] ) {
480 if ( $porto_settings['catalog-admin'] || ( ! $porto_settings['catalog-admin'] && ! ( current_user_can( 'administrator' ) && is_user_logged_in() ) ) ) {
481 if ( ! $porto_settings['catalog-cart'] ) {
482 if ( $porto_settings['catalog-readmore'] && 'all' === $porto_settings['catalog-readmore-archive'] ) {
483 $link = get_post_meta( get_the_id(), 'product_more_link', true );
484 if ( $link ) {
485 $more_link = $link;
486 }
487 $more_target = $porto_settings['catalog-readmore-target'] ? 'target="' . esc_attr( $porto_settings['catalog-readmore-target'] ) . '"' : '';
488 }
489 }
490 }
491 }
492 ?>
493 <a class="product-loop-title" <?php echo porto_filter_output( $more_target ); ?> href="<?php echo esc_url( $more_link ); ?>">
494 <?php
495}
496function porto_woocommerce_shop_loop_item_title_close() {
497 ?>
498 </a>
499 <?php
500}
501function porto_woocommerce_shop_loop_item_title() {
502 echo '<h3 class="woocommerce-loop-product__title">' . get_the_title() . '</h3>';
503}
504function porto_woocommerce_single_excerpt() {
505 global $post;
506 if ( ! $post->post_excerpt ) {
507 return;
508 }
509 ?>
510 <div class="description">
511 <?php echo force_balance_tags( apply_filters( 'porto_woocommerce_short_description', $post->post_excerpt ) ); ?>
512 </div>
513 <?php
514}
515
516function porto_woocommerce_next_product( $in_same_cat = false, $excluded_categories = '' ) {
517 porto_adjacent_post_link_product( $in_same_cat, $excluded_categories, false );
518}
519function porto_woocommerce_prev_product( $in_same_cat = false, $excluded_categories = '' ) {
520 porto_adjacent_post_link_product( $in_same_cat, $excluded_categories, true );
521}
522function porto_adjacent_post_link_product( $in_same_cat = false, $excluded_categories = '', $previous = true ) {
523 if ( $previous && is_attachment() ) {
524 $post = get_post( get_post()->post_parent );
525 } else {
526 $post = porto_get_adjacent_post_product( $in_same_cat, $excluded_categories, $previous );
527 }
528 if ( $previous ) {
529 $label = 'prev';
530 } else {
531 $label = 'next';
532 }
533 if ( $post ) {
534 $product = wc_get_product( $post->ID );
535 ?>
536 <div class="product-<?php echo porto_filter_output( $label ); ?>">
537 <a href="<?php echo esc_url( get_permalink( $post ) ); ?>">
538 <span class="product-link"></span>
539 <span class="product-popup">
540 <span class="featured-box">
541 <span class="box-content">
542 <span class="product-image">
543 <span class="inner">
544 <?php
545 if ( has_post_thumbnail( $post->ID ) ) {
546 echo get_the_post_thumbnail( $post->ID, apply_filters( 'single_product_small_thumbnail_size', 'shop_thumbnail' ) );
547 } else {
548 echo '<img src="' . wc_placeholder_img_src() . '" alt="Placeholder" width="' . wc_get_image_size( 'shop_thumbnail_image_width' )['width'] . '" height="' . wc_get_image_size( 'shop_thumbnail_image_height' )['height'] . '" />';
549 }
550 ?>
551 </span>
552 </span>
553 <span class="product-details">
554 <span class="product-title"><?php echo ( get_the_title( $post ) ) ? get_the_title( $post ) : $post->ID; ?></span>
555 </span>
556 </span>
557 </span>
558 </span>
559 </a>
560 </div>
561 <?php
562 } else {
563 ?>
564 <div class="product-<?php echo porto_filter_output( $label ); ?>">
565 <span class="product-link disabled"></span>
566 </div>
567 <?php
568 }
569}
570function porto_get_adjacent_post_product( $in_same_cat = false, $excluded_categories = '', $previous = true ) {
571 global $wpdb;
572 $post = get_post();
573 if ( ! $post ) {
574 return null;
575 }
576 $current_post_date = $post->post_date;
577 $join = '';
578 $posts_in_ex_cats_sql = '';
579 if ( $in_same_cat || ! empty( $excluded_categories ) ) {
580 $join = " INNER JOIN $wpdb->term_relationships AS tr ON p.ID = tr.object_id INNER JOIN $wpdb->term_taxonomy tt ON tr.term_taxonomy_id = tt.term_taxonomy_id";
581 if ( $in_same_cat ) {
582 if ( ! is_object_in_taxonomy( $post->post_type, 'product_cat' ) ) {
583 return '';
584 }
585 $cat_array = wp_get_object_terms( $post->ID, 'product_cat', array( 'fields' => 'ids' ) );
586 if ( ! $cat_array || is_wp_error( $cat_array ) ) {
587 return '';
588 }
589 $join .= $wpdb->prepare( ' AND tt.taxonomy = %s AND tt.term_id IN (' . implode( ',', $cat_array ) . ')', 'product_cat' );
590 }
591 $posts_in_ex_cats_sql = "AND tt.taxonomy = 'product_cat'";
592 if ( ! empty( $excluded_categories ) ) {
593 if ( ! is_array( $excluded_categories ) ) {
594 // back-compat, $excluded_categories used to be IDs separated by " and "
595 if ( strpos( $excluded_categories, ' and ' ) !== false ) {
596 /* translators: %s: and */
597 _deprecated_argument( __FUNCTION__, '3.3', sprintf( __( 'Use commas instead of %s to separate excluded categories.', 'porto' ), "'and'" ) );
598 $excluded_categories = explode( ' and ', $excluded_categories );
599 } else {
600 $excluded_categories = explode( ',', $excluded_categories );
601 }
602 }
603 $excluded_categories = array_map( 'intval', $excluded_categories );
604 if ( ! empty( $cat_array ) ) {
605 $excluded_categories = array_diff( $excluded_categories, $cat_array );
606 $posts_in_ex_cats_sql = '';
607 }
608 if ( ! empty( $excluded_categories ) ) {
609 $posts_in_ex_cats_sql = $wpdb->prepare( ' AND tt.taxonomy = %s AND tt.term_id NOT IN (' . implode( $excluded_categories, ',' ) . ')', 'product_cat' );
610 }
611 }
612 }
613 $adjacent = $previous ? 'previous' : 'next';
614 $op = $previous ? '<' : '>';
615 $order = $previous ? 'DESC' : 'ASC';
616 $join = apply_filters( "get_{$adjacent}_post_join", $join, $in_same_cat, $excluded_categories, 'product_cat', $post );
617 $where = apply_filters( "get_{$adjacent}_post_where", $wpdb->prepare( "WHERE p.post_date $op %s AND p.post_type = %s AND p.post_status = 'publish' $posts_in_ex_cats_sql", $current_post_date, $post->post_type ), $in_same_cat, $excluded_categories, 'product_cat', $post );
618 $sort = apply_filters( "get_{$adjacent}_post_sort", "ORDER BY p.post_date $order LIMIT 1", $post, $order );
619 $query = "SELECT p.id FROM $wpdb->posts AS p $join $where $sort";
620 $query_key = 'adjacent_post_' . md5( $query );
621 $result = wp_cache_get( $query_key, 'counts' );
622 if ( false !== $result ) {
623 if ( $result ) {
624 $result = get_post( $result );
625 }
626 return $result;
627 }
628 $result = $wpdb->get_var( $query );
629 if ( null === $result ) {
630 $result = '';
631 }
632 wp_cache_set( $query_key, $result, 'counts' );
633 if ( $result ) {
634 $result = get_post( $result );
635 }
636 return $result;
637}
638add_action( 'woocommerce_init', 'porto_woocommerce_init' );
639function porto_woocommerce_init() {
640 global $porto_settings;
641 // Hide product short description
642 if ( isset( $porto_settings['catalog-enable'] ) && ! $porto_settings['product-short-desc'] ) {
643 remove_action( 'woocommerce_single_product_summary', 'woocommerce_template_single_excerpt', 20 );
644 }
645
646 add_action( 'woocommerce_single_product_summary', 'porto_woocommerce_product_nav', 5 );
647 // Catalog Mode
648 if ( isset( $porto_settings['catalog-enable'] ) && $porto_settings['catalog-enable'] ) {
649 if ( $porto_settings['catalog-admin'] || ( ! $porto_settings['catalog-admin'] && ! ( current_user_can( 'administrator' ) && is_user_logged_in() ) ) ) {
650 if ( ! $porto_settings['catalog-price'] ) {
651 remove_action( 'woocommerce_single_product_summary', 'woocommerce_template_single_price', 10 );
652 remove_action( 'woocommerce_after_shop_loop_item_title', 'woocommerce_template_loop_price', 10 );
653 add_filter( 'woocommerce_get_price_html', 'porto_woocommerce_get_price_html_empty', 100, 2 );
654 add_filter( 'woocommerce_cart_item_price', 'porto_woocommerce_get_price_empty', 100, 3 );
655 add_filter( 'woocommerce_cart_item_subtotal', 'porto_woocommerce_get_price_empty', 100, 3 );
656 add_filter( 'woocommerce_cart_subtotal', 'porto_woocommerce_get_price_empty', 100, 3 );
657 add_filter( 'woocommerce_get_variation_price_html', 'porto_woocommerce_get_price_html_empty', 100, 2 );
658 }
659 if ( ! $porto_settings['catalog-cart'] ) {
660 remove_action( 'woocommerce_single_product_summary', 'woocommerce_template_single_add_to_cart', 30 );
661 add_action( 'woocommerce_single_product_summary', 'porto_woocommerce_template_single_add_to_cart', 30 );
662 remove_action( 'woocommerce_after_shop_loop_item', 'woocommerce_template_loop_add_to_cart' );
663 if ( $porto_settings['catalog-readmore'] ) {
664 add_action( 'woocommerce_single_product_summary', 'porto_woocommerce_readmore_button', 30 );
665 }
666 if ( 'outimage' == $porto_settings['category-addlinks-pos'] && ( $porto_settings['product-wishlist'] || $porto_settings['product-quickview'] ) ) {
667 $porto_settings['category-addlinks-pos'] = 'onimage';
668 }
669 }
670 if ( ! $porto_settings['catalog-review'] ) {
671 add_filter( 'pre_option_woocommerce_enable_review_rating', 'porto_woocommerce_disable_rating' );
672 add_filter( 'woocommerce_product_tabs', 'porto_woocommerce_remove_reviews_tab', 98 );
673 function porto_woocommerce_remove_reviews_tab( $tabs ) {
674 unset( $tabs['reviews'] );
675 return $tabs;
676 }
677 }
678 }
679 }
680 // change product tabs position
681 if ( isset( $porto_settings['product-tabs-pos'] ) && 'below' == $porto_settings['product-tabs-pos'] ) {
682 if ( is_customize_preview() || ! porto_is_ajax() ) {
683 remove_action( 'woocommerce_after_single_product_summary', 'woocommerce_output_product_data_tabs' );
684 add_action( 'woocommerce_single_product_summary', 'woocommerce_output_product_data_tabs', 25 );
685 }
686 }
687
688 // add to cart sticky
689 if ( isset( $porto_settings['product-sticky-addcart'] ) && $porto_settings['product-sticky-addcart'] ) {
690 add_action( 'woocommerce_single_product_summary', 'porto_woocommerce_product_sticky_addcart', 5 );
691 }
692
693 // define woocommerce functions if use previous version
694 if ( ! function_exists( 'wc_product_class' ) ) :
695 function wc_product_class( $arg = array() ) {
696 return post_class( $arg );
697 }
698 endif;
699 if ( ! function_exists( 'wc_get_product_class' ) ) :
700 function wc_get_product_class( $arg = array() ) {
701 return get_post_class( $arg );
702 }
703 endif;
704}
705
706function porto_woocommerce_open_product_images() {
707 echo '<div class="product-summary-images summary-before container">';
708}
709function porto_woocommerce_close_product_images() {
710 echo '</div>';
711}
712function porto_woocommerce_template_single_add_to_cart() {
713 global $product;
714 if ( 'variable' == $product->product_type ) {
715 remove_action( 'woocommerce_single_variation', 'woocommerce_single_variation_add_to_cart_button', 20 );
716 do_action( 'woocommerce_' . $product->product_type . '_add_to_cart' );
717 }
718}
719function porto_woocommerce_get_price_html_empty( $price, $product ) {
720 return '';
721}
722function porto_woocommerce_get_price_empty( $price, $param2, $param3 ) {
723 return '';
724}
725function porto_woocommerce_disable_rating( $false ) {
726 return 'no';
727}
728function porto_woocommerce_readmore_button() {
729 global $porto_settings;
730 $more_link = get_post_meta( get_the_id(), 'product_more_link', true );
731 $more_target = $porto_settings['catalog-readmore-target'] ? 'target="' . esc_attr( $porto_settings['catalog-readmore-target'] ) . '"' : '';
732 if ( ! $more_link ) {
733 $more_link = apply_filters( 'the_permalink', get_permalink() );
734 }
735 ?>
736 <div class="cart">
737 <a <?php echo porto_filter_output( $more_target ); ?> href="<?php echo esc_url( $more_link ); ?>" class="single_add_to_cart_button button readmore"><?php echo wp_kses_post( $porto_settings['catalog-readmore-label'] ); ?></a>
738 </div>
739 <?php
740}
741// ajax products archive display
742add_filter( 'pre_option_woocommerce_shop_page_display', 'porto_shop_page_display_ajax' );
743function porto_shop_page_display_ajax( $value ) {
744 $params = array( 'count', 'orderby', 'min_price', 'max_price' );
745 foreach ( $params as $param ) {
746 if ( ! empty( $_GET[ $param ] ) ) {
747 return '';
748 }
749 }
750 $attribute_taxonomies = wc_get_attribute_taxonomies();
751 if ( $attribute_taxonomies ) {
752 foreach ( $attribute_taxonomies as $tax ) {
753 $attribute = wc_sanitize_taxonomy_name( $tax->attribute_name );
754 $taxonomy = wc_attribute_taxonomy_name( $attribute );
755 $name = 'filter_' . $attribute;
756 if ( ! empty( $_GET[ $name ] ) && taxonomy_exists( $taxonomy ) ) {
757 return '';
758 }
759 }
760 }
761 $page_num = get_query_var( 'paged' ) ? intval( get_query_var( 'paged' ) ) : 0;
762 if ( $page_num ) {
763 return '';
764 }
765 return $value;
766}
767add_filter( 'get_woocommerce_term_metadata', 'porto_woocommerce_term_metadata_ajax', 10, 4 );
768function porto_woocommerce_term_metadata_ajax( $value, $object_id, $meta_key, $single ) {
769 if ( 'display_type' === $meta_key ) {
770 $params = array( 'count', 'orderby', 'min_price', 'max_price' );
771 foreach ( $params as $param ) {
772 if ( ! empty( $_GET[ $param ] ) ) {
773 return 'products';
774 }
775 }
776 $attribute_taxonomies = wc_get_attribute_taxonomies();
777 if ( $attribute_taxonomies ) {
778 foreach ( $attribute_taxonomies as $tax ) {
779 $attribute = wc_sanitize_taxonomy_name( $tax->attribute_name );
780 $taxonomy = wc_attribute_taxonomy_name( $attribute );
781 $name = 'filter_' . $attribute;
782 if ( ! empty( $_GET[ $name ] ) && taxonomy_exists( $taxonomy ) ) {
783 return 'products';
784 }
785 }
786 }
787 $page_num = get_query_var( 'paged' ) ? intval( get_query_var( 'paged' ) ) : 0;
788 if ( $page_num ) {
789 return 'products';
790 }
791 }
792 return $value;
793}
794function porto_is_product_archive() {
795 if ( is_archive() ) {
796 $term = get_queried_object();
797 if ( $term && isset( $term->taxonomy ) && isset( $term->term_id ) ) {
798 switch ( $term->taxonomy ) {
799 case in_array( $term->taxonomy, porto_get_taxonomies( 'product' ) ):
800 case 'product_cat':
801 return true;
802 break;
803 default:
804 return false;
805 }
806 }
807 }
808 return false;
809}
810
811
812add_filter( 'woocommerce_get_stock_html', 'porto_woocommerce_stock_html', 10, 2 );
813function porto_woocommerce_stock_html( $availability_html, $product ) {
814 if ( $product->is_type( 'simple' ) ) {
815 return '';
816 }
817 return $availability_html;
818}
819
820add_action( 'woocommerce_product_meta_start', 'porto_woocommerce_add_stock_html', 10 );
821function porto_woocommerce_add_stock_html() {
822 global $product;
823 if ( $product->is_type( 'simple' ) ) {
824 $availability = $product->get_availability();
825 $availability_html = empty( $availability['availability'] ) ? '' : '<span class="product-stock ' . esc_attr( $availability['class'] ) . '">' . esc_html__( 'Availability', 'porto' ) . ': <span class="stock">' . esc_html( $availability['availability'] ) . '</span></span>';
826
827 echo apply_filters( 'porto_woocommerce_stock_html', $availability_html, $availability['availability'], $product );
828 }
829}
830
831add_action( 'wp', 'porto_woocommerce_init_layout' );
832function porto_woocommerce_init_layout() {
833 // woocommerce single product layout
834 global $porto_settings, $porto_product_layout, $porto_shop_filter_layout;
835 if ( class_exists( 'Woocommerce' ) && ( is_singular( 'product' ) || ( ! empty( $post->post_content ) && strstr( $post->post_content, '[product_page' ) ) ) ) {
836 $porto_product_layout = get_post_meta( get_the_ID(), 'product_layout', true );
837 $porto_product_layout = ( ! $porto_product_layout && isset( $porto_settings['product-single-content-layout'] ) ) ? $porto_settings['product-single-content-layout'] : $porto_product_layout;
838 if ( ! $porto_product_layout ) {
839 $porto_product_layout = 'default';
840 }
841 }
842 if ( class_exists( 'Woocommerce' ) && ( is_product_taxonomy() || is_post_type_archive( 'product' ) || is_page( wc_get_page_id( 'shop' ) ) ) ) {
843 $porto_shop_filter_layout = false;
844 $term = get_queried_object();
845 if ( $term && isset( $term->taxonomy ) && isset( $term->term_id ) ) {
846 $porto_shop_filter_layout = get_metadata( $term->taxonomy, $term->term_id, 'filter_layout', true );
847 }
848 if ( ! $porto_shop_filter_layout ) {
849 $porto_shop_filter_layout = $porto_settings['product-archive-filter-layout'];
850 }
851 }
852
853 // product layout
854 if ( $porto_product_layout ) {
855 if ( 'extended' === $porto_product_layout ) {
856 if ( is_singular( 'product' ) ) {
857 remove_action( 'woocommerce_before_single_product_summary', 'woocommerce_show_product_sale_flash', 10 );
858 add_action( 'porto_after_content_top', 'woocommerce_show_product_sale_flash', 40 );
859 remove_action( 'woocommerce_before_single_product_summary', 'woocommerce_show_product_images', 20 );
860 add_action( 'porto_after_content_top', 'porto_woocommerce_open_product_images', 39 );
861 add_action( 'porto_after_content_top', 'woocommerce_show_product_images', 50 );
862 add_action( 'porto_after_content_top', 'porto_woocommerce_close_product_images', 51 );
863 }
864 remove_action( 'woocommerce_single_product_summary', 'woocommerce_template_single_sharing', 50 );
865 add_action( 'woocommerce_single_product_summary', 'woocommerce_template_single_sharing', 6 );
866 add_action( 'woocommerce_single_product_summary', 'porto_woocommerce_template_single_custom_block', 11 );
867 remove_action( 'woocommerce_single_variation', 'woocommerce_single_variation', 10 );
868 add_action( 'woocommerce_after_variations_form', 'woocommerce_single_variation', 10 );
869 } elseif ( 'grid' === $porto_product_layout ) {
870 remove_action( 'woocommerce_single_product_summary', 'porto_woocommerce_sale_product_period', 15 );
871 add_action( 'woocommerce_before_add_to_cart_button', 'porto_woocommerce_sale_product_period', 15 );
872 remove_action( 'woocommerce_single_product_summary', 'woocommerce_template_single_meta', 26 );
873 add_action( 'woocommerce_single_product_summary', 'woocommerce_template_single_meta', 40 );
874 } elseif ( 'full_width' === $porto_product_layout ) {
875 add_action( 'woocommerce_single_product_summary', 'porto_woocommerce_template_single_custom_block', 1 );
876 if ( ! isset( $porto_settings['product-tabs-pos'] ) || 'below' != $porto_settings['product-tabs-pos'] ) {
877 remove_action( 'woocommerce_after_single_product_summary', 'woocommerce_output_product_data_tabs', 10 );
878 add_action( 'woocommerce_single_product_summary', 'woocommerce_output_product_data_tabs', 50 );
879 }
880 } elseif ( 'sticky_info' === $porto_product_layout ) {
881 remove_action( 'woocommerce_single_product_summary', 'woocommerce_template_single_sharing', 50 );
882 add_action( 'woocommerce_after_single_product_summary', 'woocommerce_template_single_sharing', 9 );
883 add_action( 'woocommerce_after_single_product_summary', 'porto_woocommerce_template_single_custom_block', 8 );
884 } elseif ( 'sticky_both_info' === $porto_product_layout ) {
885 remove_action( 'woocommerce_single_product_summary', 'woocommerce_template_single_title', 5 );
886 remove_action( 'woocommerce_single_product_summary', 'woocommerce_template_single_rating', 10 );
887 remove_action( 'woocommerce_single_product_summary', 'woocommerce_template_single_sharing', 50 );
888 remove_action( 'woocommerce_single_product_summary', 'porto_woocommerce_product_nav', 5 );
889 remove_action( 'woocommerce_single_product_summary', 'woocommerce_template_single_add_to_cart', 30 );
890 remove_action( 'woocommerce_single_product_summary', 'porto_woocommerce_sale_product_period', 15 );
891 add_action( 'porto_woocommerce_before_single_product_summary', 'woocommerce_template_single_title', 5 );
892 add_action( 'porto_woocommerce_before_single_product_summary', 'woocommerce_template_single_rating', 10 );
893 add_action( 'porto_woocommerce_before_single_product_summary', 'woocommerce_template_single_sharing', 6 );
894 add_action( 'porto_woocommerce_before_single_product_summary', 'porto_woocommerce_product_nav', 7 );
895 add_action( 'porto_woocommerce_single_product_summary2', 'woocommerce_template_single_add_to_cart', 10 );
896 add_action( 'woocommerce_before_add_to_cart_button', 'porto_woocommerce_sale_product_period', 15 );
897 } elseif ( 'centered_vertical_zoom' === $porto_product_layout ) {
898 remove_action( 'woocommerce_single_product_summary', 'woocommerce_template_single_add_to_cart', 30 );
899 remove_action( 'woocommerce_single_product_summary', 'porto_woocommerce_sale_product_period', 15 );
900 add_action( 'porto_woocommerce_single_product_summary2', 'woocommerce_template_single_add_to_cart', 10 );
901 add_action( 'porto_woocommerce_single_product_summary2', 'porto_woocommerce_template_single_custom_block', 5 );
902 add_action( 'woocommerce_before_add_to_cart_button', 'porto_woocommerce_sale_product_period', 15 );
903 } elseif ( 'left_sidebar' === $porto_product_layout ) {
904 remove_action( 'porto_after_content_bottom', 'porto_woocommerce_output_related_products', 10 );
905 add_action( 'woocommerce_after_single_product_summary', 'porto_woocommerce_output_related_products', 10 );
906 }
907 }
908
909 // horizontal filter
910 if ( $porto_shop_filter_layout && 'horizontal' == $porto_shop_filter_layout ) {
911 remove_action( 'woocommerce_before_shop_loop', 'porto_woocommerce_open_before_clearfix_div', 11 );
912 remove_action( 'woocommerce_before_shop_loop', 'woocommerce_catalog_ordering', 30 );
913 remove_action( 'woocommerce_before_shop_loop', 'porto_grid_list_toggle', 40 );
914 remove_action( 'woocommerce_before_shop_loop', 'woocommerce_pagination', 50 );
915 remove_action( 'woocommerce_before_shop_loop', 'porto_woocommerce_close_before_clearfix_div', 80 );
916 add_action( 'porto_before_content', 'porto_woocommerce_open_before_clearfix_div', 80 );
917 add_action( 'porto_before_content', 'porto_woocommerce_output_horizontal_filter', 82 );
918 add_action( 'porto_before_content', 'woocommerce_catalog_ordering', 84 );
919 add_action( 'porto_before_content', 'porto_grid_list_toggle', 86 );
920 add_action( 'porto_before_content', 'woocommerce_pagination', 88 );
921 add_action( 'porto_before_content', 'porto_woocommerce_close_before_clearfix_div', 90 );
922 } elseif ( $porto_shop_filter_layout && 'horizontal2' == $porto_shop_filter_layout ) {
923 add_action( 'woocommerce_before_shop_loop', 'porto_woocommerce_output_horizontal_filter', 25 );
924 }
925
926 // archive page infinite scroll
927 if ( isset( $porto_settings['product-infinite'] ) && $porto_settings['product-infinite'] ) {
928 remove_action( 'woocommerce_before_shop_loop', 'woocommerce_pagination', 50 );
929 if ( $porto_shop_filter_layout && 'horizontal' == $porto_shop_filter_layout ) {
930 remove_action( 'porto_before_content', 'woocommerce_pagination', 88 );
931 }
932 }
933}
934
935function porto_woocommerce_template_single_custom_block() {
936 global $porto_product_layout;
937 $block_slug = get_post_meta( get_the_ID(), 'product_custom_block', true );
938 if ( $block_slug ) {
939 echo '<div class="single-product-custom-block">';
940 echo do_shortcode( '[porto_block name="' . esc_attr( $block_slug ) . '"]' );
941 echo '</div>';
942 }
943}
944
945// product custom tabs
946add_filter( 'woocommerce_product_tabs', 'porto_woocommerce_custom_tabs' );
947add_filter( 'woocommerce_product_tabs', 'porto_woocommerce_global_tab' );
948function porto_woocommerce_custom_tabs( $tabs ) {
949 global $porto_settings;
950 $custom_tabs_count = isset( $porto_settings['product-custom-tabs-count'] ) ? $porto_settings['product-custom-tabs-count'] : '2';
951 if ( $custom_tabs_count ) {
952 for ( $i = 0; $i < $custom_tabs_count; $i++ ) {
953 $index = $i + 1;
954 $custom_tab_title = get_post_meta( get_the_id(), 'custom_tab_title' . $index, true );
955 $custom_tab_priority = (int) get_post_meta( get_the_id(), 'custom_tab_priority' . $index, true );
956 if ( ! $custom_tab_priority ) {
957 $custom_tab_priority = 40 + $i;
958 }
959 $custom_tab_content = get_post_meta( get_the_id(), 'custom_tab_content' . $index, true );
960 if ( $custom_tab_title && $custom_tab_content ) {
961 $tabs[ 'custom_tab' . $index ] = array(
962 'title' => wp_kses_post( $custom_tab_title ),
963 'priority' => $custom_tab_priority,
964 'callback' => 'porto_woocommerce_custom_tab_content',
965 'content' => $custom_tab_content,
966 );
967 }
968 }
969 }
970 return $tabs;
971}
972function porto_woocommerce_global_tab( $tabs ) {
973 global $porto_settings;
974 $custom_tab_title = $porto_settings['product-tab-title'];
975 $custom_tab_content = '[porto_block name="' . $porto_settings['product-tab-block'] . '"]';
976 $custom_tab_priority = ( isset( $porto_settings['product-tab-priority'] ) && $porto_settings['product-tab-priority'] ) ? $porto_settings['product-tab-priority'] : 60;
977 if ( $custom_tab_title && $custom_tab_content ) {
978 $tabs['global_tab'] = array(
979 'title' => wp_kses_post( $custom_tab_title ),
980 'priority' => $custom_tab_priority,
981 'callback' => 'porto_woocommerce_custom_tab_content',
982 'content' => $custom_tab_content,
983 );
984 }
985 return $tabs;
986}
987function porto_woocommerce_custom_tab_content( $key, $tab ) {
988 echo do_shortcode( $tab['content'] );
989}
990// woocommerce multilingual compatibility
991add_filter( 'wcml_multi_currency_is_ajax', 'porto_multi_currency_ajax' );
992function porto_multi_currency_ajax( $actions ) {
993 $actions[] = 'porto_product_quickview';
994 return $actions;
995}
996
997/* Register/Login */
998/**
999* Add new register fields for WooCommerce registration.
1000*
1001* @return string Register fields HTML.
1002*/
1003function porto_wooc_extra_register_start_fields() {
1004 global $porto_settings;
1005 if ( isset( $porto_settings['reg-form-info'] ) && 'full' == $porto_settings['reg-form-info'] ) :
1006 ?>
1007 <p class="form-row form-row-first">
1008 <label for="reg_billing_first_name"><?php esc_html_e( 'First Name', 'porto' ); ?><span class="required">*</span></label>
1009 <input type="text" class="woocommerce-Input woocommerce-Input--text input-text" name="billing_first_name" id="reg_billing_first_name" value="<?php echo ! empty( $_POST['billing_first_name'] ) ? esc_attr( $_POST['billing_first_name'] ) : ''; ?>" />
1010 </p>
1011 <p class="form-row form-row-last">
1012 <label for="reg_billing_last_name"><?php esc_html_e( 'Last Name', 'porto' ); ?><span class="required">*</span></label>
1013 <input type="text" class="woocommerce-Input woocommerce-Input--text input-text" name="billing_last_name" id="reg_billing_last_name" value="<?php echo ! empty( $_POST['billing_last_name'] ) ? esc_attr( $_POST['billing_last_name'] ) : ''; ?>" />
1014 </p>
1015 <div class="clear"></div>
1016 <?php
1017 endif;
1018}
1019add_action( 'woocommerce_register_form_start', 'porto_wooc_extra_register_start_fields' );
1020/**
1021* Validate the extra register fields.
1022*
1023* @param string $username Current username.
1024* @param string $email Current email.
1025* @param object $validation_errors WP_Error object.
1026*
1027* @return void
1028*/
1029function porto_wooc_validate_extra_register_fields( $username, $email, $validation_errors ) {
1030 global $porto_settings;
1031 if ( isset( $porto_settings['reg-form-info'] ) && 'full' == $porto_settings['reg-form-info'] ) {
1032 if ( isset( $_POST['billing_first_name'] ) && empty( $_POST['billing_first_name'] ) ) {
1033 $validation_errors->add( 'billing_first_name_error', __( '<strong>Error</strong>: First name is required!', 'porto' ) );
1034 }
1035 if ( isset( $_POST['billing_last_name'] ) && empty( $_POST['billing_last_name'] ) ) {
1036 $validation_errors->add( 'billing_last_name_error', __( '<strong>Error</strong>: Last name is required!.', 'porto' ) );
1037 }
1038 }
1039}
1040add_action( 'woocommerce_register_post', 'porto_wooc_validate_extra_register_fields', 10, 3 );
1041/**
1042* Save the extra register fields.
1043*
1044* @paramint $customer_id Current customer ID.
1045*
1046* @return void
1047*/
1048function porto_wooc_save_extra_register_fields( $customer_id ) {
1049 global $porto_settings;
1050 if ( isset( $porto_settings['reg-form-info'] ) && 'full' == $porto_settings['reg-form-info'] ) {
1051 if ( isset( $_POST['billing_first_name'] ) ) {
1052 // WordPress default first name field.
1053 update_user_meta( $customer_id, 'first_name', sanitize_text_field( $_POST['billing_first_name'] ) );
1054 // WooCommerce billing first name.
1055 update_user_meta( $customer_id, 'billing_first_name', sanitize_text_field( $_POST['billing_first_name'] ) );
1056 }
1057 if ( isset( $_POST['billing_last_name'] ) ) {
1058 // WordPress default last name field.
1059 update_user_meta( $customer_id, 'last_name', sanitize_text_field( $_POST['billing_last_name'] ) );
1060 // WooCommerce billing last name.
1061 update_user_meta( $customer_id, 'billing_last_name', sanitize_text_field( $_POST['billing_last_name'] ) );
1062 }
1063 }
1064}
1065add_action( 'woocommerce_created_customer', 'porto_wooc_save_extra_register_fields' );
1066// Confirm password field on the register form under My Accounts.
1067add_filter( 'woocommerce_registration_errors', 'registration_errors_validation', 10, 3 );
1068function registration_errors_validation( $reg_errors, $sanitized_user_login, $user_email ) {
1069
1070
1071 global $porto_settings, $woocommerce;
1072 if ( isset( $porto_settings['reg-form-info'] ) && 'full' == $porto_settings['reg-form-info'] && 'no' === get_option( 'woocommerce_registration_generate_password' ) ) {
1073 extract( $_POST );
1074 if ( strcmp( $password, $confirm_password ) !== 0 ) {
1075 return new WP_Error( 'registration-error', __( 'Passwords do not match.', 'porto' ) );
1076 }
1077 return $reg_errors;
1078 }
1079 return $reg_errors;
1080}
1081/* End - Register/Login */
1082/* Cart & Checkout - Start */
1083function porto_cart_version() {
1084 global $porto_settings;
1085 $cart_ver = ( isset( $porto_settings['cart-version'] ) && $porto_settings['cart-version'] ) ? $porto_settings['cart-version'] : 'v1';
1086 return apply_filters( 'porto_filter_cart_version', $cart_ver );
1087}
1088add_action( 'init', 'porto_wc_cart_page' );
1089function porto_wc_cart_page() {
1090 global $porto_settings;
1091 if ( porto_cart_version() == 'v2' ) {
1092 remove_action( 'woocommerce_cart_collaterals', 'woocommerce_cross_sell_display' );
1093 add_action( 'woocommerce_after_cart', 'woocommerce_cross_sell_display', 20 );
1094
1095 add_action( 'woocommerce_before_cart_totals', 'porto_shipping_calculator', 1 );
1096 }
1097}
1098function porto_shipping_calculator() {
1099 if ( WC()->cart->needs_shipping() && WC()->cart->show_shipping() ) {
1100 do_action( 'woocommerce_cart_totals_before_shipping' );
1101 wc_cart_totals_shipping_html();
1102 do_action( 'woocommerce_cart_totals_after_shipping' );
1103 } elseif ( WC()->cart->needs_shipping() ) {
1104 woocommerce_shipping_calculator();
1105 }
1106}
1107add_filter( 'body_class', 'porto_body_class' );
1108function porto_body_class( $classes ) {
1109 if ( is_cart() && porto_cart_version() == 'v2' ) {
1110 $classes[] = 'cart-v2';
1111 } elseif ( is_checkout() && porto_checkout_version() == 'v2' ) {
1112 $classes[] = 'checkout-v2';
1113 }
1114 // login popup
1115 global $porto_settings;
1116 if ( ! isset( $porto_settings['woo-account-login-style'] ) || ! $porto_settings['woo-account-login-style'] ) {
1117 $classes[] = 'login-popup';
1118 }
1119 return $classes;
1120}
1121function porto_checkout_version() {
1122 global $porto_settings;
1123 $checkout_ver = ( isset( $porto_settings['checkout-version'] ) && $porto_settings['checkout-version'] ) ? $porto_settings['checkout-version'] : 'v1';
1124 return apply_filters( 'porto_filter_checkout_version', $checkout_ver );
1125}
1126add_action( 'init', 'porto_wc_checkout_page' );
1127function porto_wc_checkout_page() {
1128 global $porto_settings;
1129 if ( porto_checkout_version() == 'v2' ) {
1130 add_action( 'woocommerce_review_order_before_payment', 'porto_woocommerce_review_order_before_payment' );
1131 }
1132}
1133function porto_woocommerce_review_order_before_payment() {
1134 echo '</div><div class="col-lg-6">';
1135}
1136/* End - Cart & Checkout */
1137
1138// woocommerce vendor start
1139if ( class_exists( 'WC_Vendors' ) ) {
1140 add_action( 'woocommerce_after_shop_loop_item_title', 'porto_wpvendors_product_seller_name', 2 );
1141 remove_action( 'woocommerce_product_meta_start', array( 'WCV_Vendor_Cart', 'sold_by_meta' ), 10, 2 );
1142 add_action( 'woocommerce_product_meta_start', 'porto_wc_vendors_sold_by_meta', 25, 2 );
1143 remove_action( 'woocommerce_after_shop_loop_item', array( 'WCV_Vendor_Shop', 'template_loop_sold_by' ), 9 );
1144
1145 add_filter( 'user_contactmethods', 'porto_add_to_author_profile', 10, 1 );
1146 function porto_add_to_author_profile( $contactmethods ) {
1147
1148 $contactmethods['phone_number'] = __( 'Phone Number', 'porto' );
1149 $contactmethods['facebook_url'] = __( 'Facebook Profile URL', 'porto' );
1150 $contactmethods['gplus_url'] = __( 'Google Plus Profil URL', 'porto' );
1151 $contactmethods['twitter_url'] = __( 'Twitter Profile URL', 'porto' );
1152 $contactmethods['linkedin_url'] = __( 'Linkedin Profile URL', 'porto' );
1153 $contactmethods['youtube_url'] = __( 'Youtube Profile URL', 'porto' );
1154 $contactmethods['flickr_url'] = __( 'Flickr Profile URL', 'porto' );
1155
1156 return $contactmethods;
1157 }
1158
1159 function porto_wpvendors_product_seller_name() {
1160
1161 global $porto_settings;
1162 $product_id = get_the_ID();
1163 $author = WCV_Vendors::get_vendor_from_product( $product_id );
1164
1165 $vendor_display_name = WC_Vendors::$pv_options->get_option( 'vendor_display_name' );
1166
1167 switch ( $vendor_display_name ) {
1168 case 'display_name':
1169 $vendor = get_userdata( $author );
1170 $vendor_name = $vendor->display_name;
1171 break;
1172 case 'user_login':
1173 $vendor = get_userdata( $author );
1174 $vendor_name = $vendor->user_login;
1175 break;
1176 default:
1177 $vendor_name = '';
1178 $vendor_name = WCV_Vendors::is_vendor( $author ) ? WCV_Vendors::get_vendor_shop_name( $author ) : get_bloginfo( 'name' );
1179
1180 }
1181
1182 $sold_by = ( WCV_Vendors::is_vendor( $author ) ) ? sprintf( '<a href="%s">%s</a>', WCV_Vendors::get_vendor_shop_page( $author ), $vendor_name ) : get_bloginfo( 'name' );
1183 if ( $porto_settings['porto_wcvendors_shop_soldby'] ) {
1184 echo '<p class="product-seller-name">' . apply_filters( 'wcvendors_sold_by_in_loop', __( 'By', 'porto' ) ) . ' <span>' . $sold_by . '</span> </p>';
1185 }
1186
1187 }
1188
1189 function porto_wc_vendors_sold_by_meta() {
1190 global $porto_settings;
1191 $author_id = get_the_author_meta( 'ID' );
1192 $vendor_display_name = WC_Vendors::$pv_options->get_option( 'vendor_display_name' );
1193
1194 switch ( $vendor_display_name ) {
1195 case 'display_name':
1196 $vendor = get_userdata( $author_id );
1197 $vendor_name = $vendor->display_name;
1198 break;
1199 case 'user_login':
1200 $vendor = get_userdata( $author_id );
1201 $vendor_name = $vendor->user_login;
1202 break;
1203 default:
1204 $vendor_name = '';
1205 $vendor_name = ( WCV_Vendors::is_vendor( $author_id ) ) ? WCV_Vendors::get_vendor_shop_name( $author_id ) : get_bloginfo( 'name' );
1206 }
1207
1208 $sold_by = WCV_Vendors::is_vendor( $author_id ) ? sprintf( '<a href="%s">%s</a>', WCV_Vendors::get_vendor_shop_page( $author_id ), $vendor_name ) : get_bloginfo( 'name' );
1209
1210 if ( $porto_settings['porto_wcvendors_product_soldby'] ) {
1211 echo '<ul class="list-item-details"><li class="list-item-details"><span class="data-type">' . esc_html__( 'Sold by : ', 'porto' ) . '</span><span class="value">' . $sold_by . '</span></li></ul>';
1212 }
1213 }
1214
1215 add_action( 'show_user_profile', 'porto_user_profile_fields' );
1216 add_action( 'edit_user_profile', 'porto_user_profile_fields' );
1217 function porto_user_profile_fields( $user ) {
1218 $r = get_user_meta( $user->ID, 'picture', true );
1219 ?>
1220 <!-- Artist Photo Gallery -->
1221 <h3><?php esc_html_e( 'Public Profile - Gallery', 'porto' ); ?></h3>
1222 <table class="form-table">
1223 <tr>
1224 <th scope="row">Picture</th>
1225 <td><input type="file" name="picture" value="" /></td>
1226 </tr>
1227 <tr>
1228 <td>
1229 <?php
1230 if ( $r && isset( $r['url'] ) ) {
1231 $r = $r['url'];
1232 echo "<img width='200px' src='$r' alt='profile' />";
1233 }
1234 ?>
1235 </td>
1236 </tr>
1237 </table>
1238 <?php
1239 }
1240 add_action( 'personal_options_update', 'save_extra_user_profile_fields' );
1241 add_action( 'edit_user_profile_update', 'save_extra_user_profile_fields' );
1242
1243 function save_extra_user_profile_fields( $user_id ) {
1244 if ( ! current_user_can( 'edit_user', $user_id ) ) {
1245 return false; }
1246 $_POST['action'] = 'wp_handle_upload';
1247 $r = wp_handle_upload( $_FILES['picture'] );
1248 update_user_meta( $user_id, 'picture', $r, get_user_meta( $user_id, 'picture', true ) );
1249 }
1250 add_action( 'user_edit_form_tag', 'make_form_accept_uploads' );
1251 function make_form_accept_uploads() {
1252 echo ' enctype="multipart/form-data"';
1253 }
1254 // Woocommerce Vendor Function More Product
1255 function porto_more_seller_product() {
1256 global $product, $porto_woocommerce_loop;
1257 if ( empty( $product ) || ! $product->exists() ) {
1258 return;
1259 }
1260 global $post;
1261 if ( ! WCV_Vendors::is_vendor( $post->post_author ) ) {
1262 return;
1263 }
1264 $meta_query = WC()->query->get_meta_query();
1265 $args = array(
1266 'post_type' => 'product',
1267 'post_status' => 'publish',
1268 'ignore_sticky_posts' => 1,
1269 'no_found_rows' => 1,
1270 'posts_per_page' => 4,
1271 'author' => get_the_author_meta( 'ID' ),
1272 'meta_query' => $meta_query,
1273 'orderby' => 'desc',
1274 );
1275 $products = new WP_Query( $args );
1276 $porto_woocommerce_loop['columns'] = isset( $porto_settings['product-related-cols'] ) ? $porto_settings['product-related-cols'] : $porto_settings['product-cols'];
1277 if ( ! $porto_woocommerce_loop['columns'] ) {
1278 $porto_woocommerce_loop['columns'] = 4;
1279 }
1280 if ( $products->have_posts() ) :
1281 ?>
1282 <div class="related products">
1283 <h2 class="slider-title"><span class="inline-title"><?php esc_html_e( 'More from this seller…', 'porto' ); ?></span></h2>
1284
1285 <?php woocommerce_product_loop_start(); ?>
1286 <?php
1287 while ( $products->have_posts() ) :
1288 $products->the_post();
1289 ?>
1290 <?php wc_get_template_part( 'content', 'product' ); ?>
1291 <?php endwhile; // end of the loop. ?>
1292
1293 </div>
1294
1295 <?php woocommerce_product_loop_end(); ?>
1296
1297 <?php
1298 endif;
1299 wp_reset_postdata();
1300 }
1301}
1302
1303// add color attribute type
1304add_filter( 'product_attributes_type_selector', 'porto_add_product_attribute_color', 10, 1 );
1305function porto_add_product_attribute_color( $attrs ) {
1306 return array_merge( $attrs, array( 'color' => __( 'Color', 'porto' ) ) );
1307}
1308add_action( 'woocommerce_product_option_terms', 'porto_add_product_attribute_color_variation', 10, 2 );
1309function porto_add_product_attribute_color_variation( $attribute_taxonomy, $i ) {
1310 if ( 'color' !== $attribute_taxonomy->attribute_type ) {
1311 return;
1312 }
1313
1314 global $product_object;
1315 if ( ! $product_object && isset( $_POST['post_id'] ) && isset( $_POST['product_type'] ) ) {
1316 $product_id = absint( $_POST['post_id'] );
1317 $product_type = ! empty( $_POST['product_type'] ) ? wc_clean( $_POST['product_type'] ) : 'simple';
1318 $classname = WC_Product_Factory::get_product_classname( $product_id, $product_type );
1319 $product_object = new $classname( $product_id );
1320 }
1321 if ( $product_object ) {
1322 $attributes = $product_object->get_attributes( 'edit' );
1323 if ( ! array_key_exists( 'pa_' . $attribute_taxonomy->attribute_name, $attributes ) ) {
1324 return;
1325 }
1326 $options = $attributes[ 'pa_' . $attribute_taxonomy->attribute_name ]->get_options();
1327 } else {
1328 $options = array();
1329 }
1330 ?>
1331 <select multiple="multiple" data-placeholder="<?php esc_attr_e( 'Select terms', 'woocommerce' ); ?>" class="multiselect attribute_values wc-enhanced-select" name="attribute_values[<?php echo esc_attr( $i ); ?>][]">
1332 <?php
1333 $args = array(
1334 'orderby' => 'name',
1335 'hide_empty' => 0,
1336 );
1337 $all_terms = get_terms( 'pa_' . $attribute_taxonomy->attribute_name, apply_filters( 'woocommerce_product_attribute_terms', $args ) );
1338 if ( $all_terms ) {
1339 foreach ( $all_terms as $term ) {
1340 $options = ! empty( $options ) ? $options : array();
1341 echo '<option value="' . esc_attr( $term->term_id ) . '" ' . selected( in_array( $term->term_id, $options ), true, false ) . '>' . esc_html( apply_filters( 'woocommerce_product_attribute_term_name', $term->name, $term ) ) . '</option>';
1342 }
1343 }
1344 ?>
1345 </select>
1346 <button class="button plus select_all_attributes"><?php esc_html_e( 'Select all', 'woocommerce' ); ?></button>
1347 <button class="button minus select_no_attributes"><?php esc_html_e( 'Select none', 'woocommerce' ); ?></button>
1348 <button class="button fr plus add_new_attribute"><?php esc_html_e( 'Add new', 'woocommerce' ); ?></button>
1349 <?php
1350}
1351
1352add_filter( 'woocommerce_dropdown_variation_attribute_options_html', 'porto_woocommerce_dropdown_variation_attribute_options_html', 10, 2 );
1353function porto_woocommerce_dropdown_variation_attribute_options_html( $select_html, $args ) {
1354 global $porto_settings;
1355 if ( isset( $porto_settings['product_variation_display_mode'] ) && 'select' === $porto_settings['product_variation_display_mode'] ) {
1356 return $select_html;
1357 }
1358 $args = wp_parse_args(
1359 apply_filters( 'woocommerce_dropdown_variation_attribute_options_args', $args ),
1360 array(
1361 'options' => false,
1362 'attribute' => false,
1363 'product' => false,
1364 'selected' => false,
1365 'name' => '',
1366 'id' => '',
1367 'class' => '',
1368 'show_option_none' => __( 'Choose an option', 'woocommerce' ),
1369 )
1370 );
1371 $options = $args['options'];
1372 $product = $args['product'];
1373 $attribute = $args['attribute'];
1374 $name = $args['name'] ? $args['name'] : 'attribute_' . sanitize_title( $attribute );
1375 $id = $args['id'] ? $args['id'] : sanitize_title( $attribute );
1376 $class = $args['class'];
1377 $show_option_none = $args['show_option_none'] ? true : false;
1378
1379 $is_color = false;
1380 $attribute_taxonomies = wc_get_attribute_taxonomies();
1381 if ( $attribute_taxonomies ) {
1382 foreach ( $attribute_taxonomies as $tax ) {
1383 if ( 'color' === $tax->attribute_type && wc_attribute_taxonomy_name( $tax->attribute_name ) === $attribute ) {
1384 $is_color = true;
1385 break;
1386 }
1387 }
1388 }
1389
1390 if ( empty( $options ) && ! empty( $product ) && ! empty( $attribute ) ) {
1391 $attributes = $product->get_variation_attributes();
1392 $options = $attributes[ $attribute ];
1393 }
1394
1395 $html = '';
1396 if ( ! empty( $options ) ) {
1397 $swatch_options = $product->get_meta( 'swatch_options', true );
1398 $key = md5( sanitize_title( $attribute ) );
1399
1400 $html .= '<ul class="filter-item-list" name="' . esc_attr( $name ) . '">';
1401 if ( $product ) {
1402 $select_html = '<select id="' . esc_attr( $id ) . '" class="' . esc_attr( $class ) . '" name="' . esc_attr( $name ) . '" data-attribute_name="attribute_' . esc_attr( sanitize_title( $attribute ) ) . '" data-show_option_none="' . ( $show_option_none ? 'yes' : 'no' ) . '">';
1403 $select_html .= '<option value=""></option>';
1404
1405 if ( taxonomy_exists( $attribute ) ) {
1406 // Get terms if this is a taxonomy - ordered. We need the names too.
1407 $terms = wc_get_product_terms( $product->get_id(), $attribute, array( 'fields' => 'all' ) );
1408 foreach ( $terms as $term ) {
1409 if ( in_array( $term->slug, $options ) ) {
1410 $attribute_terms[] = array(
1411 'id' => md5( $term->slug ),
1412 'slug' => $term->slug,
1413 'label' => $term->name,
1414 'term_id' => $term->term_id,
1415 );
1416 }
1417 }
1418 } else {
1419 foreach ( $options as $term ) {
1420 $attribute_terms[] = array(
1421 'id' => ( md5( sanitize_title( strtolower( $term ) ) ) ),
1422 'slug' => esc_html( $term ),
1423 'label' => esc_html( $term ),
1424 );
1425 }
1426 }
1427
1428 $is_image = false;
1429 if ( isset( $swatch_options[ $key ] ) && isset( $swatch_options[ $key ]['type'] ) ) {
1430 if ( ! $is_color ) {
1431 $is_color = 'color' == $swatch_options[ $key ]['type'];
1432 }
1433 $is_image = 'image' == $swatch_options[ $key ]['type'];
1434 }
1435 if ( $is_image ) {
1436 $image_size = isset( $swatch_options[ $key ]['size'] ) ? $swatch_options[ $key ]['size'] : 'swatches_image_size';
1437 }
1438
1439 foreach ( $attribute_terms as $term ) {
1440 if ( isset( $term['term_id'] ) ) {
1441 $color_value = get_woocommerce_term_meta( $term['term_id'], 'color_value' );
1442 }
1443 if ( ( ! isset( $color_value ) || ! $color_value ) && isset( $swatch_options[ $key ] ) && isset( $swatch_options[ $key ]['attributes'][ $term['id'] ]['color'] ) ) {
1444 $color_value = $swatch_options[ $key ]['attributes'][ $term['id'] ]['color'];
1445 }
1446 $current_attribute_image_src = '';
1447 if ( $is_image && isset( $swatch_options[ $key ]['attributes'][ $term['id'] ]['image'] ) ) {
1448 $current_attribute_image_id = $swatch_options[ $key ]['attributes'][ $term['id'] ]['image'];
1449 if ( $current_attribute_image_id ) {
1450 $current_attribute_image_src = wp_get_attachment_image_src( $current_attribute_image_id, $image_size );
1451 $current_attribute_image_src = $current_attribute_image_src[0];
1452 }
1453 }
1454
1455 if ( $is_color ) {
1456 $a_class = 'filter-color';
1457 $option_attrs = ' data-color="' . esc_attr( $color_value ) . '"';
1458 $a_attrs = ' style="background-color: ' . esc_attr( $color_value ) . '"';
1459 } elseif ( $is_image ) {
1460 $a_class = 'filter-item filter-image';
1461 $option_attrs = ' data-image="' . esc_url( $current_attribute_image_src ) . '"';
1462 if ( $current_attribute_image_src ) {
1463 $a_attrs = ' style="background-image: url(' . esc_url( $current_attribute_image_src ) . ')"';
1464 } else {
1465 $a_attrs = '';
1466 }
1467 } else {
1468 $a_class = 'filter-item';
1469 $option_attrs = '';
1470 $a_attrs = '';
1471 }
1472
1473 $select_html .= '<option' . $option_attrs . ' value="' . esc_attr( $term['slug'] ) . '" ' . selected( sanitize_title( $args['selected'] ), $term['slug'], false ) . '>' . esc_html( apply_filters( 'woocommerce_variation_option_name', $term['label'] ) ) . '</option>';
1474
1475 $html .= '<li>';
1476 $html .= '<a href="#" class="' . $a_class . '" data-value="' . esc_attr( $term['slug'] ) . '" ' . ( sanitize_title( $args['selected'] ) == $term['slug'] ? ' class="active"' : '' ) . $a_attrs . '>' . esc_html( apply_filters( 'woocommerce_variation_option_name', $term['label'] ) ) . '</a>';
1477 $html .= '</li>';
1478 }
1479 $select_html .= '</select>';
1480 }
1481 $html .= '</ul>';
1482 }
1483 return $html . $select_html;
1484}
1485
1486add_filter( 'woocommerce_layered_nav_term_html', 'porto_woocommerce_layed_nav_color_html', 10, 4 );
1487function porto_woocommerce_layed_nav_color_html( $term_html, $term, $link, $count ) {
1488 $term_html = '';
1489 $color_value = get_woocommerce_term_meta( $term->term_id, 'color_value' );
1490 $attrs = '';
1491 if ( $color_value ) {
1492 $attrs = ' class="filter-color" style="background-color: ' . esc_attr( $color_value ) . '"';
1493 }
1494
1495 // fix for yith ajax navigation
1496 if ( isset( $_GET['product_cat'] ) ) {
1497 $link = add_query_arg( array( 'product_cat' => $_GET['product_cat'] ), remove_query_arg( 'product_cat', $link ) );
1498 }
1499
1500 if ( $count > 0 ) {
1501 $link = str_replace( '#038;', '&', $link );
1502 $link = str_replace( '&&', '&', $link );
1503 $term_html = '<a href="' . esc_url( $link ) . '"' . $attrs . '>' . esc_html( $term->name ) . '</a>';
1504 } else {
1505 $link = false;
1506 $term_html = '<span' . $attrs . '>' . esc_html( $term->name ) . '</span>';
1507 }
1508 if ( $color_value ) {
1509 $before_html = ob_get_clean();
1510 $before_html = str_replace( '"woocommerce-widget-layered-nav-list"', '"woocommerce-widget-layered-nav-list filter-item-list"', $before_html );
1511 ob_start();
1512 echo porto_filter_output( $before_html );
1513 }
1514 return $term_html;
1515}
1516
1517add_filter( 'yith_woocommerce_reset_filter_link', 'porto_yith_woocommerce_reset_filter_link' );
1518function porto_yith_woocommerce_reset_filter_link( $link ) {
1519 if ( ! isset( $_GET['source_id'] ) && is_product_category() ) {
1520 global $wp_query;
1521 return esc_url( get_term_link( $wp_query->get_queried_object() ) );
1522 }
1523 return $link;
1524}
1525
1526// add to wishlist
1527add_filter( 'yith_wcwl_positions', 'porto_add_wishlist_button_position', 10, 1 );
1528function porto_add_wishlist_button_position( $position ) {
1529 $position['add-to-cart'] = array(
1530 'hook' => 'woocommerce_after_add_to_cart_button',
1531 'priority' => 31,
1532 );
1533 return $position;
1534}
1535
1536// horizontal filter
1537function porto_woocommerce_output_horizontal_filter() {
1538 global $porto_shop_filter_layout;
1539 if ( isset( $porto_shop_filter_layout ) && 'horizontal' === $porto_shop_filter_layout ) {
1540 if ( porto_is_ajax() && isset( $_COOKIE['porto_horizontal_filter'] ) && 'opened' == $_COOKIE['porto_horizontal_filter'] ) {
1541 $class = ' opened';
1542 } else {
1543 $class = '';
1544 }
1545 echo '<span class="porto-product-filters-toggle' . $class . '"><span>' . esc_html__( 'Filters:', 'porto' ) . '</span><a href="#"> </a></span>';
1546 } elseif ( isset( $porto_shop_filter_layout ) && 'horizontal2' === $porto_shop_filter_layout ) {
1547 echo '<div class="porto-product-filters style2 mobile-sidebar">';
1548 echo '<div class="sidebar-toggle"><i class="fa"></i></div>';
1549 echo '<div class="porto-product-filters-body">';
1550 dynamic_sidebar( 'woo-category-filter-sidebar' );
1551 echo '</div>';
1552 echo '</div>';
1553 unset( $porto_shop_filter_layout );
1554 }
1555}
1556
1557// sale product period
1558function porto_woocommerce_sale_product_period() {
1559 global $product;
1560 if ( $product->is_on_sale() ) {
1561 $is_single = is_singular( 'product' ) && is_single( $product->get_id() );
1562 $extra_class = '';
1563 if ( $is_single && $product->is_type( 'variable' ) ) {
1564 $variations = $product->get_available_variations();
1565 $date_diff = '';
1566 $sale_date = '';
1567 foreach ( $variations as $variation ) {
1568 $new_date = get_post_meta( $variation['variation_id'], '_sale_price_dates_to', true );
1569 if ( ! $new_date || ( $date_diff && $date_diff != $new_date ) ) {
1570 $date_diff = false;
1571 } elseif ( $new_date ) {
1572 if ( false !== $date_diff ) {
1573 $date_diff = $new_date;
1574 }
1575 $sale_date = $new_date;
1576 }
1577 if ( false === $date_diff && $sale_date ) {
1578 break;
1579 }
1580 }
1581 if ( $date_diff ) {
1582 $date_diff = date( 'Y/m/d H:i:s', (int) $date_diff );
1583 } elseif ( $sale_date ) {
1584 $extra_class .= ' for-some-variations';
1585 $date_diff = date( 'Y/m/d H:i:s', (int) $sale_date );
1586 }
1587 } else {
1588 $date_diff = $product->get_date_on_sale_to();
1589 if ( $date_diff ) {
1590 $date_diff = $product->get_date_on_sale_to()->date( 'Y/m/d H:i:s' );
1591 }
1592 }
1593 if ( $date_diff ) {
1594 echo '<div class="sale-product-daily-deal' . $extra_class . '"' . ( $extra_class ? ' style="display: none"' : '' ) . '>';
1595 echo '<h5 class="daily-deal-title">' . esc_html__( 'Offer Ends In:', 'porto' ) . '</h5>';
1596 if ( $is_single ) {
1597 echo do_shortcode( '[porto_countdown datetime="' . $date_diff . '" countdown_opts="sday,shr,smin,ssec" string_days="' . esc_attr__( 'Day', 'porto' ) . '" string_days2="' . esc_attr__( 'Days', 'porto' ) . '" string_hours="' . esc_attr__( 'Hour', 'porto' ) . '" string_hours2="' . esc_attr__( 'Hours', 'porto' ) . '" string_minutes="' . esc_attr__( 'Minute', 'porto' ) . '" string_minutes2="' . esc_attr__( 'Minutes', 'porto' ) . '" string_seconds="' . esc_attr__( 'Second', 'porto' ) . '" string_seconds2="' . esc_attr__( 'Seconds', 'porto' ) . '"]' );
1598 } else {
1599 echo do_shortcode( '[porto_countdown datetime="' . $date_diff . '" countdown_opts="sday,shr,smin,ssec" string_days="' . esc_attr__( 'Day', 'porto' ) . '" string_days2="' . esc_attr__( 'Days', 'porto' ) . '" string_hours=":" string_hours2=":" string_minutes=":" string_minutes2=":" string_seconds="" string_seconds2=""]' );
1600 }
1601 echo '</div>';
1602 }
1603 }
1604}
1605
1606// get sale end date
1607function porto_woocommerce_get_sale_end_date( $vars, $product, $variation ) {
1608 if ( $variation->is_on_sale() ) {
1609 $date_diff = $variation->get_date_on_sale_to();
1610 if ( $date_diff ) {
1611 $date_diff = $date_diff->date( 'Y/m/d H:i:s' );
1612 $vars['porto_date_on_sale_to'] = $date_diff;
1613 }
1614 }
1615 return $vars;
1616}
1617
1618// account login popup
1619add_action( 'wp_ajax_porto_account_login_popup', 'porto_account_login_popup' );
1620add_action( 'wp_ajax_nopriv_porto_account_login_popup', 'porto_account_login_popup' );
1621function porto_account_login_popup() {
1622 check_ajax_referer( 'porto-nonce', 'nonce' );
1623
1624 global $porto_settings;
1625 if ( ! is_checkout() && ! is_user_logged_in() && ( ! isset( $porto_settings['woo-account-login-style'] ) || ! $porto_settings['woo-account-login-style'] ) ) {
1626 $is_facebook_login = porto_nextend_facebook_login();
1627 $is_google_login = porto_nextend_google_login();
1628 $is_twitter_login = porto_nextend_twitter_login();
1629 echo '<div id="login-form-popup" class="lightbox-content">';
1630 echo wc_get_template_part( 'myaccount/form-login' );
1631 if ( ( $is_facebook_login || $is_google_login || $is_twitter_login ) && get_option( 'woocommerce_enable_myaccount_registration' ) == 'yes' && ! is_user_logged_in() ) {
1632 echo wc_get_template_part( 'myaccount/login-social' );
1633 }
1634 echo '</div>';
1635 die();
1636 }
1637}
1638add_action( 'wp_ajax_porto_account_login_popup_login', 'porto_account_login_popup_login' );
1639add_action( 'wp_ajax_nopriv_porto_account_login_popup_login', 'porto_account_login_popup_login' );
1640function porto_account_login_popup_login() {
1641
1642 $nonce_value = wc_get_var( $_REQUEST['woocommerce-login-nonce'], wc_get_var( $_REQUEST['_wpnonce'], '' ) ); // @codingStandardsIgnoreLine.
1643 $result = false;
1644 if ( wp_verify_nonce( $nonce_value, 'woocommerce-login' ) ) {
1645 try {
1646 $creds = array(
1647 'user_login' => trim( $_POST['username'] ),
1648 'user_password' => $_POST['password'],
1649 'remember' => isset( $_POST['rememberme'] ),
1650 );
1651
1652 $validation_error = new WP_Error();
1653 $validation_error = apply_filters( 'woocommerce_process_login_errors', $validation_error, $_POST['username'], $_POST['password'] );
1654
1655 if ( $validation_error->get_error_code() ) {
1656 echo json_encode(
1657 array(
1658 'loggedin' => false,
1659 'message' => '<strong>' . esc_html__(
1660 'Error:',
1661 'woocommerce'
1662 ) . '</strong> ' . $validation_error->get_error_message(),
1663 )
1664 );
1665 die();
1666 }
1667
1668 if ( empty( $creds['user_login'] ) ) {
1669 echo json_encode(
1670 array(
1671 'loggedin' => false,
1672 'message' => '<strong>' . esc_html__(
1673 'Error:',
1674 'woocommerce'
1675 ) . '</strong> ' . esc_html__(
1676 'Username is required.',
1677 'woocommerce'
1678 ),
1679 )
1680 );
1681 die();
1682 }
1683
1684 // On multisite, ensure user exists on current site, if not add them before allowing login.
1685 if ( is_multisite() ) {
1686 $user_data = get_user_by( is_email( $creds['user_login'] ) ? 'email' : 'login', $creds['user_login'] );
1687
1688 if ( $user_data && ! is_user_member_of_blog( $user_data->ID, get_current_blog_id() ) ) {
1689 add_user_to_blog( get_current_blog_id(), $user_data->ID, 'customer' );
1690 }
1691 }
1692
1693 // Perform the login
1694 $user = wp_signon( apply_filters( 'woocommerce_login_credentials', $creds ), is_ssl() );
1695 if ( ! is_wp_error( $user ) ) {
1696 $result = true;
1697 }
1698 } catch ( Exception $e ) {
1699 }
1700 }
1701 if ( $result ) {
1702 echo json_encode(
1703 array(
1704 'loggedin' => true,
1705 'message' => esc_html__(
1706 'Login successful, redirecting...',
1707 'porto'
1708 ),
1709 )
1710 );
1711 } else {
1712 echo json_encode(
1713 array(
1714 'loggedin' => false,
1715 'message' => esc_html__(
1716 'Wrong username or password.',
1717 'porto'
1718 ),
1719 )
1720 );
1721 }
1722 die();
1723}
1724add_action( 'wp_ajax_porto_account_login_popup_register', 'porto_account_login_popup_register' );
1725add_action( 'wp_ajax_nopriv_porto_account_login_popup_register', 'porto_account_login_popup_register' );
1726function porto_account_login_popup_register() {
1727
1728 $nonce_value = isset( $_POST['_wpnonce'] ) ? $_POST['_wpnonce'] : '';
1729 $nonce_value = isset( $_POST['woocommerce-register-nonce'] ) ? $_POST['woocommerce-register-nonce'] : $nonce_value;
1730 $result = true;
1731
1732 if ( wp_verify_nonce( $nonce_value, 'woocommerce-register' ) ) {
1733 $username = 'no' === get_option( 'woocommerce_registration_generate_username' ) ? $_POST['username'] : '';
1734 $password = 'no' === get_option( 'woocommerce_registration_generate_password' ) ? $_POST['password'] : '';
1735 $email = $_POST['email'];
1736
1737 try {
1738 $validation_error = new WP_Error();
1739 $validation_error = apply_filters( 'woocommerce_process_registration_errors', $validation_error, $username, $password, $email );
1740
1741 if ( $validation_error->get_error_code() ) {
1742 echo json_encode(
1743 array(
1744 'loggedin' => false,
1745 'message' => $validation_error->get_error_message(),
1746 )
1747 );
1748 die();
1749 }
1750
1751 $new_customer = wc_create_new_customer( sanitize_email( $email ), wc_clean( $username ), $password );
1752
1753 if ( is_wp_error( $new_customer ) ) {
1754 echo json_encode(
1755 array(
1756 'loggedin' => false,
1757 'message' => $new_customer->get_error_message(),
1758 )
1759 );
1760 die();
1761 }
1762
1763 if ( apply_filters( 'woocommerce_registration_auth_new_customer', true, $new_customer ) ) {
1764 wc_set_customer_auth_cookie( $new_customer );
1765 }
1766 } catch ( Exception $e ) {
1767 $result = false;
1768 }
1769 }
1770 if ( $result ) {
1771 echo json_encode(
1772 array(
1773 'loggedin' => true,
1774 'message' => esc_html__(
1775 'Register successful, redirecting...',
1776 'porto'
1777 ),
1778 )
1779 );
1780 } else {
1781 echo json_encode(
1782 array(
1783 'loggedin' => false,
1784 'message' => esc_html__(
1785 'Register failed.',
1786 'porto'
1787 ),
1788 )
1789 );
1790 }
1791 die();
1792}
1793
1794// shortcodes ajax action
1795add_action( 'wp_ajax_porto_woocommerce_shortcodes_products', 'porto_woocommerce_shortcodes_products' );
1796add_action( 'wp_ajax_nopriv_porto_woocommerce_shortcodes_products', 'porto_woocommerce_shortcodes_products' );
1797function porto_woocommerce_shortcodes_products() {
1798 check_ajax_referer( 'porto-nonce', 'nonce' );
1799
1800 $atts = '';
1801 $atts .= ' ids="' . esc_attr( $_POST['ids'] ) . '"';
1802 if ( $_POST['category'] ) {
1803 $atts .= ' category="' . esc_attr( $_POST['category'] ) . '"';
1804 }
1805 $atts .= ' columns="' . esc_attr( $_POST['columns'] ) . '"';
1806 $atts .= ' count="' . esc_attr( $_POST['count'] ) . '"';
1807 $atts .= ' orderby="' . esc_attr( $_POST['orderby'] ) . '"';
1808 $atts .= ' pagination_style="' . esc_attr( $_POST['pagination_style'] ) . '"';
1809 if ( isset( $_POST['product-page'] ) ) {
1810 $_GET['product-page'] = esc_attr( $_POST['product-page'] );
1811 }
1812 if ( isset( $_POST['view'] ) ) {
1813 $atts .= ' view="' . esc_attr( $_POST['view'] ) . '"';
1814 }
1815 echo '<div class="porto-products-response">';
1816 echo do_shortcode( '[porto_products' . $atts . ']' );
1817 if ( $_POST['category'] && isset( $_POST['category_description'] ) ) {
1818 $term = get_term_by( 'slug', $_POST['category'], 'product_cat', 'ARRAY_A' );
1819 if ( $term && isset( $term['description'] ) ) {
1820 WPBMap::addAllMappedShortcodes();
1821 echo '<div class="category-description">';
1822 echo do_shortcode( $term['description'] );
1823 echo '</div>';
1824 }
1825 }
1826 echo '</div>';
1827 die();
1828}
1829
1830// shortcodes image size
1831remove_action( 'woocommerce_before_subcategory_title', 'woocommerce_subcategory_thumbnail', 10 );
1832add_action( 'woocommerce_before_subcategory_title', 'porto_woocommerce_subcategory_thumbnail', 10 );
1833
1834if ( ! function_exists( 'porto_woocommerce_subcategory_thumbnail' ) ) :
1835 function porto_woocommerce_subcategory_thumbnail( $category ) {
1836
1837 global $porto_woocommerce_loop;
1838 $dimensions = false;
1839 if ( isset( $porto_woocommerce_loop['image_size'] ) && $porto_woocommerce_loop['image_size'] ) {
1840 $small_thumbnail_size = $porto_woocommerce_loop['image_size'];
1841 } else {
1842 $small_thumbnail_size = 'woocommerce_thumbnail';
1843 }
1844 $small_thumbnail_size = apply_filters( 'subcategory_archive_thumbnail_size', $small_thumbnail_size );
1845 $thumbnail_id = get_woocommerce_term_meta( $category->term_id, 'thumbnail_id', true );
1846
1847 if ( $thumbnail_id ) {
1848 $image = wp_get_attachment_image_src( $thumbnail_id, $small_thumbnail_size );
1849
1850 if ( isset( $porto_woocommerce_loop['image_size'] ) && $porto_woocommerce_loop['image_size'] ) {
1851 $dimensions = array(
1852 'width' => $image[1],
1853 'height' => $image[2],
1854 );
1855 }
1856
1857 $image = $image[0];
1858 $image_srcset = function_exists( 'wp_get_attachment_image_srcset' ) ? wp_get_attachment_image_srcset( $thumbnail_id, $small_thumbnail_size ) : false;
1859 $image_sizes = function_exists( 'wp_get_attachment_image_sizes' ) ? wp_get_attachment_image_sizes( $thumbnail_id, $small_thumbnail_size ) : false;
1860
1861 } else {
1862 $image = wc_placeholder_img_src();
1863 $image_srcset = false;
1864 $image_sizes = false;
1865 }
1866
1867 if ( $image ) {
1868 if ( ! $dimensions ) {
1869 $dimensions = wc_get_image_size( $small_thumbnail_size );
1870 }
1871 // Prevent esc_url from breaking spaces in urls for image embeds.
1872 // Ref: https://core.trac.wordpress.org/ticket/23605.
1873 $image = str_replace( ' ', '%20', $image );
1874
1875 // Add responsive image markup if available.
1876 if ( $image_srcset && $image_sizes ) {
1877 echo '<img src="' . esc_url( $image ) . '" alt="' . esc_attr( $category->name ) . '" width="' . esc_attr( $dimensions['width'] ) . '" height="' . esc_attr( $dimensions['height'] ) . '" srcset="' . esc_attr( $image_srcset ) . '" sizes="' . esc_attr( $image_sizes ) . '" />';
1878 } else {
1879 echo '<img src="' . esc_url( $image ) . '" alt="' . esc_attr( $category->name ) . '" width="' . esc_attr( $dimensions['width'] ) . '" height="' . esc_attr( $dimensions['height'] ) . '" />';
1880 }
1881 }
1882 }
1883endif;
1884
1885// add variable product attributes & quantity input on shop pages
1886add_filter( 'woocommerce_loop_add_to_cart_link', 'porto_woocommerce_display_quantity_input_on_shop_page', 10, 2 );
1887add_action( 'porto_woocommerce_before_shop_loop_item_title', 'porto_woocommerce_display_variation_on_shop_page' );
1888
1889function porto_woocommerce_display_quantity_input_on_shop_page( $html, $product ) {
1890
1891 global $porto_settings;
1892 $availability = $product->get_availability();
1893 $stock_status = $availability['class'];
1894 if ( 'quantity' == $porto_settings['category-addlinks-pos'] && $product->is_type( 'simple' ) && $product->is_purchasable() && 'out-of-stock' !== $stock_status ) {
1895 woocommerce_quantity_input(
1896 array(
1897 'min_value' => apply_filters( 'woocommerce_quantity_input_min', $product->get_min_purchase_quantity(), $product ),
1898 'max_value' => apply_filters( 'woocommerce_quantity_input_max', $product->get_max_purchase_quantity(), $product ),
1899 'input_value' => isset( $_POST['quantity'] ) ? wc_stock_amount( sanitize_text_field( wp_unslash( $_POST['quantity'] ) ) ) : $product->get_min_purchase_quantity(), // WPCS: CSRF ok, input var ok.
1900 )
1901 );
1902 }
1903 return $html;
1904}
1905
1906function porto_woocommerce_display_variation_on_shop_page() {
1907
1908 global $product, $porto_settings;
1909 if ( isset( $porto_settings['show_swatch'] ) && $porto_settings['show_swatch'] && $product->is_type( 'variable' ) ) {
1910 $attributes = $product->get_variation_attributes();
1911 $woocommerce_taxonomies = wc_get_attribute_taxonomies();
1912 $woocommerce_taxonomy_infos = array();
1913 foreach ( $woocommerce_taxonomies as $tax ) {
1914 $woocommerce_taxonomy_infos[ wc_attribute_taxonomy_name( $tax->attribute_name ) ] = $tax;
1915 }
1916
1917 $swatch_options = $product->get_meta( 'swatch_options', true );
1918
1919 foreach ( $attributes as $key => $attr ) {
1920 if ( array_key_exists( $key, $woocommerce_taxonomy_infos ) && isset( $woocommerce_taxonomy_infos[ $key ]->attribute_type ) ) {
1921 if ( 'color' != $woocommerce_taxonomy_infos[ $key ]->attribute_type ) {
1922 if ( $swatch_options ) {
1923 $swatch_key = md5( sanitize_title( $key ) );
1924 if ( ! isset( $swatch_options[ $swatch_key ] ) || ( 'color' != $swatch_options[ $swatch_key ]['type'] && 'image' != $swatch_options[ $swatch_key ]['type'] ) ) {
1925 unset( $attributes[ $key ] );
1926 }
1927 } else {
1928 unset( $attributes[ $key ] );
1929 }
1930 }
1931 }
1932 }
1933
1934 wc_get_template(
1935 'single-product/add-to-cart/variable.php',
1936 array(
1937 'available_variations' => $product->get_available_variations(),
1938 'attributes' => $attributes,
1939 'selected_attributes' => $product->get_default_attributes(),
1940 'no_add_to_cart' => true,
1941 )
1942 );
1943 }
1944}
1945
1946if ( ! function_exists( 'porto_woocommerce_product_sticky_addcart' ) ) :
1947 /**
1948 *
1949 */
1950 function porto_woocommerce_product_sticky_addcart() {
1951 global $porto_settings;
1952 if ( ! is_product() || ! isset( $porto_settings['product-sticky-addcart'] ) || ! $porto_settings['product-sticky-addcart'] ) {
1953 return;
1954 }
1955
1956 global $product;
1957 $attachment_id = method_exists( $product, 'get_image_id' ) ? $product->get_image_id() : get_post_thumbnail_id();
1958 $availability = $product->get_availability();
1959 $average = $product->get_average_rating();
1960
1961 echo '<div class="sticky-product hide"><div class="container">';
1962 echo '<div class="sticky-image">';
1963 echo wp_get_attachment_image( $attachment_id, 'thumbnail' );
1964 echo '</div>';
1965 echo '<div class="sticky-detail">';
1966 echo '<div class="product-name-area">';
1967 echo '<h2 class="product-name">' . get_the_title() . '</h2>';
1968 echo woocommerce_template_single_price();
1969 echo '</div>';
1970 echo '<div class="star-rating" title="' . $average . '">';
1971 echo '<span style="width:' . ( ( $average / 5 ) * 100 ) . '%"></span>';
1972 echo '</div>';
1973 echo '<div class="availability"><span>' . ( 'out-of-stock' == $availability['class'] ? esc_html__( 'Out of stock', 'porto' ) : esc_html__( 'In stock', 'porto' ) ) . '</span></div>';
1974 echo '</div>';
1975 echo '<div class="add-to-cart">';
1976 echo '<button type="submit" class="single_add_to_cart_button button">' . esc_html__( 'Add to cart', 'woocommerce' ) . '</button>';
1977 echo '</div>';
1978 echo '</div></div>';
1979 }
1980endif;