GetPaid_MaxMind_Geolocation::get_geolocation()   A
last analyzed

Complexity

Conditions 3
Paths 2

Size

Total Lines 13
Code Lines 8

Duplication

Lines 0
Ratio 0 %

Importance

Changes 0
Metric Value
cc 3
eloc 8
nc 2
nop 2
dl 0
loc 13
rs 10
c 0
b 0
f 0
1
<?php
2
/**
3
 * Maxmind Geolocation class
4
 *
5
 * Handles geolocation and updating the geolocation database.
6
 * This product includes GeoLite data created by MaxMind, available from http://www.maxmind.com.
7
 *
8
 */
9
10
defined( 'ABSPATH' ) || exit;
11
12
/**
13
 * Uses MaxMind for Geolocation
14
 *
15
 * @since 1.0.19
16
 */
17
class GetPaid_MaxMind_Geolocation {
18
19
	/**
20
	 * The service responsible for interacting with the MaxMind database.
21
	 *
22
	 * @var GetPaid_MaxMind_Database_Service
23
	 */
24
	private $database_service;
25
26
	/**
27
	 * Initialize the integration.
28
	 */
29
	public function __construct() {
30
31
		/**
32
		 * Supports overriding the database service to be used.
33
		 *
34
		 * @since 1.0.19
35
		 * @return mixed|null The geolocation database service.
36
		 */
37
		$this->database_service = apply_filters( 'getpaid_maxmind_geolocation_database_service', null );
38
		if ( null === $this->database_service ) {
39
			$this->database_service = new GetPaid_MaxMind_Database_Service( $this->get_database_prefix() );
40
		}
41
42
		// Bind to the scheduled updater action.
43
		add_action( 'getpaid_update_geoip_databases', array( $this, 'update_database' ) );
44
45
		// Bind to the geolocation filter for MaxMind database lookups.
46
		add_filter( 'getpaid_get_geolocation', array( $this, 'get_geolocation' ), 10, 2 );
47
48
		// Handle maxmind key updates.
49
		add_filter( 'wpinv_settings_sanitize_maxmind_license_key', array( $this, 'handle_key_updates' ) );
50
51
	}
52
53
	/**
54
	 * Get database service.
55
	 *
56
	 * @return GetPaid_MaxMind_Database_Service|null
57
	 */
58
	public function get_database_service() {
59
		return $this->database_service;
60
	}
61
62
	/**
63
	 * Checks to make sure that the license key is valid.
64
	 *
65
	 * @param string $license_key The new license key.
66
	 * @return string
67
	 */
68
	public function handle_key_updates( $license_key ) {
69
70
		// Trim whitespaces and strip slashes.
71
		$license_key = trim( $license_key );
72
73
		// Abort if the license key is empty or unchanged.
74
		if ( empty( $license_key ) ) {
75
			return $license_key;
76
		}
77
78
		// Abort if a database exists and the license key is unchaged.
79
		if ( file_exists( $this->database_service->get_database_path() && $license_key == wpinv_get_option( 'maxmind_license_key' ) ) ) {
0 ignored issues
show
Bug introduced by
$this->database_service-...('maxmind_license_key') of type boolean is incompatible with the type string expected by parameter $filename of file_exists(). ( Ignorable by Annotation )

If this is a false-positive, you can also ignore this issue in your code via the ignore-type  annotation

79
		if ( file_exists( /** @scrutinizer ignore-type */ $this->database_service->get_database_path() && $license_key == wpinv_get_option( 'maxmind_license_key' ) ) ) {
Loading history...
80
			return $license_key;
81
		}
82
83
		// Check the license key by attempting to download the Geolocation database.
84
		$tmp_database_path = $this->database_service->download_database( $license_key );
85
		if ( is_wp_error( $tmp_database_path ) ) {
86
			getpaid_admin()->show_error( $tmp_database_path->get_error_message() );
87
			return $license_key;
88
		}
89
90
		$this->update_database( /** @scrutinizer ignore-type */ $tmp_database_path );
91
92
		return $license_key;
93
	}
94
95
	/**
96
	 * Updates the database used for geolocation queries.
97
	 *
98
	 * @param string $tmp_database_path Temporary database path.
99
	 */
100
	public function update_database( $tmp_database_path = null ) {
101
102
		// Allow us to easily interact with the filesystem.
103
		require_once ABSPATH . 'wp-admin/includes/file.php';
104
		WP_Filesystem();
105
		global $wp_filesystem;
106
107
		// Remove any existing archives to comply with the MaxMind TOS.
108
		$target_database_path = $this->database_service->get_database_path();
109
110
		// If there's no database path, we can't store the database.
111
		if ( empty( $target_database_path ) ) {
112
			return;
113
		}
114
115
		if ( $wp_filesystem->exists( $target_database_path ) ) {
116
			$wp_filesystem->delete( $target_database_path );
117
		}
118
119
		// We can't download a database if there's no license key configured.
120
		$license_key = wpinv_get_option( 'maxmind_license_key' );
121
		if ( empty( $license_key ) ) {
122
			return;
123
		}
124
125
		if ( empty( $tmp_database_path ) ) {
126
			$tmp_database_path = $this->database_service->download_database( $license_key );
127
		}
128
129
		if ( is_wp_error( $tmp_database_path ) ) {
130
			wpinv_error_log( $tmp_database_path->get_error_message() );
131
			return;
132
		}
133
134
		// Move the new database into position.
135
		$wp_filesystem->move( $tmp_database_path, $target_database_path, true );
136
		$wp_filesystem->delete( dirname( $tmp_database_path ) );
0 ignored issues
show
Bug introduced by
It seems like $tmp_database_path can also be of type WP_Error; however, parameter $path of dirname() does only seem to accept string, maybe add an additional type check? ( Ignorable by Annotation )

If this is a false-positive, you can also ignore this issue in your code via the ignore-type  annotation

136
		$wp_filesystem->delete( dirname( /** @scrutinizer ignore-type */ $tmp_database_path ) );
Loading history...
137
	}
138
139
	/**
140
	 * Performs a geolocation lookup against the MaxMind database for the given IP address.
141
	 *
142
	 * @param array  $data       Geolocation data.
143
	 * @param string $ip_address The IP address to geolocate.
144
	 * @return array Geolocation including country code, state, city and postcode based on an IP address.
145
	 */
146
	public function get_geolocation( $data, $ip_address ) {
147
148
		if ( ! empty( $data['country'] ) || empty( $ip_address ) ) {
149
			return $data;
150
		}
151
152
		$country_code = $this->database_service->get_iso_country_code_for_ip( $ip_address );
153
154
		return array(
155
			'country'  => $country_code,
156
			'state'    => '',
157
			'city'     => '',
158
			'postcode' => '',
159
		);
160
161
	}
162
163
	/**
164
	 * Fetches the prefix for the MaxMind database file.
165
	 *
166
	 * @return string
167
	 */
168
	private function get_database_prefix() {
169
170
		$prefix = get_option( 'wpinv_maxmind_database_prefix' );
171
172
		if ( empty( $prefix ) ) {
173
			$prefix = md5( uniqid( 'wpinv' ) );
174
			update_option( 'wpinv_maxmind_database_prefix', $prefix );
175
		}
176
177
		return $prefix;
178
	}
179
180
}
181