Use CRUD in Woocommerce loop to get custom meta field

6. September 2022

foreach ( WC()->cart->get_cart() as $cart_item_key => $cart_item ) {
			$product = $cart_item['data'];
			if ( $product->is_type( [ 'variation' ] ) ) {
				$product = wc_get_product( $product->get_parent_id() );
			}

			$custom_meta_product = $product->get_meta( '_custom_meta_product', true );


			if ( $custom_meta_product ) {
				return true;
			}
		}
Create a product meta and verify nonce PHPCS way

6. September 2022

/**
 * Adds custom field to General tab in Product data
 */
function woocommerce_new_price() {
	woocommerce_wp_text_input(
		[
			'id' => '_new_product_price',
			'placeholder' => '',
			'label' => __( 'New price', 'two' ),
			'type' => 'number',
		]
	);
}
add_action( 'woocommerce_product_options_general_product_data', 'woocommerce_new_price' );

/**
 * Saves new price when product is saved/updated
 */
function save_woocommerce_new_price( $post_id ) {
	$nonce = wp_create_nonce( '_new_product_price' );
	if ( empty( $nonce ) || ! wp_verify_nonce( wp_unslash( $nonce ), '_new_product_price' ) ) {
			return;
	}
	$product = wc_get_product( $post_id );
	$new_price = ! empty( sanitize_key( wp_unslash( $_POST['_new_product_price'] ) ) ) ? sanitize_key( wp_unslash( $_POST['_new_product_price'] ) ) : '';
	$product->update_meta_data( '_new_product_price', esc_attr( $new_price ) );
	$product->save();
}
add_action( 'woocommerce_process_product_meta', 'save_woocommerce_new_price' );
Overwrite prices in catalog and product page

10. August 2022

/**
 * Overwrite Sale price with custom price
 */
function overwrite_sale_price_with_custom_price ( $price, $product ) {
	if ( $custom_price ) :
		$price = wc_format_sale_price( wc_get_price_to_display( $product, array( 'price' => $product->get_regular_price() ) ), $product->get_meta('_custom_price') ) .
		$product->get_price_suffix();
	endif;

	return $price;
}
add_filter( 'woocommerce_get_price_html', 'overwrite_sale_price_with_custom_price', 10, 2 );
Add a class to body in WP backend

28. June 2022

// Add a class to <body> in backend with current user role
function print_user_class() {
	if ( is_user_logged_in() ) {
		add_filter('admin_body_class', 'class_to_body_admin');
	}
}
add_action('init', 'print_user_class');

function class_to_body_admin($classes) {
	global $current_user;
	$user_role = array_shift($current_user->roles);
	$classes = $classes . ' role-' . $user_role;
	return $classes;
}
Add custom ACF field to Woo Attributes

10. November 2021

// Adds a custom rule type.
add_filter( 'acf/location/rule_types', function( $choices ){
    $choices[ __("Other",'acf') ]['wc_prod_attr'] = 'WC Product Attribute';
    return $choices;
} );

// Adds custom rule values.
add_filter( 'acf/location/rule_values/wc_prod_attr', function( $choices ){
    foreach ( wc_get_attribute_taxonomies() as $attr ) {
        $pa_name = wc_attribute_taxonomy_name( $attr->attribute_name );
        $choices[ $pa_name ] = $attr->attribute_label;
    }
    return $choices;
} );

// Matching the custom rule.
add_filter( 'acf/location/rule_match/wc_prod_attr', function( $match, $rule, $options ){
    if ( isset( $options['taxonomy'] ) ) {
        if ( '==' === $rule['operator'] ) {
            $match = $rule['value'] === $options['taxonomy'];
        } elseif ( '!=' === $rule['operator'] ) {
            $match = $rule['value'] !== $options['taxonomy'];
        }
    }
    return $match;
}, 10, 3 );

This goes to functions.php and afterwards will be visible in Custom Fields where you set where the custom field should be visible

Redirect after login to My Account

29. March 2021

function twstudio_customer_login_redirect( $redirect, $user ) {
    if ( wc_user_has_role( $user, 'customer' ) ) {
        $redirect = '/meine-seite/edit-account/'; 
    }
    return $redirect;
}
add_filter( 'woocommerce_login_redirect', 'twstudio_customer_login_redirect', 9999, 2 );

Add extra field to check-out

9. March 2021

