PageRenderTime 48ms CodeModel.GetById 13ms RepoModel.GetById 0ms app.codeStats 0ms

/wp-content/plugins/woocommerce/includes/data-stores/class-wc-shipping-zone-data-store.php

https://gitlab.com/campus-academy/krowkaramel
PHP | 373 lines | 196 code | 48 blank | 129 comment | 15 complexity | 25c026ceffbdceed1c2fa155edfcf3f4 MD5 | raw file
  1. <?php
  2. /**
  3. * Class WC_Shipping_Zone_Data_Store file.
  4. *
  5. * @package WooCommerce\DataStores
  6. */
  7. if ( ! defined( 'ABSPATH' ) ) {
  8. exit;
  9. }
  10. /**
  11. * WC Shipping Zone Data Store.
  12. *
  13. * @version 3.0.0
  14. */
  15. class WC_Shipping_Zone_Data_Store extends WC_Data_Store_WP implements WC_Shipping_Zone_Data_Store_Interface, WC_Object_Data_Store_Interface {
  16. /**
  17. * Method to create a new shipping zone.
  18. *
  19. * @since 3.0.0
  20. * @param WC_Shipping_Zone $zone Shipping zone object.
  21. */
  22. public function create( &$zone ) {
  23. global $wpdb;
  24. $wpdb->insert(
  25. $wpdb->prefix . 'woocommerce_shipping_zones',
  26. array(
  27. 'zone_name' => $zone->get_zone_name(),
  28. 'zone_order' => $zone->get_zone_order(),
  29. )
  30. );
  31. $zone->set_id( $wpdb->insert_id );
  32. $zone->save_meta_data();
  33. $this->save_locations( $zone );
  34. $zone->apply_changes();
  35. WC_Cache_Helper::invalidate_cache_group( 'shipping_zones' );
  36. WC_Cache_Helper::get_transient_version( 'shipping', true );
  37. }
  38. /**
  39. * Update zone in the database.
  40. *
  41. * @since 3.0.0
  42. * @param WC_Shipping_Zone $zone Shipping zone object.
  43. */
  44. public function update( &$zone ) {
  45. global $wpdb;
  46. if ( $zone->get_id() ) {
  47. $wpdb->update(
  48. $wpdb->prefix . 'woocommerce_shipping_zones',
  49. array(
  50. 'zone_name' => $zone->get_zone_name(),
  51. 'zone_order' => $zone->get_zone_order(),
  52. ),
  53. array( 'zone_id' => $zone->get_id() )
  54. );
  55. }
  56. $zone->save_meta_data();
  57. $this->save_locations( $zone );
  58. $zone->apply_changes();
  59. WC_Cache_Helper::invalidate_cache_group( 'shipping_zones' );
  60. WC_Cache_Helper::get_transient_version( 'shipping', true );
  61. }
  62. /**
  63. * Method to read a shipping zone from the database.
  64. *
  65. * @since 3.0.0
  66. * @param WC_Shipping_Zone $zone Shipping zone object.
  67. * @throws Exception If invalid data store.
  68. */
  69. public function read( &$zone ) {
  70. global $wpdb;
  71. // Zone 0 is used as a default if no other zones fit.
  72. if ( 0 === $zone->get_id() || '0' === $zone->get_id() ) {
  73. $this->read_zone_locations( $zone );
  74. $zone->set_zone_name( __( 'Locations not covered by your other zones', 'woocommerce' ) );
  75. $zone->read_meta_data();
  76. $zone->set_object_read( true );
  77. /**
  78. * Indicate that the WooCommerce shipping zone has been loaded.
  79. *
  80. * @param WC_Shipping_Zone $zone The shipping zone that has been loaded.
  81. */
  82. do_action( 'woocommerce_shipping_zone_loaded', $zone );
  83. return;
  84. }
  85. $zone_data = $wpdb->get_row(
  86. $wpdb->prepare(
  87. "SELECT zone_name, zone_order FROM {$wpdb->prefix}woocommerce_shipping_zones WHERE zone_id = %d LIMIT 1",
  88. $zone->get_id()
  89. )
  90. );
  91. if ( ! $zone_data ) {
  92. throw new Exception( __( 'Invalid data store.', 'woocommerce' ) );
  93. }
  94. $zone->set_zone_name( $zone_data->zone_name );
  95. $zone->set_zone_order( $zone_data->zone_order );
  96. $this->read_zone_locations( $zone );
  97. $zone->read_meta_data();
  98. $zone->set_object_read( true );
  99. /** This action is documented in includes/datastores/class-wc-shipping-zone-data-store.php. */
  100. do_action( 'woocommerce_shipping_zone_loaded', $zone );
  101. }
  102. /**
  103. * Deletes a shipping zone from the database.
  104. *
  105. * @since 3.0.0
  106. * @param WC_Shipping_Zone $zone Shipping zone object.
  107. * @param array $args Array of args to pass to the delete method.
  108. * @return void
  109. */
  110. public function delete( &$zone, $args = array() ) {
  111. $zone_id = $zone->get_id();
  112. if ( $zone_id ) {
  113. global $wpdb;
  114. // Delete methods and their settings.
  115. $methods = $this->get_methods( $zone_id, false );
  116. if ( $methods ) {
  117. foreach ( $methods as $method ) {
  118. $this->delete_method( $method->instance_id );
  119. }
  120. }
  121. // Delete zone.
  122. $wpdb->delete( $wpdb->prefix . 'woocommerce_shipping_zone_locations', array( 'zone_id' => $zone_id ) );
  123. $wpdb->delete( $wpdb->prefix . 'woocommerce_shipping_zones', array( 'zone_id' => $zone_id ) );
  124. $zone->set_id( null );
  125. WC_Cache_Helper::invalidate_cache_group( 'shipping_zones' );
  126. WC_Cache_Helper::get_transient_version( 'shipping', true );
  127. do_action( 'woocommerce_delete_shipping_zone', $zone_id );
  128. }
  129. }
  130. /**
  131. * Get a list of shipping methods for a specific zone.
  132. *
  133. * @since 3.0.0
  134. * @param int $zone_id Zone ID.
  135. * @param bool $enabled_only True to request enabled methods only.
  136. * @return array Array of objects containing method_id, method_order, instance_id, is_enabled
  137. */
  138. public function get_methods( $zone_id, $enabled_only ) {
  139. global $wpdb;
  140. if ( $enabled_only ) {
  141. $raw_methods_sql = "SELECT method_id, method_order, instance_id, is_enabled FROM {$wpdb->prefix}woocommerce_shipping_zone_methods WHERE zone_id = %d AND is_enabled = 1";
  142. } else {
  143. $raw_methods_sql = "SELECT method_id, method_order, instance_id, is_enabled FROM {$wpdb->prefix}woocommerce_shipping_zone_methods WHERE zone_id = %d";
  144. }
  145. return $wpdb->get_results( $wpdb->prepare( $raw_methods_sql, $zone_id ) ); // phpcs:ignore WordPress.DB.PreparedSQL.NotPrepared
  146. }
  147. /**
  148. * Get count of methods for a zone.
  149. *
  150. * @since 3.0.0
  151. * @param int $zone_id Zone ID.
  152. * @return int Method Count
  153. */
  154. public function get_method_count( $zone_id ) {
  155. global $wpdb;
  156. return $wpdb->get_var( $wpdb->prepare( "SELECT COUNT(*) FROM {$wpdb->prefix}woocommerce_shipping_zone_methods WHERE zone_id = %d", $zone_id ) );
  157. }
  158. /**
  159. * Add a shipping method to a zone.
  160. *
  161. * @since 3.0.0
  162. * @param int $zone_id Zone ID.
  163. * @param string $type Method Type/ID.
  164. * @param int $order Method Order.
  165. * @return int Instance ID
  166. */
  167. public function add_method( $zone_id, $type, $order ) {
  168. global $wpdb;
  169. $wpdb->insert(
  170. $wpdb->prefix . 'woocommerce_shipping_zone_methods',
  171. array(
  172. 'method_id' => $type,
  173. 'zone_id' => $zone_id,
  174. 'method_order' => $order,
  175. ),
  176. array(
  177. '%s',
  178. '%d',
  179. '%d',
  180. )
  181. );
  182. return $wpdb->insert_id;
  183. }
  184. /**
  185. * Delete a method instance.
  186. *
  187. * @since 3.0.0
  188. * @param int $instance_id Instance ID.
  189. */
  190. public function delete_method( $instance_id ) {
  191. global $wpdb;
  192. $method = $this->get_method( $instance_id );
  193. if ( ! $method ) {
  194. return;
  195. }
  196. delete_option( 'woocommerce_' . $method->method_id . '_' . $instance_id . '_settings' );
  197. $wpdb->delete( $wpdb->prefix . 'woocommerce_shipping_zone_methods', array( 'instance_id' => $instance_id ) );
  198. do_action( 'woocommerce_delete_shipping_zone_method', $instance_id );
  199. }
  200. /**
  201. * Get a shipping zone method instance.
  202. *
  203. * @since 3.0.0
  204. * @param int $instance_id Instance ID.
  205. * @return object
  206. */
  207. public function get_method( $instance_id ) {
  208. global $wpdb;
  209. return $wpdb->get_row( $wpdb->prepare( "SELECT zone_id, method_id, instance_id, method_order, is_enabled FROM {$wpdb->prefix}woocommerce_shipping_zone_methods WHERE instance_id = %d LIMIT 1;", $instance_id ) );
  210. }
  211. /**
  212. * Find a matching zone ID for a given package.
  213. *
  214. * @since 3.0.0
  215. * @param object $package Package information.
  216. * @return int
  217. */
  218. public function get_zone_id_from_package( $package ) {
  219. global $wpdb;
  220. $country = strtoupper( wc_clean( $package['destination']['country'] ) );
  221. $state = strtoupper( wc_clean( $package['destination']['state'] ) );
  222. $continent = strtoupper( wc_clean( WC()->countries->get_continent_code_for_country( $country ) ) );
  223. $postcode = wc_normalize_postcode( wc_clean( $package['destination']['postcode'] ) );
  224. // Work out criteria for our zone search.
  225. $criteria = array();
  226. $criteria[] = $wpdb->prepare( "( ( location_type = 'country' AND location_code = %s )", $country );
  227. $criteria[] = $wpdb->prepare( "OR ( location_type = 'state' AND location_code = %s )", $country . ':' . $state );
  228. $criteria[] = $wpdb->prepare( "OR ( location_type = 'continent' AND location_code = %s )", $continent );
  229. $criteria[] = 'OR ( location_type IS NULL ) )';
  230. // Postcode range and wildcard matching.
  231. $postcode_locations = $wpdb->get_results( "SELECT zone_id, location_code FROM {$wpdb->prefix}woocommerce_shipping_zone_locations WHERE location_type = 'postcode';" );
  232. if ( $postcode_locations ) {
  233. $zone_ids_with_postcode_rules = array_map( 'absint', wp_list_pluck( $postcode_locations, 'zone_id' ) );
  234. $matches = wc_postcode_location_matcher( $postcode, $postcode_locations, 'zone_id', 'location_code', $country );
  235. $do_not_match = array_unique( array_diff( $zone_ids_with_postcode_rules, array_keys( $matches ) ) );
  236. if ( ! empty( $do_not_match ) ) {
  237. $criteria[] = 'AND zones.zone_id NOT IN (' . implode( ',', $do_not_match ) . ')';
  238. }
  239. }
  240. /**
  241. * Get shipping zone criteria
  242. *
  243. * @since 3.6.6
  244. * @param array $criteria Get zone criteria.
  245. * @param array $package Package information.
  246. * @param array $postcode_locations Postcode range and wildcard matching.
  247. */
  248. $criteria = apply_filters( 'woocommerce_get_zone_criteria', $criteria, $package, $postcode_locations );
  249. // Get matching zones.
  250. return $wpdb->get_var(
  251. "SELECT zones.zone_id FROM {$wpdb->prefix}woocommerce_shipping_zones as zones
  252. LEFT OUTER JOIN {$wpdb->prefix}woocommerce_shipping_zone_locations as locations ON zones.zone_id = locations.zone_id AND location_type != 'postcode'
  253. WHERE " . implode( ' ', $criteria ) // phpcs:ignore WordPress.DB.PreparedSQL.NotPrepared
  254. . ' ORDER BY zone_order ASC, zones.zone_id ASC LIMIT 1'
  255. );
  256. }
  257. /**
  258. * Return an ordered list of zones.
  259. *
  260. * @since 3.0.0
  261. * @return array An array of objects containing a zone_id, zone_name, and zone_order.
  262. */
  263. public function get_zones() {
  264. global $wpdb;
  265. return $wpdb->get_results( "SELECT zone_id, zone_name, zone_order FROM {$wpdb->prefix}woocommerce_shipping_zones order by zone_order ASC, zone_id ASC;" );
  266. }
  267. /**
  268. * Return a zone ID from an instance ID.
  269. *
  270. * @since 3.0.0
  271. * @param int $id Instnace ID.
  272. * @return int
  273. */
  274. public function get_zone_id_by_instance_id( $id ) {
  275. global $wpdb;
  276. return $wpdb->get_var( $wpdb->prepare( "SELECT zone_id FROM {$wpdb->prefix}woocommerce_shipping_zone_methods as methods WHERE methods.instance_id = %d LIMIT 1;", $id ) );
  277. }
  278. /**
  279. * Read location data from the database.
  280. *
  281. * @param WC_Shipping_Zone $zone Shipping zone object.
  282. */
  283. private function read_zone_locations( &$zone ) {
  284. global $wpdb;
  285. $locations = $wpdb->get_results(
  286. $wpdb->prepare(
  287. "SELECT location_code, location_type FROM {$wpdb->prefix}woocommerce_shipping_zone_locations WHERE zone_id = %d",
  288. $zone->get_id()
  289. )
  290. );
  291. if ( $locations ) {
  292. foreach ( $locations as $location ) {
  293. $zone->add_location( $location->location_code, $location->location_type );
  294. }
  295. }
  296. }
  297. /**
  298. * Save locations to the DB.
  299. * This function clears old locations, then re-inserts new if any changes are found.
  300. *
  301. * @since 3.0.0
  302. *
  303. * @param WC_Shipping_Zone $zone Shipping zone object.
  304. *
  305. * @return bool|void
  306. */
  307. private function save_locations( &$zone ) {
  308. $changed_props = array_keys( $zone->get_changes() );
  309. if ( ! in_array( 'zone_locations', $changed_props, true ) ) {
  310. return false;
  311. }
  312. global $wpdb;
  313. $wpdb->delete( $wpdb->prefix . 'woocommerce_shipping_zone_locations', array( 'zone_id' => $zone->get_id() ) );
  314. foreach ( $zone->get_zone_locations( 'edit' ) as $location ) {
  315. $wpdb->insert(
  316. $wpdb->prefix . 'woocommerce_shipping_zone_locations',
  317. array(
  318. 'zone_id' => $zone->get_id(),
  319. 'location_code' => $location->code,
  320. 'location_type' => $location->type,
  321. )
  322. );
  323. }
  324. }
  325. }