Passed
Push — master ( 1ce22f...41fbb9 )
by Brian
09:44 queued 04:28
created

GetPaid_MaxMind_Geolocation   A

Complexity

Total Complexity 19

Size/Duplication

Total Lines 160
Duplicated Lines 0 %

Importance

Changes 1
Bugs 0 Features 0
Metric Value
wmc 19
eloc 50
c 1
b 0
f 0
dl 0
loc 160
rs 10

6 Methods

Rating   Name   Duplication   Size   Complexity  
A update_database() 0 37 6
A handle_key_updates() 0 23 5
A __construct() 0 21 2
A get_geolocation() 0 13 3
A get_database_prefix() 0 10 2
A get_database_service() 0 2 1
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' ) ) ) {
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( $tmp_database_path );
0 ignored issues
show
Bug introduced by
$tmp_database_path of type WP_Error is incompatible with the type string expected by parameter $tmp_database_path of GetPaid_MaxMind_Geolocation::update_database(). ( Ignorable by Annotation )

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

90
		$this->update_database( /** @scrutinizer ignore-type */ $tmp_database_path );
Loading history...
91
92
	}
93
94
	/**
95
	 * Updates the database used for geolocation queries.
96
	 *
97
	 * @param string $tmp_database_path Temporary database path.
98
	 */
99
	public function update_database( $tmp_database_path = null ) {
100
101
		// Allow us to easily interact with the filesystem.
102
		require_once ABSPATH . 'wp-admin/includes/file.php';
103
		WP_Filesystem();
104
		global $wp_filesystem;
105
106
		// Remove any existing archives to comply with the MaxMind TOS.
107
		$target_database_path = $this->database_service->get_database_path();
108
109
		// If there's no database path, we can't store the database.
110
		if ( empty( $target_database_path ) ) {
111
			return;
112
		}
113
114
		if ( $wp_filesystem->exists( $target_database_path ) ) {
115
			$wp_filesystem->delete( $target_database_path );
116
		}
117
118
		// We can't download a database if there's no license key configured.
119
		$license_key = wpinv_get_option( 'maxmind_license_key' );
120
		if ( empty( $license_key ) ) {
121
			return;
122
		}
123
124
		if ( empty( $tmp_database_path ) ) {
125
			$tmp_database_path = $this->database_service->download_database( $license_key );
126
		}
127
128
		if ( is_wp_error( $tmp_database_path ) ) {
129
			wpinv_error_log( $tmp_database_path->get_error_message() );
130
			return;
131
		}
132
133
		// Move the new database into position.
134
		$wp_filesystem->move( $tmp_database_path, $target_database_path, true );
135
		$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

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