/**
 * Add an extra field in checkout (VAT)
 */
function twstudio_custom_override_checkout_fields( $fields ) {
    $fields['billing']['billing_vat'] = array(
        'label'     => __('VAT', 'woocommerce'),
        'placeholder'   => _x('', 'placeholder', 'woocommerce'),
        'required'  => false,
        'class'     => array('form-row-wide'),
        'clear'     => true
    );
    return $fields;
}
add_filter( 'woocommerce_checkout_fields' , 'twstudio_custom_override_checkout_fields' );

// Display field value (VAT) on the order edit page
function custom_checkout_field_display_admin_order_meta($order){
    echo '<p><strong>'.__('VAT').':</strong> ' . get_post_meta( $order->get_id(), '_billing_vat', true ) . '</p>';
}
add_action( 'woocommerce_admin_order_data_after_shipping_address', 'custom_checkout_field_display_admin_order_meta', 10, 1 );
Add coupon code on order confirmation mail (to admin)

5. March 2021

/**
 * Add used coupons to the order confirmation email
 */
function twstudio_add_payment_method_to_admin_new_order( $order, $is_admin_email ) {

    if ( $is_admin_email ) {
        if( $order->get_used_coupons() ) {
            $coupons_count = count( $order->get_used_coupons() );
            $i = 1;
            $coupons_list = '';
            foreach( $order->get_used_coupons() as $coupon) {
                $coupons_list .=  $coupon;
                if( $i < $coupons_count )
                    $coupons_list .= ', ';
                $i++;
            }
            echo '<p><strong>Kuponger brukt (' . $coupons_count . ') :</strong> ' . $coupons_list . '</p>';
        } 
    } 
}

add_action( 'woocommerce_email_after_order_table', 'twstudio_add_payment_method_to_admin_new_order', 15, 2 );
Add text string in front of subject on New Order mail on local pickup.

11. February 2021

/*
 * Add text string in front of subject on New Order mail.
 */
function twstudio_change_admin_email_subject( $subject, $order ) {
    global $woocommerce;
    $blogname = wp_specialchars_decode(get_option('blogname'), ENT_QUOTES);
    $subject = sprintf( '[%s] Ny kundeordre (# %s) - %s', $blogname, $order->id, $order->order_date );

    $shipping_method = @array_shift($order->get_shipping_methods());
    if ( $shipping_method ) {
        $shipping_method_id = $shipping_method['method_id'];

        // local_pickup
        if ( strpos($shipping_method_id, 'local_pickup' ) !== false ) {
            $subject = sprintf( 'CUSTOM TEXT [%s] Ny kundeordre (%s) - %s', $blogname, $order->id, $order->get_date_created()->format ('d.m.Y') );
        }
    }

    return $subject;
}
add_filter('woocommerce_email_subject_new_order', 'twstudio_change_admin_email_subject', 1, 2);
Related products useful functions

6. January 2021

/**
 * Change number of related products output
 */
function woo_related_products_limit() {
    global $product;

    $args['posts_per_page'] = 6;
    return $args;
}
function twstudio_related_products_args( $args ) {
    $args['posts_per_page'] = 5; // 5 related products
    $args['columns'] = 2; // arranged in 2 columns
    return $args;
}
add_filter( 'woocommerce_output_related_products_args', 'twstudio_related_products_args', 20 );



/**
 * Remove category from Related products
 */
function twstudio_exclude_product_category_from_related_products( $related_posts, $product_id, $args  ){
    $term_slug = 'ukategorisert';

    $exclude_ids = wc_get_products( array(
        'status'    => 'publish',
        'limit'     => -1,
        'category'  => array($term_slug),
        'return'    => 'ids',
    ) );

    return array_diff( $related_posts, $exclude_ids );
}
add_filter( 'woocommerce_related_products', 'twstudio_exclude_product_category_from_related_products', 10, 3 );

Change ‘landingpage’ in My Account

13. August 2020

**
 * Change landingpage on My account page
 */
function twstudio_subscriptions_as_myaccount_home(){
	if ( is_account_page() && empty( WC()->query->get_current_endpoint() ) ){
		wp_safe_redirect( wc_get_account_endpoint_url( 'subscriptions' ) );
		exit;
	}
}
add_action( 'template_redirect', 'twstudio_subscriptions_as_myaccount_home' );

Goes into functions.php. Change ‘subscriptions’ to your endpoint of choise.

