Categories
WooCommerce Extensions

Cities Shipping Zones for WooCommerce

Cities List

How to modify cities names?
Update countries codes, and cities codes and names:

add_filter( 'woocommerce_states', 'csz_modify_woocommerce_states', 40 );
function csz_modify_woocommerce_states( $states ) {
	$states['AT']['AT90001'] = 'Vienna';
	return $states;
}

How to remove some cities from the list?
Update cities codes:

add_filter( 'woocommerce_states', 'csz_remove_woocommerce_states', 50 );
function csz_remove_woocommerce_states( $states ) {
	$unnecessary_cities = [ 'AT10101', 'AT10201', 'AT10301' ];
	foreach ( $unnecessary_cities as $city ) {
		unset( $states[ substr( $city, 0, 2 ) ][ $city ] );
	}
	return $states;
}

How to keep only specific cities in the list?
Update country code and cities codes:

add_filter( 'woocommerce_states', 'csz_set_woocommerce_states', 20 );
function csz_set_woocommerce_states( $states ) {
	$country = 'AT';
	$cities = [ 'AT10101', 'AT10201', 'AT10301' ];
	$new_states = [];
	foreach ( $cities as $city ) {
		if ( isset( $states[ $country ][ $city ] ) ) {
			$new_states[ $city ] = $states[ $country ][ $city ];
		}
	}
	$states[ $country ] = $new_states;
	return $states;
}

How to remove from the list all the cities of certain states?
Update states codes:

add_filter( 'csz_country_states', 'csz_remove_states_cities' );
function csz_remove_states_cities( $states ) {
	$unnecessary_states = [ 'EE001', 'EE004', 'EE006' ];
	foreach ( $unnecessary_states as $state_code ) {
		if ( isset( $states[ $state_code ] ) ) {
			unset( $states[ $state_code ] );
		}
	}
	return $states;
}

How to keep in the list only cities of certain states?
Update country code and states codes:

add_filter( 'csz_country_states', 'csz_keep_states_cities' );
function csz_keep_states_cities( $states ) {
	$country_code = 'EE';
	$keep_states = [ 'EE001', 'EE004', 'EE006' ];
	if ( substr( array_keys( $states )['0'], 0, 2 ) === $country_code ) {
		foreach ( $states as $state_code => $state_name ) {
			if ( ! in_array( $state_code, $keep_states ) ) {
				unset( $states[ $state_code ] );
			}
		}
	}
	return $states;
}

How to create shipping zones for quarters inside a city?
Create shipping zone with that city and restrict to the relevant postcodes, or (what is less recommended) split the city into areas (update city code and areas names, if the store is located inside this city update the store location in WooCommerce settings):

add_filter( 'woocommerce_states', 'csz_split_woocommerce_states', 30 );
function csz_split_woocommerce_states( $states ) {
	$city_code = 'AT90001';
	$sub_cities = [ __( 'Northern', 'woocommerce' ), __( 'Southern', 'woocommerce' ) ];
	$count = 101;
	foreach ( $sub_cities as $sub_city ) {
		$states[ substr( $city_code, 0, 2 ) ][ $city_code . $count ] = $states[ substr( $city_code, 0, 2 ) ][ $city_code ] . ' - ' . $sub_city;
		$count++;
	}
	unset( $states[ substr( $city_code, 0, 2 ) ][ $city_code ] );
	return $states;
}

Which uses shop owners make with the customer city?

  • Set shipping rates per cities
  • Sales stats by city (Dashbaord => WooCommerce => Reports => Sales by city)
  • Displaying certain products by city (filter by city category)
  • Selling certain products per city (plugin that limits by state)
  • Shipping certain products per city (associating the products to a class without price in the relevant shipping method)
  • Applying taxes per city (using the city code in the state field in the settings)
  • Enabling payment / shipping methods per city (conditional payment / shipping plugin)
  • Displaying the cities in external checkout page (retreiving the states via WooCommerce REST API)
