Files
LiveCartaWP/html/wp-content/plugins/contact-form-7-mailchimp-extension/includes/utils/class-cmatic-remote-fetcher.php

252 lines
6.5 KiB
PHP

<?php
/**
* Remote data fetcher with caching.
*
* @package contact-form-7-mailchimp-extension
* @author renzo.johnson@gmail.com
* @copyright 2014-2026 https://renzojohnson.com
* @license GPL-3.0+
*/
defined( 'ABSPATH' ) || exit;
class CMatic_Remote_Fetcher {
private $config;
private $defaults = array(
'url' => '',
'cache_key' => 'cmatic_remote_data',
'cache_duration' => DAY_IN_SECONDS,
'retry_interval' => 600, // 10 minutes in seconds
'max_retries' => 3,
'retry_count_key' => 'cmatic_retry_count',
'cron_hook' => 'cmatic_fetch_retry',
'timeout' => 15,
'fallback_data' => array(),
'parser_callback' => null,
);
public function __construct( $config = array() ) {
$this->config = wp_parse_args( $config, $this->defaults );
add_action( $this->config['cron_hook'], array( $this, 'cron_retry_fetch' ) );
}
public function get_data() {
$cached_data = $this->get_cache();
if ( false !== $cached_data ) {
return $cached_data;
}
$fresh_data = $this->fetch_fresh_data();
if ( false !== $fresh_data ) {
$this->set_cache( $fresh_data );
$this->clear_retry_schedule();
return $fresh_data;
}
$this->schedule_retry();
return $this->get_fallback_data();
}
public function get_cache() {
return get_transient( $this->config['cache_key'] );
}
public function set_cache( $data ) {
return set_transient(
$this->config['cache_key'],
$data,
$this->config['cache_duration']
);
}
public function clear_cache() {
return delete_transient( $this->config['cache_key'] );
}
private function fetch_fresh_data() {
if ( empty( $this->config['url'] ) ) {
return false;
}
$response = wp_remote_get(
$this->config['url'],
array(
'timeout' => $this->config['timeout'],
'user-agent' => 'WordPress/' . get_bloginfo( 'version' ) . '; ' . home_url(),
)
);
if ( is_wp_error( $response ) ) {
return false;
}
$response_code = wp_remote_retrieve_response_code( $response );
if ( 200 !== $response_code ) {
return false;
}
$body = wp_remote_retrieve_body( $response );
if ( empty( $body ) ) {
return false;
}
return $this->parse_content( $body );
}
/** Parse fetched content. */
private function parse_content( $content ) {
if ( is_callable( $this->config['parser_callback'] ) ) {
return call_user_func( $this->config['parser_callback'], $content );
}
$json_data = $this->parse_pricing_json( $content );
if ( false !== $json_data ) {
return $json_data;
}
return $this->parse_pricing_html( $content );
}
private function parse_pricing_json( $content ) {
$json = json_decode( $content, true );
if ( null === $json || ! is_array( $json ) ) {
return false;
}
if ( ! isset( $json['regular_price'] ) || ! isset( $json['discount_percent'] ) ) {
return false;
}
$pricing_data = array(
'regular_price' => (int) $json['regular_price'],
'sale_price' => isset( $json['sale_price'] ) ? (float) $json['sale_price'] : null,
'discount_percent' => (int) $json['discount_percent'],
'coupon_code' => isset( $json['coupon_code'] ) ? sanitize_text_field( $json['coupon_code'] ) : null,
'last_updated' => current_time( 'mysql' ),
);
if ( null === $pricing_data['sale_price'] ) {
$discount_amount = $pricing_data['regular_price'] * ( $pricing_data['discount_percent'] / 100 );
$pricing_data['sale_price'] = $pricing_data['regular_price'] - $discount_amount;
}
if ( null === $pricing_data['coupon_code'] ) {
$pricing_data['coupon_code'] = 'NOW' . $pricing_data['discount_percent'];
}
$pricing_data['formatted'] = sprintf(
'$%d → $%s • Save %d%%',
$pricing_data['regular_price'],
number_format( $pricing_data['sale_price'], 2 ),
$pricing_data['discount_percent']
);
return $pricing_data;
}
private function parse_pricing_html( $html ) {
$pricing_data = array(
'regular_price' => null,
'sale_price' => null,
'discount_percent' => null,
'coupon_code' => null,
'formatted' => null,
'last_updated' => current_time( 'mysql' ),
);
if ( preg_match( '/Single\s+Site[^$]*\$(\d+)\/year/i', $html, $matches ) ) {
$pricing_data['regular_price'] = (int) $matches[1];
}
if ( preg_match( '/(\d+)%\s+Off/i', $html, $matches ) ) {
$pricing_data['discount_percent'] = (int) $matches[1];
}
if ( preg_match( '/coupon\s+code\s+["\']([A-Z0-9]+)["\']/i', $html, $matches ) ) {
$pricing_data['coupon_code'] = sanitize_text_field( $matches[1] );
}
if ( $pricing_data['regular_price'] && $pricing_data['discount_percent'] ) {
$discount_amount = $pricing_data['regular_price'] * ( $pricing_data['discount_percent'] / 100 );
$pricing_data['sale_price'] = $pricing_data['regular_price'] - $discount_amount;
}
if ( $pricing_data['regular_price'] && $pricing_data['sale_price'] && $pricing_data['discount_percent'] ) {
$pricing_data['formatted'] = sprintf(
'$%d → $%s • Save %d%%',
$pricing_data['regular_price'],
number_format( $pricing_data['sale_price'], 2 ),
$pricing_data['discount_percent']
);
}
if ( null === $pricing_data['regular_price'] ) {
return false;
}
return $pricing_data;
}
private function get_fallback_data() {
if ( ! empty( $this->config['fallback_data'] ) ) {
return $this->config['fallback_data'];
}
return array(
'regular_price' => 39,
'sale_price' => 29.25,
'discount_percent' => 25,
'coupon_code' => 'NOW25',
'formatted' => '$39 → $29.25 • Save 25%',
'last_updated' => null,
);
}
private function schedule_retry() {
$retry_count = (int) get_option( $this->config['retry_count_key'], 0 );
if ( $retry_count >= $this->config['max_retries'] ) {
return;
}
update_option( $this->config['retry_count_key'], $retry_count + 1 );
if ( ! wp_next_scheduled( $this->config['cron_hook'] ) ) {
wp_schedule_single_event(
time() + $this->config['retry_interval'],
$this->config['cron_hook']
);
}
}
public function cron_retry_fetch() {
$fresh_data = $this->fetch_fresh_data();
if ( false !== $fresh_data ) {
$this->set_cache( $fresh_data );
$this->clear_retry_schedule();
} else {
$this->schedule_retry();
}
}
private function clear_retry_schedule() {
$timestamp = wp_next_scheduled( $this->config['cron_hook'] );
if ( $timestamp ) {
wp_unschedule_event( $timestamp, $this->config['cron_hook'] );
}
delete_option( $this->config['retry_count_key'] );
}
public function clear_all() {
$this->clear_cache();
$this->clear_retry_schedule();
}
}