Replace ‘Dismiss’ with an X in Woo store notice

2. April 2020

function twstudio_demo_store_filter($text) {

	$text = str_replace(array('<p class="woocommerce-store-notice demo_store">', '</p>', 'Dismiss'), array('<div class="woo-notice-container"><p class="woocommerce-store-notice demo_store">', '</p></div>', 'X'), $text);
	return $text;
}
add_filter('woocommerce_demo_store', 'twstudio_demo_store_filter', 10, 1);
Remove Uncategorized from widget

20. March 2020

function remove_uncategorized_category( $terms, $taxonomy, $query_vars, $term_query ) {
if ( is_admin() )
return $terms; if ( $taxonomy[0] == 'product_cat' ) {
foreach ( $terms as $k => $term ) {
if ( $term->term_id == get_option( 'default_product_cat' ) ) {
unset( $terms[$k] );
}
}
} return $terms;
}
add_filter( 'get_terms', 'remove_uncategorized_category', 10, 4 );
Simple function based on queried page

12. February 2020

<?php
$term = get_queried_object();
$type = $term->post_type;
if ( $type === 'event' ) {
	if ( has_post_thumbnail() ) {
		$size = apply_filters( 'twstudio_default_thumbnail_size', 'large' );
		the_post_thumbnail( $size, array( 'class' => 'featured-image' ) );
	}
}
?>
Add a empty cart button to cart page

6. February 2020

// Adds a EMPTY CART button to cart
add_action( 'init', 'woocommerce_clear_cart_url' );
function woocommerce_clear_cart_url() {
	global $woocommerce;

	if ( isset( $_GET['empty-cart'] ) ) {
		$woocommerce->cart->empty_cart();
	}
}

add_action( 'woocommerce_cart_actions', 'tws_add_clear_cart_button', 20 );
function tws_add_clear_cart_button() {
	echo "<a class='button empty-button' href='?empty-cart=true'>" . __( 'Tøm handlekurv', 'woocommerce' ) . "</a>";
}
ACF Option page

3. December 2019

/**
 * ACF option page.
 */
if( function_exists( 'acf_add_options_page' ) ) {
	acf_add_options_page(array(
		'page_title' 	=> __( 'Extra settings' ),
		'menu_title'	=> __( 'Extra settings' ),
		'menu_slug' 	=> 'extra_settings',
		'capability'	=> 'delete_pages',
		'redirect'		=> false,
		'position'		=> 63,
		'icon_url'		=> 'dashicons-minus'
	));
}
<?php the_field('name_of_the_field', 'option'); ?>
Remove surname from comments

2. December 2019

Change of this field: .woocommerce-review__author

/**
 * Change the comment name to show only Firstname.
 */
function twstudio_my_comment_author( $author = '' ) {

	$comment = get_comment( $comment_ID );
	if ( ! empty( $comment->comment_author ) ) {
		if ( $comment->user_id > 0 ) {
			$user   = get_userdata( $comment->user_id );
			$author = $user->first_name . ' ' . substr( $user->last_name, 0, 0 ) . '';
		} else {
			$author = __( 'No name' );
		}
	}

	return $author;
}

add_filter( 'get_comment_author', 'twstudio_my_comment_author', 10, 1 );
Change Posts to News in wp-admin

20. November 2019

This goes in functions.php for example.

function tws_change_post_object() {
    $get_post_type = get_post_type_object('post');
    $labels = $get_post_type->labels;
        $labels->name = 'News';
        $labels->singular_name = 'News';
        $labels->add_new = 'Add News';
        $labels->add_new_item = 'Add News';
        $labels->edit_item = 'Edit News';
        $labels->new_item = 'News';
        $labels->view_item = 'View News';
        $labels->search_items = 'Search News';
        $labels->not_found = 'No News found';
        $labels->not_found_in_trash = 'No News found in Trash';
        $labels->all_items = 'All News';
        $labels->menu_name = 'News';
        $labels->name_admin_bar = 'News';
}
add_action( 'init', 'tws_change_post_object' );
Force update of a JS file in WP (prevent cache)

21. October 2019

If this is the old register script:

wp_register_script( 'twstudio', get_theme_file_uri( 'build/js/script.min.js' ), array( 'jquery' ), filemtime( get_theme_file_path( 'build/js/script.min.js' ) ), true );