Bulk Edit Tool

What is the required format?
Semicolon (;) between each city. For example: Wien; Rust; Steinbrunn

How to modify cities in list to the required format?
Replace [\r\n]+ (regex) with ; in Notepad++.

How to enter all the locations within certain distance from a city with distances list?
Enter exclamation mark (!) followed by the city code, if necessary add minium and maximum distance seperated by semicolon (;).

Integrations

Why the city appear twice in my integrated software?
You will have to remove the sending of the state field via its plugin’s code.

Why the city field is empty in my integrated software?
You will have to modify its way of retreiving data from the order- from: $_POST['billing_city'] into $order->get_billing_city() or into $_POST['billing_state'] if $order was not created yet. Or add action that copies $_POST['billing_state'] into $_POST['billing_city']. Do the same for the shipping field.

Distance Fee

How to apply distance fee?
Given a (domestic) city’s distances list, it will be possible to add distance based fee for the shipping rate or product price (for example- to sell moving services).

Why the tax is not calculated on the distance fee?
Enter in the shipping method cost greater than zero.

Where the configured product distance fee will be displayed?
The product the fee will be added to its price and will be displayed in the subtotal of the mini cart widget.

How I shall organize the distances list for some city?
Use as index the locations codes or names (as they appear in the dashboard and update $key_format), verify to set distance to the city itself, the distances should be greater than 0.

WooCommerce REST API

Use the class:

add_filter( 'woocommerce_rest_api_get_rest_namespaces', 'wc_states_api' );
function wc_states_api( $controllers ) {
	$controllers['wc/v3']['data-states'] = 'WC_REST_Data_States_Controller';
	return $controllers;
}

class WC_REST_Data_States_Controller extends WC_REST_Data_Controller {
	protected $namespace = 'wc/v3';
	protected $rest_base = 'data/states';
	function register_routes() {
		register_rest_route( $this->namespace, '/' . $this->rest_base . '/(?P<state>[\w-]+)/zone', [
			'methods'		=> 'GET',
			'callback'		=> [ $this, 'get_zone' ],
			'args'			=> [ 'state' => [ 'description' => __( 'State / County', 'woocommerce' ), 'type' => 'string' ] ],
			'permission_callback'	=> [ $this, 'get_items_permissions_check' ],
		] );
		register_rest_route( $this->namespace, '/' . $this->rest_base . '/(?P<state>[\w-]+)/state', [
			'methods'		=> 'GET',
			'callback'		=> [ $this, 'get_state' ],
			'args'			=> [ 'state' => [ 'description' => __( 'State / County', 'woocommerce' ), 'type' => 'string' ] ],
			'permission_callback'	=> [ $this, 'get_items_permissions_check' ],
		] );
	}
	function get_zone( $data ) {
		return [ 'id' => wc_get_shipping_zone( [ 'destination' => [ 'country' => substr( $data['state'], 0, 2 ), 'state' => $data['state'], 'postcode' => '' ] ] )->get_zone_id() ];
	}
	function get_state( $data ) {
		foreach ( get_option( 'wc_csz_countries_codes' ) as $country_code ) {
			$country_cities = '';
			$country_states = '';
			include( WP_PLUGIN_DIR . '/cities-shipping-zones-for-woocommerce/i18n/cities/' . $country_code . '.php' );
			if ( isset( $country_states ) ) {
				foreach ( $country_states as $state_code => $state_name ) {
					if ( isset( $country_cities[ $state_code ][ $data['state'] ] ) ) {
						return $country_states[ $state_code ];
					}
				}
			}
		}
		return false;
	}
}

How to retrieve the shipping zone a city belong to?

/wp-json/wc/v3/data/states/<city_code>/zone

How to retrieve the state name a city belong to?

