Нема описа

class-wc-integration-maxmind-database-service.php 4.9KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173
  1. <?php
  2. /**
  3. * The database service class file.
  4. *
  5. * @version 3.9.0
  6. * @package WooCommerce\Integrations
  7. */
  8. defined( 'ABSPATH' ) || exit;
  9. /**
  10. * The service class responsible for interacting with MaxMind databases.
  11. *
  12. * @since 3.9.0
  13. */
  14. class WC_Integration_MaxMind_Database_Service {
  15. /**
  16. * The name of the MaxMind database to utilize.
  17. */
  18. const DATABASE = 'GeoLite2-Country';
  19. /**
  20. * The extension for the MaxMind database.
  21. */
  22. const DATABASE_EXTENSION = '.mmdb';
  23. /**
  24. * A prefix for the MaxMind database filename.
  25. *
  26. * @var string
  27. */
  28. private $database_prefix;
  29. /**
  30. * WC_Integration_MaxMind_Database_Service constructor.
  31. *
  32. * @param string|null $database_prefix A prefix for the MaxMind database filename.
  33. */
  34. public function __construct( $database_prefix ) {
  35. $this->database_prefix = $database_prefix;
  36. }
  37. /**
  38. * Fetches the path that the database should be stored.
  39. *
  40. * @return string The local database path.
  41. */
  42. public function get_database_path() {
  43. $uploads_dir = wp_upload_dir();
  44. $database_path = trailingslashit( $uploads_dir['basedir'] ) . 'woocommerce_uploads/';
  45. if ( ! empty( $this->database_prefix ) ) {
  46. $database_path .= $this->database_prefix . '-';
  47. }
  48. $database_path .= self::DATABASE . self::DATABASE_EXTENSION;
  49. /**
  50. * Filter the geolocation database storage path.
  51. *
  52. * @param string $database_path The path to the database.
  53. * @param int $version Deprecated since 3.4.0.
  54. * @deprecated 3.9.0
  55. */
  56. $database_path = apply_filters_deprecated(
  57. 'woocommerce_geolocation_local_database_path',
  58. array( $database_path, 2 ),
  59. '3.9.0',
  60. 'woocommerce_maxmind_geolocation_database_path'
  61. );
  62. /**
  63. * Filter the geolocation database storage path.
  64. *
  65. * @since 3.9.0
  66. * @param string $database_path The path to the database.
  67. */
  68. return apply_filters( 'woocommerce_maxmind_geolocation_database_path', $database_path );
  69. }
  70. /**
  71. * Fetches the database from the MaxMind service.
  72. *
  73. * @param string $license_key The license key to be used when downloading the database.
  74. * @return string|WP_Error The path to the database file or an error if invalid.
  75. */
  76. public function download_database( $license_key ) {
  77. $download_uri = add_query_arg(
  78. array(
  79. 'edition_id' => self::DATABASE,
  80. 'license_key' => urlencode( wc_clean( $license_key ) ),
  81. 'suffix' => 'tar.gz',
  82. ),
  83. 'https://download.maxmind.com/app/geoip_download'
  84. );
  85. // Needed for the download_url call right below.
  86. require_once ABSPATH . 'wp-admin/includes/file.php';
  87. $tmp_archive_path = download_url( esc_url_raw( $download_uri ) );
  88. if ( is_wp_error( $tmp_archive_path ) ) {
  89. // Transform the error into something more informative.
  90. $error_data = $tmp_archive_path->get_error_data();
  91. if ( isset( $error_data['code'] ) ) {
  92. switch ( $error_data['code'] ) {
  93. case 401:
  94. return new WP_Error(
  95. 'woocommerce_maxmind_geolocation_database_license_key',
  96. __( 'The MaxMind license key is invalid. If you have recently created this key, you may need to wait for it to become active.', 'woocommerce' )
  97. );
  98. }
  99. }
  100. return new WP_Error( 'woocommerce_maxmind_geolocation_database_download', __( 'Failed to download the MaxMind database.', 'woocommerce' ) );
  101. }
  102. // Extract the database from the archive.
  103. try {
  104. $file = new PharData( $tmp_archive_path );
  105. $tmp_database_path = trailingslashit( dirname( $tmp_archive_path ) ) . trailingslashit( $file->current()->getFilename() ) . self::DATABASE . self::DATABASE_EXTENSION;
  106. $file->extractTo(
  107. dirname( $tmp_archive_path ),
  108. trailingslashit( $file->current()->getFilename() ) . self::DATABASE . self::DATABASE_EXTENSION,
  109. true
  110. );
  111. } catch ( Exception $exception ) {
  112. return new WP_Error( 'woocommerce_maxmind_geolocation_database_archive', $exception->getMessage() );
  113. } finally {
  114. // Remove the archive since we only care about a single file in it.
  115. unlink( $tmp_archive_path );
  116. }
  117. return $tmp_database_path;
  118. }
  119. /**
  120. * Fetches the ISO country code associated with an IP address.
  121. *
  122. * @param string $ip_address The IP address to find the country code for.
  123. * @return string The country code for the IP address, or empty if not found.
  124. */
  125. public function get_iso_country_code_for_ip( $ip_address ) {
  126. $country_code = '';
  127. if ( ! class_exists( 'MaxMind\Db\Reader' ) ) {
  128. wc_get_logger()->notice( __( 'Missing MaxMind Reader library!', 'woocommerce' ), array( 'source' => 'maxmind-geolocation' ) );
  129. return $country_code;
  130. }
  131. $database_path = $this->get_database_path();
  132. if ( ! file_exists( $database_path ) ) {
  133. return $country_code;
  134. }
  135. try {
  136. $reader = new MaxMind\Db\Reader( $database_path );
  137. $data = $reader->get( $ip_address );
  138. if ( isset( $data['country']['iso_code'] ) ) {
  139. $country_code = $data['country']['iso_code'];
  140. }
  141. $reader->close();
  142. } catch ( Exception $e ) {
  143. wc_get_logger()->notice( $e->getMessage(), array( 'source' => 'maxmind-geolocation' ) );
  144. }
  145. return $country_code;
  146. }
  147. }