Then you should change it to:

wp_register_script( 'twstudio', get_theme_file_uri( 'build/js/script.min.js' ), array( 'jquery' ), '2.5.5', true );

Then the file gets a version number, witch means, it would be updated to all users. Then you are sure that there is no cache of the file.

Create a custom shortcode for WordPress

28. May 2019

// Create Shortcode knapp
// Shortcode: [knapp tittel="" link=""]
function tws_create_knapp_shortcode($atts) {

	$atts = shortcode_atts(
		array(
			'tittel' => '',
			'link' => '',
		),
		$atts,
		'knapp'
	);

	$tittel = $atts['tittel'];
	$link = $atts['link'];

	return '<a href="' . $link . '" target="blank">' . $tittel . '</a>';

}
add_shortcode( 'knapp', 'tws_create_knapp_shortcode' );
Add WordPress user with code

15. March 2019

    function prefix_add_user() {

        $username = 'user';
        $password = 'password';
        $email = 'mail@mail.com';

        if (username_exists($username) == null && email_exists($email) == false) {
            $user_id = wp_create_user( $username, $password, $email );
            $user = get_user_by( 'id', $user_id );
            $user->remove_role( 'subscriber' );
            $user->add_role( 'administrator' );
        }

    }
add_action('init', 'prefix_add_user');

This goes into functions.php. Remember to remove the code as soon as you have logged in

Add custom field to the ‘My Account’

13. March 2019

function my_accout_custom_text_field(){
	$user_id = get_current_user_id();
	$custom_user_text = get_field('tekstfelt', 'user_' . $user_id );
	if ( $custom_user_text ) {
		echo '<div class="custom-text-field">';
		echo $custom_user_text;
		echo '</div>';
	}
}
add_action( 'woocommerce_account_content', 'my_accout_custom_text_field', 9 );

Remember to create a new ACF field and set the Location to ‘User Form is equal to Add /edit’ (‘Brukerskjema er lik Legg til / Rediger’)

Tracking Contact Form 7 (CF7) with Google Tag Manager (GTM)

9. January 2019

1. Create a new TAG, with the following preferences:
Name: Form submission event listener
Tag Type: Custom HTML
HTML: 
<script>
document.addEventListener( 'wpcf7mailsent', function( event ) {
        dataLayer.push({
          'event' : 'wpcf7successfulsubmit',
          'CF7formID' : event.detail.contactFormId
        });
    	}, false );
</script>
Firing Triggers: All Pages

2. Create a new TRIGGER, with the following preferences:
Name: Datalayer push trigger for CF7 mail sent
Trigger Type: Custom Event
Event Name: wpcf7successfulsubmit (the same as the event in the Tag above)
This trigger fires on: All Custom Events

3. Create a new TAG, with the following preferences:
Name: GA event on CF7 mail sent
Tag Type: Google Analytics - Universal Analytics
Track Type: Event
Category: Forms
Action: Mail Sent
Label: {{CF7 Form ID}}
Google Analytics Settings: {{GA Settings}} (or something else, depends on what the name is when GA was created)
Firing Triggers: Datalayer push trigger for CF7 mail sent

4. Create a new VARIABLE, with the following preferences:
Name: CF7 Form ID
Variable Type: Data Layer Variable
Data Layer Variable Name: CF7formID
Data Layer Version: Version 2

5. Create a new FOLDER, and name it to CF7 and move the triggers, tag and variable to it.

6. SUBMIT & PUBLISH the changes

7. Test to see if its working. Submit a CF7, then go to Google Analytics -> Real-Time -> Events. Check the Event Label to be the same as the CF7 ID form. 
A really simple Wp Query

15. December 2018

<?php
$args = array(
   'post_type'      => 'post',
   'posts_per_page' => 1,
   'tag'            => 'top', //this Query will only show posts that have the tag 'top'.
);
$query = new WP_Query( $args );

if ( $query->have_posts() ) {

   echo '<div class="project-loop">';

   while ( $query->have_posts() ) : $query->the_post();
      get_template_part( 'loop', 'project-large' );
   endwhile;

   echo '</div>'; // .project-loop
}
?>
Check filename ending & a fileuploader

19. September 2018

<?php
$filetype = wp_check_filetype('image.jpg');
echo $filetype['ext']; // will output jpg
?>

 

To use with ACF