/wp-json/wc/v3/data/states/<city_code>/state
Uninstall Plugin / Countries / Locations
  • WooCommerce Shipping Zones settings: Remove the locations
  • Plugin Settings: Remove the countries
  • WooCommerce Settings: Update the store location
  • Plugins: Deactivate and delete the plugin
  • Database: Consider to convert/erase the state field values of orders and users that were created/updated while the plugin was applied on the countries they belong to
Categories
WooCommerce Extensions

User Posts Limit

How to make some user unrestricted in rules that applied on certain post type?
Update the user id and the post type:

add_filter( 'upl_query', 'upl_unrestrict_user' );
function upl_unrestrict_user( $args ) {
	$post_type = 'post';
	$user_id = 12;
	if ( $post_type === $args['post_type'] && $user_id === $args['author'] ) {
		$args['post_type'] = 'none';
	}
	return $args;
}

How to make rules that applied on certain post type to limit the total posts in the website?
Update the post type:

add_filter( 'upl_query', 'upl_limit_total_posts' );
function upl_limit_total_posts( $args ) {
	$post_type = 'post';
	if ( $post_type === $args['post_type'] ) {
		$args['author'] = '';
	}
	return $args;
}

How to make rules that applied on certain post type to limit by posts in specific category only?
Update the post type and the category id (make sure users can’t modify posts category):

add_filter( 'upl_query', 'upl_specific_category' );
function upl_specific_category( $args ) {
	$post_type = 'post';
	$category_id = 4;
	if ( $post_type === $args['post_type'] ) {
		$args['cat'] = $category_id;
	}
	return $args;
}

How to make rules that applied on certain post type to limit specific post status?
Update the post type and the post status (make sure users can’t modify post status):

add_filter( 'upl_query', 'upl_specific_post_status' );
function upl_specific_post_status( $args ) {
	$post_type = 'post';
	$post_status = [ 'any' ];
	if ( $post_type === $args['post_type'] ) {
		$args['post_status'] = $post_status;
	}
	return $args;
}

How to modify the cycle for rules that applied on certain post type?
Update the post type and the cycle (keep in mind that the change will not take affect in places that the date is displayed):

add_filter( 'upl_query', 'upl_modify_cycle' );
function upl_modify_cycle( $args ) {
	$post_type = 'post';
	$cycle = '3 days ago';
	if ( $post_type === $args['post_type'] ) {
		$args['date_query']['after'] = $cycle;
	}
	return $args;
}

How to send users an Email to encourage them to upgrade their membership after they try to post after posts limit exceeded?
Attach your code for sending Email to the upl_limit_applied action hook.

How to define different message types for each user?
Use the upl_message and upl_notice filters.

Categories
WooCommerce Extensions

Advanced Options for WooCommerce

Categories
WooCommerce Extensions

Default Attributes for WooCommerce

How to exclude some attribute from the stock-based default attributes calculation?
Update the attribute id:

add_filter( 'daw_max_variations', 'exclude_attribute', 10, 2 );
function exclude_attribute( $max_variations, $attribute ) {
	$excluded_attribute = 25;
	if ( $excluded_attribute === $attribute['id'] ) {
		return 0;
	}
	return $max_variations;
}

How to apply the first attribute option only on products with less than certain amount of attributes?
Update the amount of attributes:

add_filter( 'first_attribute_checkbox', 'daw_first_attribute_restrict_products', 10, 2 );
function daw_first_attribute_restrict_products( $first_attribute_checkbox, $product ) {
	$max_attributes = 3;
	if ( $max_attributes < count( $product->get_attributes() ) ) {
		return 'no';
	}
	return $first_attribute_checkbox;
}

How to exclude product from all the default attributes calculations?
Update the product id:

add_filter( 'daw_include_product', 'exclude_product', 10, 2 );
function exclude_product( $included, $product ) {
	$excluded_product = 71;
	if ( $excluded_product === $product->get_id() ) {
		return false;
	}
	return $included;
}