PluginProbe
HurryTimer – An Scarcity and Urgency Countdown Timer for WordPress & WooCommerce / 2.6.2
HurryTimer – An Scarcity and Urgency Countdown Timer for WordPress & WooCommerce v2.6.2
2.15.0 trunk 1.0.0 1.0.1 1.1.0 1.1.1 1.1.2 1.1.3 1.2.0 1.2.1 1.2.2 1.2.3 1.2.4 2.0.0 2.0.1 2.0.2 2.0.3 2.0.4 2.1.2 2.1.3 2.1.5 2.1.6 2.1.7 2.1.8 2.10.0 All 62 releases
hurrytimer / includes / IP_Detection.php

IP_Detection.php in HurryTimer – An Scarcity and Urgency Countdown Timer for WordPress & WooCommerce 2.6.2, at includes/IP_Detection.php

323 lines 7.4 KB
No matching file
Up and down to move Enter to open Esc to close
Raw Download Zip
1 <?php
2
3 namespace Hurrytimer;
4
5 use Exception;
6 use Hurrytimer\Utils\Helpers;
7
8 class IP_Detection
9 {
10 /**
11 * Evergreen IP entries table name.
12 *
13 * @var string
14 */
15 private $table;
16
17 /**
18 * @var int $campaignId
19 */
20 protected $campaignId;
21 /**
22 * Cleanup idle IP entries action name.
23 */
24 const CLEANUP_ACTION = "hurrytimer_evergreen_daily_cleanup";
25
26 public function __construct( $campaignId )
27 {
28 global $wpdb;
29
30 $this->table = "{$wpdb->prefix}hurrytimer_evergreen";
31 $this->campaignId = $campaignId;
32 add_action( self::CLEANUP_ACTION, [ $this, 'cleanup_idle_entries' ] );
33
34 }
35
36
37 /**
38 * Find IP log.
39 *
40 * @return array|null
41 */
42 public function getCurrentUserEndDate()
43 {
44 global $wpdb;
45
46 $ipAddress = $this->fetchCurrentUserIpAddress();
47
48 try {
49 $sql = $wpdb->prepare(
50 "SELECT id, client_expires_at FROM {$this->table}
51 WHERE countdown_id = %d
52 AND client_ip_address = %s",
53 $this->campaignId,
54 $ipAddress
55 );
56
57 /**
58 * @var object{id, client_expires_at} $result
59 */
60 $found = $wpdb->get_row( $sql );
61
62 if ( !$found ) {
63 $found = $this->getCurrentUserEndDateLegacy( $this->campaignId, $ipAddress );
64 }
65 if ( !$found ) {
66 return null;
67 }
68
69 return [ $found->id, $found->client_expires_at ];
70 } catch ( Exception $e ) {
71 return null;
72 }
73 }
74
75 public function fetchCurrentUserIpAddress()
76 {
77 return Helpers::ip_address();
78 }
79
80 public function getCurrentUserResetToken()
81 {
82 global $wpdb;
83
84 $ipAddress = $this->fetchCurrentUserIpAddress();
85
86 try {
87 $sql = $wpdb->prepare(
88 "SELECT id, reset_token FROM {$this->table}
89 WHERE countdown_id = %d
90 AND client_ip_address = %s",
91 $this->campaignId,
92 $ipAddress
93 );
94
95 $found = $wpdb->get_row( $sql );
96 if ( !$found ) {
97 $found = $this->getCurrentUserEndDateLegacy( $this->campaignId, $ipAddress );
98 }
99
100 if ( empty( $found ) || !is_object( $found ) ) {
101 return false;
102 }
103
104 return [ $found->id, $found->reset_token ];
105
106 } catch ( Exception $e ) {
107 return false;
108 }
109 }
110
111
112 /**
113 * This provide compatibility for prior versions.
114 *
115 * @param int $campaignId
116 * @param string $ipAddress
117 *
118 * @return array|null
119 *
120 */
121 private function getCurrentUserEndDateLegacy( $campaignId, $ipAddress )
122 {
123 $_ipAddress = sanitize_key( $ipAddress );
124
125 $transient = sprintf( 'ht_cdt_%d_%s', $campaignId, $_ipAddress );
126
127 $endDateTS = get_transient( $transient );
128
129 if ( !$endDateTS ) {
130 return null;
131 }
132 $created = $this->create( $campaignId, $endDateTS );
133
134 if ( $created ) {
135 // Clear transients.
136 delete_transient( $transient );
137 delete_transient( "{$transient}_status" );
138
139 return $this->getCurrentUserEndDate();
140 }
141
142 return null;
143 }
144
145 /**
146 * Create a new IP log.
147 *
148 * @param int $campaignId
149 * @param int $endDateTS
150 * @return bool
151 */
152 public function create( $campaignId, $endDateTS )
153 {
154 global $wpdb;
155 // Auto-destroy after one month.
156 $destroy_at = Helpers::date_later( MONTH_IN_SECONDS );
157
158 $result = $wpdb->insert(
159 $this->table,
160 [
161 'countdown_id' => $campaignId,
162 'client_ip_address' => $this->fetchCurrentUserIpAddress(),
163 'client_expires_at' => $endDateTS,
164 'destroy_at' => $destroy_at
165 ]
166 );
167
168 if ( $result !== false ) {
169 $this->maybeScheduleDestroy();
170
171 return true;
172 }
173
174 return false;
175 }
176
177 /**
178 *
179 * Update client expiration time.
180 *
181 * @param $id
182 * @param $client_expires_at
183 *
184 * @return false|int
185 */
186 public function update( $id, $client_expires_at )
187 {
188 global $wpdb;
189
190 $destroy_at = Helpers::date_later( MONTH_IN_SECONDS );
191
192 return $wpdb->update(
193 $this->table,
194 compact( 'client_expires_at', 'destroy_at' ),
195 compact( 'id' )
196 );
197 }
198
199 public function updateOrCreate( $id, $endDateTS )
200 {
201 if ( empty( $id ) ) {
202 return $this->create( $this->campaignId, $endDateTS );
203 } else {
204 $this->update( $id, $endDateTS );
205 }
206 }
207
208 public function updateCurrentUserResetToken( $id, $reset_token )
209 {
210 global $wpdb;
211
212 if ( empty( $id ) ) {
213 return false;
214 }
215 return $wpdb->update(
216 $this->table,
217 compact( 'reset_token' ),
218 compact( 'id' )
219 );
220 }
221
222 /**
223 * Delete given countdown and IP entry.
224 *
225 * @param int $campaignId
226 * @param bool $currentUser
227 * @return void
228 */
229 public function forget( $campaignId, $currentUser = false )
230 {
231 global $wpdb;
232 $where = [ 'countdown_id' => $campaignId ];
233 if ( $currentUser ) {
234 $where[ 'client_ip_address' ] = $this->fetchCurrentUserIpAddress();
235 }
236 $wpdb->delete( $this->table, $where );
237
238 // maybe clear scheduled cleanup
239 if ( !$currentUser ) {
240 if ( !$this->hasEntries() ) {
241 $this->clearScheduledDestroy();
242 }
243 }
244
245 }
246
247 function forgetAll( $currentUser = false )
248 {
249 global $wpdb;
250 if ( $currentUser ) {
251 $where[ 'client_ip_address' ] = $this->fetchCurrentUserIpAddress();
252 $wpdb->delete( $this->table, $where );
253 } else {
254 $wpdb->query( "delete from {$this->table}" );
255 }
256 if ( !$this->hasEntries() ) {
257 $this->clearScheduledDestroy();
258 }
259 }
260
261 /**
262 * Clean up IP entries with passed `destroy_at`.
263 *
264 * @return void
265 */
266 private function cleanup_idle_entries()
267 {
268 global $wpdb;
269 $now = current_time( 'mysql' );
270 $sql = "DELETE FROM {$this->table} WHERE destroy_at < $now";
271 $wpdb->query( $sql );
272 }
273
274 /**
275 * Check if there is at least one IP entry.
276 *
277 * @return bool
278 */
279 private function hasEntries()
280 {
281 global $wpdb;
282
283 try {
284 $count = $wpdb->get_var( "SELECT count(*) FROM {$this->table}" );
285
286 if ( is_null( $count ) ) {
287 return false;
288 }
289
290 return $count > 0;
291
292 } catch ( Exception $e ) {
293 return false;
294 }
295 }
296
297 /**
298 * Schedule cleanup of IP entries with passed `destroy_at`.
299 *
300 * @return void
301 */
302 private function maybeScheduleDestroy()
303 {
304 if ( !wp_next_scheduled( self::CLEANUP_ACTION ) ) {
305 wp_schedule_event(
306 current_time( 'timestamp' ),
307 'daily',
308 self::CLEANUP_ACTION
309 );
310 }
311 }
312
313 /**
314 * Clear sheduled destroy event.
315 *
316 * @return void
317 */
318 private function clearScheduledDestroy()
319 {
320 wp_clear_scheduled_hook( self::CLEANUP_ACTION );
321 }
322 }
323