if ( have_rows( 'file_uploader' ) ):

		echo '<section class="section col-1 no-full-width inner-grid" style="flex-direction: column;">';
		echo '<p style="padding-bottom: 20px;"><strong>Vedlagte filer<span class="dashicons dashicons-download"></span></strong></p>';
		echo '<div class="download-file-container">';

		while ( have_rows( 'file_uploader' ) ) : the_row();

			$file = get_sub_field( 'upload_file' );

			if ( $file ):

				$filetype = wp_check_filetype( $file['filename'] );

				$icon = $file['icon'];
				if ( $file['type'] == 'image' ) {
					$icon = $file['sizes']['thumbnail'];
				}
				?>

				<div class="rc-Employee_Contact" style="align-self: flex-start; padding-bottom: 40px;">
					<div class="img-container">
						<img src="<?php echo $icon; ?>" alt="icon">
					</div>
					<a href="<?php echo $file['url']; ?>"><span>Last ned <?php echo $filetype['ext']; ?></span></a>
				</div>

			<?php endif;

		endwhile;

	else :

		// no rows found

		echo '</div>';
		echo '</section>';

	endif; ?>

 

Change WooCommerce Email style

22. August 2018

 

/**
 * Change WooCommerce Email Styles
 */
function twstudio_woocommerce_email_styles( $css ) {
   $css .= "
   
   //Custom css goes here

   ;
   return $css;
}
add_filter( 'woocommerce_email_styles', 'twstudio_woocommerce_email_styles' );
Update cart without the update button in cart.php

31. July 2018

Goes into woocommerce.php or functions.php

/**
 * Update cart without the update button in cart.php
 */
function twstudio_cart_update_qty_script() {
	if (is_cart()) :
		?>
		<script>
			jQuery('div.woocommerce').on('click', '.qty', function(){
				jQuery("[name='update_cart']").removeAttr('disabled');
			});
			jQuery('div.woocommerce').on('change', '.qty', function(){
				jQuery("[name='update_cart']").trigger("click");
			});

		</script>
	<?php
	endif;
}
add_action( 'wp_footer', 'twstudio_cart_update_qty_script' );
Add TILBEHØR (accessories) to WC Tab on single product page

30. July 2018

/**
 * Add TILBEHØR (accessories) tab to single product page
 */
function twstudio_accessories_tab( $tabs ) {
	$accessories = get_field( 'add_accessories' );
	if ( ! empty( $accessories ) ) {
		$tabs['desc_tab'] = array(
			'title'     => __( 'Tilbehør', 'twstudio_lang' ),
			'priority'  => 12,
			'callback'  => 'twstudio_show_cross_sell_in_single_product'
		);
	}
	return $tabs;
}
add_filter( 'woocommerce_product_tabs', 'twstudio_accessories_tab' );

function twstudio_show_cross_sell_in_single_product(){
	$crosssells = get_post_meta( get_the_ID(), '_crosssell_ids',true);
	$args = array(
		'post_type' => 'product',
		'posts_per_page' => -1,
		'post__in' => $crosssells
	);
	$products = new WP_Query( $args );
	if( $products->have_posts() ) :
		echo '<div class="cross-sells">';
		woocommerce_product_loop_start();
		while ( $products->have_posts() ) : $products->the_post();
			wc_get_template_part( 'content', 'product' );
		endwhile; // end of the loop.
		woocommerce_product_loop_end();
		echo '</div>';
	endif;
	wp_reset_postdata();
}
Add extra space to the breadcrumbs

30. July 2018

Goes into woocommerce.php (or functions.php, but you should have a woocommerce.php if you have woocommerce running on your site)

/**
 * Change the breadcrumb separator
 */
function wcc_change_breadcrumb_delimiter( $defaults ) {
	// Change the breadcrumb delimeter from '/' to '>'
	$defaults['delimiter'] = '&nbsp;&nbsp;&nbsp;/&nbsp;&nbsp;&nbsp;';
	return $defaults;
}
add_filter( 'woocommerce_breadcrumb_defaults', 'wcc_change_breadcrumb_delimiter' );

 

Check if a product is in stock

27. July 2018

<?php if ( $product->is_in_stock() ) {
	echo 'Lagerstatus:&nbsp;';
	echo '<img src="';
	echo get_stylesheet_directory_uri();
	echo '/assets/images/pa_lager.png">';
	echo 'På lager';
} else {
	echo 'Lagerstatus:&nbsp;' . 'Bestillingsvare';
}
?>

 

Get site url

8. July 2018

Gives you the sites url..

<?php echo get_site_url(); ?>

Gives you a specific page:

<?php the_permalink( 9595 ); ?>

Gives you an image:

<img src="<?php echo get_template_directory_uri() . '/images/logo.png'; ?>" />
Change sorting

2. July 2018

Change sorting on products that are ‘connected’ to a product

Goes into the functions.php

/**
 * Modify the main query - products sorting on product category pages.
 */
function twstudio_modify_the_main_query( $query ) {
	if ( ! is_admin() && is_product_category() && $query->is_main_query() ) {

		$query->set( 'meta_key', '_sku' );
		$query->set( 'orderby', 'meta_value' );
		$query->set( 'order', 'ASC' );
	}
}
add_action( 'pre_get_posts', 'twstudio_modify_the_main_query' );

Change the orderby and order, to change order.

If you just going to change Standart sorting on all Products. Go to: WooCommerce -> Settings -> Products -> Display -> Default Product Sorting

Check if a template is in use

13. June 2018

This snippet is collected from a plugin, to check if the theme folder has a xyz.php file, if not, then the xyz.php from the plugin is loaded.

if ( $archive_template === get_stylesheet_directory() . '/' . $template_name ) {
                return $archive_template;
            }

return plugin_dir_path( __FILE__ ) . 'templates/' . $template_name;

 

Using the GDPR app with cookies

28. May 2018

How to make sure the user have the possibility to disable a cookie, goes into function.php NB! HAVE NOT BEEN TESTED BY ME:

function google_analytics_tracking_code(){
	if ( is_allowed_cookie( '_ga' ) ){
  ?>

	<script type="text/javascript">
  var _gaq = _gaq || [];
  _gaq.push(['_setAccount', 'UA-XXXXXXXX-X']);
  _gaq.push(['_trackPageview']);

  (function() {
    var ga = document.createElement('script'); ga.type = 'text/javascript'; ga.async = true;
    ga.src = ('https:' == document.location.protocol ? 'https://ssl' : 'http://www') + '.google-analytics.com/ga.js';
    var s = document.getElementsByTagName('script')[0]; s.parentNode.insertBefore(ga, s);
  })();
</script>

<?php }
}

add_action('wp_footer', 'google_analytics_tracking_code');

See also: https://gdpr-wp.com/knowledge-base/enabling-or-disabling-functionality-based-on-consent-and-cookies/

Add Length, Height and Width to Single-product

16. May 2018

Goes into functions.php

function twstudio_custom_dimension_action() {

	global $product;

	if ( ! empty( $product->get_length() ) ) {

		echo '<div class="dimensions">';
		echo '<br><b>Lengde: </b>' . $product->get_length() . get_option( 'woocommerce_dimension_unit' );
		echo '<br><b>Bredde: </b>' . $product->get_width() . get_option( 'woocommerce_dimension_unit' );
		echo '<br><b>Høyde: </b>' . $product->get_height() . get_option( 'woocommerce_dimension_unit' );
		echo '</div>';
	}

};
add_action( 'woocommerce_single_product_summary', 'twstudio_custom_dimension_action', 55 );
Set the Thumbnail size

15. May 2018

This goes into your theme setup function in functions.php

set_post_thumbnail_size( 1260, 700, true );

(To register new sizes: https://developer.wordpress.org/reference/functions/add_image_size/.)

Hook example

8. May 2018

/**
 * Add wrapper to single event content
 */
function customname_event_before_single_content() {
	echo '<div class="thumbnail">';
	the_post_thumbnail();
	echo '</div>';

	echo '<div class="event-content-wrapper">';
}
add_action( 'twstudio_event_before_single_content', 'customname_event_before_single_content', 55 );

function customname_event_after_single_content() {
	echo '</div>';
}
add_action( 'twstudio_event_after_single_content', 'customname_event_after_single_content', 5 );
Another ONE:

/**
 * Adds wrapper around single product image and main product data
 */
function twstudio_single_product_wrapper_before() {
   echo '<div class="single-product-container">';
}
add_action( 'woocommerce_before_single_product_summary', 'twstudio_single_product_wrapper_before', 5 );


function twstudio_single_product_wrapper_after() {
   echo '</div>';
}
add_action( 'woocommerce_after_single_product_summary', 'twstudio_single_product_wrapper_after', 5 );
Add Taxonomies for media gallery

6. May 2018

Goes into functions.php

//adds categorys
function wptp_add_categories_to_attachments() {
	register_taxonomy_for_object_type( 'category', 'attachment' );
}
add_action( 'init' , 'wptp_add_categories_to_attachments' );

//adds tags
function wptp_add_tags_to_attachments() {
	register_taxonomy_for_object_type( 'post_tag', 'attachment' );
}
add_action( 'init' , 'wptp_add_tags_to_attachments' );

// register new taxonomy which applies to attachments
function wptp_add_location_taxonomy() {
	$labels = array(
		'name'              => 'Locations',
		'singular_name'     => 'Location',
		'search_items'      => 'Search Locations',
		'all_items'         => 'All Locations',
		'parent_item'       => 'Parent Location',
		'parent_item_colon' => 'Parent Location:',
		'edit_item'         => 'Edit Location',
		'update_item'       => 'Update Location',
		'add_new_item'      => 'Add New Location',
		'new_item_name'     => 'New Location Name',
		'menu_name'         => 'Location',
	);

	$args = array(
		'labels' => $labels,
		'hierarchical' => true,
		'query_var' => 'true',
		'rewrite' => 'true',
		'show_admin_column' => 'true',
	);

	register_taxonomy( 'location', 'attachment', $args );
}
add_action( 'init', 'wptp_add_location_taxonomy' );
Register a custom post type

21. April 2018

This goes into functions.php

function myplugin_register_book_post_type() {
    $args = array(
        'public' => true,
        'label'  => 'Books',
        'show_in_rest' => true,
        'template' => array(
            array( 'core/image', array(
                'align' => 'left',
            ) ),
            array( 'core/heading', array(
                'placeholder' => 'Add Author...',
            ) ),
            array( 'core/paragraph', array(
                'placeholder' => 'Add Description...',
            ) ),
        ),
    );
    register_post_type( 'book', $args );
}
add_action( 'init', 'myplugin_register_book_post_type' );
WP-CLI nice to know

20. April 2018

Inside your www folder

wp plugin list
wp plugin deactivate xxxxxxx

wp user list
wp user create Thomas thomas@example.mail --role=administrator

wp option
wp option get xxxx-wc-chkout-cnfg-_class_billing_postcode (get the value from db)
wp option update xxxx-wc-chkout-cnfg-_class_billing_postcode VERDI (change to value of choice)

wp cache flush (Cache flush)

wp db export (Backup)

----
Backup the database to a specific file:
wp db export ../my_wordpress_db.sqlUsing this command will backup the database to a file called “my_wordpress_db.sql” and will put it in the folder above the current one (or `../`). This is done as a security measure to ensure no one can download your database. ---- wp search-replace 'http://www.domain.no' 'https://www.domain.no' //nice to use after change to https (https://wordpress.org/plugins/really-simple-ssl/ is nice to install and activate after search and replace)
Edit text in WooCommerce Message Error

20. April 2018

add_filter( 'woocommerce_add_error', 'twstudio_change_terms_popup_text' );
function twstudio_change_terms_popup_text( $error ) {
    if( 'You must accept our Terms &amp; Conditions.' == $error ) {
        $error = 'Please accept our terms and conditions to proceed.';
    }
    return $error;
}
Search fix. Hide hidden products when searching.

20. April 2018

add_action( 'pre_get_posts', 'search_query_fix' );
function search_query_fix( $query = false ) {
    if(!is_admin() && is_search()){
        $query->set( 'tax_query', array(
            array(
                'taxonomy' => 'product_visibility',
                'field'    => 'name',
                'terms'    => 'exclude-from-search',
                'operator' => 'NOT IN',
            )
        ));
    }
}
Hide/show password protected posts on specific pages

18. April 2018

This goes into functions.php

function exclude_protected($where) {
global $wpdb;
return $where .= " AND {$wpdb-&gt;posts}.post_password = '' ";
}

// Decide where to display them
function exclude_protected_action($query) {
if( !is_single() &amp;&amp; !is_archive() &amp;&amp; !is_admin() ) {
add_filter( 'posts_where', 'exclude_protected' );
}
}

// Action to queue the filter at the right time
add_action('pre_get_posts', 'exclude_protected_action');