405 lines
		
	
	
		
			11 KiB
		
	
	
	
		
			PHP
		
	
	
	
	
	
			
		
		
	
	
			405 lines
		
	
	
		
			11 KiB
		
	
	
	
		
			PHP
		
	
	
	
	
	
<?php
 | 
						|
/**
 | 
						|
 * File: Extension_ImageService_Api.php
 | 
						|
 *
 | 
						|
 * @since 2.2.0
 | 
						|
 *
 | 
						|
 * @package W3TC
 | 
						|
 */
 | 
						|
 | 
						|
namespace W3TC;
 | 
						|
 | 
						|
/**
 | 
						|
 * Class: Extension_ImageService_Api
 | 
						|
 *
 | 
						|
 * @since 2.2.0
 | 
						|
 */
 | 
						|
class Extension_ImageService_Api {
 | 
						|
	/**
 | 
						|
	 * API Base URL.
 | 
						|
	 *
 | 
						|
	 * @since 2.2.0
 | 
						|
	 * @access private
 | 
						|
	 *
 | 
						|
	 * @var string
 | 
						|
	 */
 | 
						|
	private $base_url = 'https://api2.w3-edge.com';
 | 
						|
 | 
						|
	/**
 | 
						|
	 * W3TC Pro license key.
 | 
						|
	 *
 | 
						|
	 * @since 2.2.0
 | 
						|
	 * @access private
 | 
						|
	 *
 | 
						|
	 * @var string
 | 
						|
	 */
 | 
						|
	private $license_key = '0';
 | 
						|
 | 
						|
	/**
 | 
						|
	 * W3TC Pro licensed home URL.
 | 
						|
	 *
 | 
						|
	 * @since 2.2.0
 | 
						|
	 * @access private
 | 
						|
	 *
 | 
						|
	 * @var string
 | 
						|
	 */
 | 
						|
	private $home_url;
 | 
						|
 | 
						|
	/**
 | 
						|
	 * W3TC Pro licensed product item name.
 | 
						|
	 *
 | 
						|
	 * @since 2.2.0
 | 
						|
	 * @access private
 | 
						|
	 *
 | 
						|
	 * @var string
 | 
						|
	 */
 | 
						|
	private $item_name = '0';
 | 
						|
 | 
						|
	/**
 | 
						|
	 * API endpoints.
 | 
						|
	 *
 | 
						|
	 * @since 2.2.0
 | 
						|
	 * @access private
 | 
						|
	 *
 | 
						|
	 * @var array
 | 
						|
	 */
 | 
						|
	private $endpoints = array(
 | 
						|
		'convert'  => array(
 | 
						|
			'method' => 'POST',
 | 
						|
			'uri'    => '/image/convert',
 | 
						|
		),
 | 
						|
		'status'   => array(
 | 
						|
			'method' => 'GET',
 | 
						|
			'uri'    => '/job/status',
 | 
						|
		),
 | 
						|
		'download' => array(
 | 
						|
			'method' => 'GET',
 | 
						|
			'uri'    => '/image/download',
 | 
						|
		),
 | 
						|
		'usage'    => array(
 | 
						|
			'method' => 'GET',
 | 
						|
			'uri'    => '/image/usage',
 | 
						|
		),
 | 
						|
	);
 | 
						|
 | 
						|
	/**
 | 
						|
	 * Constructor.
 | 
						|
	 *
 | 
						|
	 * @since 2.2.0
 | 
						|
	 */
 | 
						|
	public function __construct() {
 | 
						|
		$config = Dispatcher::config();
 | 
						|
 | 
						|
		if ( Util_Environment::is_w3tc_pro( $config ) ) {
 | 
						|
			$this->license_key = $config->get_string( 'plugin.license_key' );
 | 
						|
			$this->home_url    = network_home_url();
 | 
						|
			$this->item_name   = W3TC_PURCHASE_PRODUCT_NAME;
 | 
						|
		} else {
 | 
						|
			$this->home_url = md5( network_home_url() );
 | 
						|
		}
 | 
						|
	}
 | 
						|
 | 
						|
	/**
 | 
						|
	 * Convert an image; submit a job request.
 | 
						|
	 *
 | 
						|
	 * @since 2.2.0
 | 
						|
	 *
 | 
						|
	 * @param string $filepath Image file path.
 | 
						|
	 * @param array  $options  Optional array of options.  Overrides settings.
 | 
						|
	 * @return array
 | 
						|
	 */
 | 
						|
	public function convert( $filepath, array $options = array() ) {
 | 
						|
		// Abort if rate-limit exceeded.
 | 
						|
		$result = get_transient( 'w3tc_imageservice_limited' );
 | 
						|
 | 
						|
		if ( ! empty( $result ) ) {
 | 
						|
			return $result;
 | 
						|
		}
 | 
						|
 | 
						|
		// Prepare request.
 | 
						|
		$config   = Dispatcher::config();
 | 
						|
		$settings = $config->get_array( 'imageservice' );
 | 
						|
		$options  = array_merge(
 | 
						|
			array(
 | 
						|
				'optimize' => 'lossy' === $settings['compression'] ? '1' : '0',
 | 
						|
			),
 | 
						|
			$options
 | 
						|
		);
 | 
						|
		$boundary = wp_generate_password( 24 );
 | 
						|
		$body     = '';
 | 
						|
 | 
						|
		$post_fields = array(
 | 
						|
			'license_key' => $this->license_key,
 | 
						|
			'home_url'    => $this->home_url,
 | 
						|
			'item_name'   => $this->item_name,
 | 
						|
			'optimize'    => $options['optimize'],
 | 
						|
		);
 | 
						|
 | 
						|
		foreach ( $post_fields as $k => $v ) {
 | 
						|
			$body .= '--' . $boundary . "\r\n";
 | 
						|
			$body .= 'Content-Disposition: form-data; name="' . $k . '"' . "\r\n\r\n";
 | 
						|
			$body .= $v . "\r\n";
 | 
						|
		}
 | 
						|
 | 
						|
		$body .= '--' . $boundary . "\r\n";
 | 
						|
		$body .= 'Content-Disposition: form-data; name="image"; filename="' . basename( $filepath ) . '"' . "\r\n\r\n";
 | 
						|
		$body .= file_get_contents( $filepath ) . "\r\n" . '--' . $boundary . '--'; // phpcs:ignore WordPress.WP.AlternativeFunctions
 | 
						|
 | 
						|
		// Send request.
 | 
						|
		$response = wp_remote_request(
 | 
						|
			$this->get_base_url() . $this->endpoints['convert']['uri'],
 | 
						|
			array(
 | 
						|
				'method'    => $this->endpoints['convert']['method'],
 | 
						|
				'sslverify' => false,
 | 
						|
				'timeout'   => 30,
 | 
						|
				'headers'   => array(
 | 
						|
					'Accept'       => 'application/json',
 | 
						|
					'Content-Type' => 'multipart/form-data; boundary=' . $boundary,
 | 
						|
				),
 | 
						|
				'body'      => $body,
 | 
						|
			)
 | 
						|
		);
 | 
						|
 | 
						|
		// Examine response.
 | 
						|
		if ( is_wp_error( $response ) ) {
 | 
						|
			return array(
 | 
						|
				'error' => __( 'WP Error: ', 'w3-total-cache' ) . $response->get_error_message(),
 | 
						|
			);
 | 
						|
		}
 | 
						|
 | 
						|
		// Convert response body to an array.
 | 
						|
		$response_body = json_decode( wp_remote_retrieve_body( $response ), true );
 | 
						|
 | 
						|
		// Update usage.
 | 
						|
		if ( isset( $response_body['usage_hourly'] ) ) {
 | 
						|
			set_transient(
 | 
						|
				'w3tc_imageservice_usage',
 | 
						|
				array(
 | 
						|
					'updated_at'    => time(),
 | 
						|
					'usage_hourly'  => $response_body['usage_hourly'],
 | 
						|
					'usage_monthly' => isset( $response_body['usage_monthly'] ) ? $response_body['usage_monthly'] : null,
 | 
						|
					'limit_hourly'  => isset( $response_body['limit_hourly'] ) ? $response_body['limit_hourly'] : null,
 | 
						|
					'limit_monthly' => isset( $response_body['limit_monthly'] ) ? $response_body['limit_monthly'] : null,
 | 
						|
				),
 | 
						|
				DAY_IN_SECONDS
 | 
						|
			);
 | 
						|
		}
 | 
						|
 | 
						|
		// Handle non-200 response codes.
 | 
						|
		if ( 200 !== $response['response']['code'] ) {
 | 
						|
			$result = array(
 | 
						|
				'code'   => $response['response']['code'],
 | 
						|
				'error'  => esc_html__( 'Error: Received a non-200 response code: ', 'w3-total-cache' ) . $response['response']['code'],
 | 
						|
				'status' => 'error',
 | 
						|
				'time'   => time(),
 | 
						|
			);
 | 
						|
 | 
						|
			if ( isset( $response_body['error']['id'] ) && 'exceeded-hourly' === $response_body['error']['id'] ) {
 | 
						|
				$result['message'] = sprintf(
 | 
						|
					// translators: 1: Hourly request limit.
 | 
						|
					esc_html__( 'You reached your hourly limit of %1$d; try again later%2$s.', 'w3-total-cache' ),
 | 
						|
					esc_attr( $response_body['limit_hourly'] ),
 | 
						|
					isset( $response_body['licensed'] ) && $response_body['licensed'] ? '' :
 | 
						|
						sprintf(
 | 
						|
							// translators: 1: Hourly request limit, 2: HTML anchor open tag, 3: HTML anchor close tag.
 | 
						|
							esc_html__( ' or %1$supgrade to Pro%2$s for higher limits', 'w3-total-cache' ),
 | 
						|
							'<a href="#" class="button-buy-plugin" data-src="imageservice_api_limit">',
 | 
						|
							'</a>'
 | 
						|
						)
 | 
						|
				);
 | 
						|
				set_transient( 'w3tc_imageservice_limited', $result, 5 * MINUTE_IN_SECONDS );
 | 
						|
			} elseif ( isset( $response_body['error']['id'] ) && 'exceeded-monthly' === $response_body['error']['id'] ) {
 | 
						|
				$result['message'] = sprintf(
 | 
						|
					// translators: 1: Monthly request limit, 2: HTML anchor open tag, 3: HTML anchor close tag.
 | 
						|
					esc_html__( 'You reached your monthly limit of %1$d; try again later or %2$supgrade to Pro%3$s for unlimited.', 'w3-total-cache' ),
 | 
						|
					esc_attr( $response_body['limit_monthly'] ),
 | 
						|
					'<a href="#" class="button-buy-plugin" data-src="imageservice_api_limit">',
 | 
						|
					'</a>'
 | 
						|
				);
 | 
						|
				set_transient( 'w3tc_imageservice_limited', $result, DAY_IN_SECONDS );
 | 
						|
			} elseif ( isset( $response_body['error']['id'] ) && 'invalid-output-mime' === $response_body['error']['id'] ) {
 | 
						|
				$result['message'] = esc_html__( 'Invalid output image MIME type.', 'w3-total-cache' );
 | 
						|
			} elseif ( isset( $response_body['error']['id'] ) && 'missing-image' === $response_body['error']['id'] ) {
 | 
						|
				$result['message'] = esc_html__( 'An image file is required.', 'w3-total-cache' );
 | 
						|
			} elseif ( isset( $response_body['error']['id'] ) && 'invalid-image' === $response_body['error']['id'] ) {
 | 
						|
				$result['message'] = esc_html__( 'Valid image data is required.', 'w3-total-cache' );
 | 
						|
			} elseif ( isset( $response_body['error']['id'] ) && 'invalid-input-mime' === $response_body['error']['id'] ) {
 | 
						|
				$result['message'] = esc_html__( 'Invalid input image MIME type.', 'w3-total-cache' );
 | 
						|
			} elseif ( 403 === $response['response']['code'] ) {
 | 
						|
				$result['message'] = sprintf(
 | 
						|
					// translators: 1: HTML anchor open tag, 2: HTML anchor close tag.
 | 
						|
					esc_html__( 'Please verify your license key in %1$sGeneral Settings%2$s.', 'w3-total-cache' ),
 | 
						|
					'<a href="' . esc_url( Util_Ui::admin_url( 'admin.php?page=w3tc_general#licensing' ) ) . '">',
 | 
						|
					'</a>'
 | 
						|
				);
 | 
						|
			} elseif ( isset( $response_body['error']['message'] ) ) {
 | 
						|
				// Unknown error message id; forward the error message.
 | 
						|
				$result['message'] = esc_html( $response_body['error']['message'] );
 | 
						|
			}
 | 
						|
 | 
						|
			return $result;
 | 
						|
		}
 | 
						|
 | 
						|
		return $response_body;
 | 
						|
	}
 | 
						|
 | 
						|
	/**
 | 
						|
	 * Get job status.
 | 
						|
	 *
 | 
						|
	 * @since 2.2.0
 | 
						|
	 *
 | 
						|
	 * @param int    $job_id    Job id.
 | 
						|
	 * @param string $signature Signature.
 | 
						|
	 * @return array
 | 
						|
	 */
 | 
						|
	public function get_status( $job_id, $signature ) {
 | 
						|
		$response = wp_remote_request(
 | 
						|
			$this->get_base_url() . $this->endpoints['status']['uri'] . '/' . $job_id . '/' . $signature,
 | 
						|
			array(
 | 
						|
				'method'    => $this->endpoints['status']['method'],
 | 
						|
				'sslverify' => false,
 | 
						|
				'timeout'   => 10,
 | 
						|
				'headers'   => array(
 | 
						|
					'Accept' => 'application/json',
 | 
						|
				),
 | 
						|
			)
 | 
						|
		);
 | 
						|
 | 
						|
		if ( is_wp_error( $response ) ) {
 | 
						|
			return array(
 | 
						|
				'error' => __( 'WP Error: ', 'w3-total-cache' ) . $response->get_error_message(),
 | 
						|
			);
 | 
						|
		}
 | 
						|
 | 
						|
		// Convert response body to an array.
 | 
						|
		$response = json_decode( wp_remote_retrieve_body( $response ), true );
 | 
						|
 | 
						|
		// Pass error message.
 | 
						|
		if ( isset( $response['error'] ) ) {
 | 
						|
			return array(
 | 
						|
				'error' => $response['error'],
 | 
						|
			);
 | 
						|
		}
 | 
						|
 | 
						|
		return $response;
 | 
						|
	}
 | 
						|
 | 
						|
	/**
 | 
						|
	 * Download a processed image.
 | 
						|
	 *
 | 
						|
	 * @since 2.2.0
 | 
						|
	 *
 | 
						|
	 * @param int    $job_id    Job id.
 | 
						|
	 * @param string $signature Signature.
 | 
						|
	 * @return array WP response array.
 | 
						|
	 */
 | 
						|
	public function download( $job_id, $signature ) {
 | 
						|
		$response = wp_remote_request(
 | 
						|
			$this->get_base_url() . $this->endpoints['download']['uri'] . '/' . $job_id . '/' . $signature,
 | 
						|
			array(
 | 
						|
				'method'    => $this->endpoints['download']['method'],
 | 
						|
				'sslverify' => false,
 | 
						|
				'timeout'   => 10,
 | 
						|
			)
 | 
						|
		);
 | 
						|
 | 
						|
		if ( is_wp_error( $response ) ) {
 | 
						|
			return array(
 | 
						|
				'error' => __( 'WP Error: ', 'w3-total-cache' ) . $response->get_error_message(),
 | 
						|
			);
 | 
						|
		}
 | 
						|
 | 
						|
		// Get the response body.
 | 
						|
		$body = wp_remote_retrieve_body( $response );
 | 
						|
 | 
						|
		// Convert response body to an array.  A successful image results in a JSON decode false return.
 | 
						|
		$json = json_decode( $body, true );
 | 
						|
 | 
						|
		// Pass error message.
 | 
						|
		if ( isset( $json['error'] ) ) {
 | 
						|
			return array(
 | 
						|
				'error' => $json['error'],
 | 
						|
			);
 | 
						|
		}
 | 
						|
 | 
						|
		return $response;
 | 
						|
	}
 | 
						|
 | 
						|
	/**
 | 
						|
	 * Get usage statistics.
 | 
						|
	 *
 | 
						|
	 * @since 2.2.0
 | 
						|
	 *
 | 
						|
	 * @return array
 | 
						|
	 */
 | 
						|
	public function get_usage() {
 | 
						|
		$error_message  = __( 'Unknown', 'w3-total-cache' );
 | 
						|
		$error_response = array(
 | 
						|
			'usage_hourly'  => $error_message,
 | 
						|
			'usage_monthly' => $error_message,
 | 
						|
			'limit_hourly'  => $error_message,
 | 
						|
			'limit_monthly' => $error_message,
 | 
						|
		);
 | 
						|
 | 
						|
		$response = wp_remote_request(
 | 
						|
			esc_url(
 | 
						|
				$this->get_base_url() . $this->endpoints['usage']['uri'] .
 | 
						|
					'/' . rawurlencode( $this->license_key ) .
 | 
						|
					'/' . urlencode( $this->item_name ) . // phpcs:ignore
 | 
						|
					'/' . rawurlencode( $this->home_url )
 | 
						|
			),
 | 
						|
			array(
 | 
						|
				'method'    => $this->endpoints['usage']['method'],
 | 
						|
				'sslverify' => false,
 | 
						|
				'timeout'   => 10,
 | 
						|
				'headers'   => array(
 | 
						|
					'Accept' => 'application/json',
 | 
						|
				),
 | 
						|
			)
 | 
						|
		);
 | 
						|
 | 
						|
		if ( is_wp_error( $response ) ) {
 | 
						|
			return $error_response;
 | 
						|
		}
 | 
						|
 | 
						|
		// Convert response body to an array.
 | 
						|
		$response = json_decode( wp_remote_retrieve_body( $response ), true );
 | 
						|
 | 
						|
		// If usage is not obtained, then return error response.
 | 
						|
		if ( ! isset( $response['usage_hourly'] ) ) {
 | 
						|
			return $error_response;
 | 
						|
		} else {
 | 
						|
			// Update usage.
 | 
						|
			set_transient(
 | 
						|
				'w3tc_imageservice_usage',
 | 
						|
				array(
 | 
						|
					'updated_at'    => time(),
 | 
						|
					'usage_hourly'  => $response['usage_hourly'],
 | 
						|
					'usage_monthly' => isset( $response['usage_monthly'] ) ? $response['usage_monthly'] : null,
 | 
						|
					'limit_hourly'  => isset( $response['limit_hourly'] ) ? $response['limit_hourly'] : null,
 | 
						|
					'limit_monthly' => isset( $response['limit_monthly'] ) ? $response['limit_monthly'] : null,
 | 
						|
				),
 | 
						|
				DAY_IN_SECONDS
 | 
						|
			);
 | 
						|
 | 
						|
			// Ensure that the monthly limit is represented correctly.
 | 
						|
			$response['limit_monthly'] = $response['limit_monthly'] ? $response['limit_monthly'] : __( 'Unlimited', 'w3-total-cache' );
 | 
						|
 | 
						|
			return $response;
 | 
						|
		}
 | 
						|
	}
 | 
						|
 | 
						|
	/**
 | 
						|
	 * Get base URL.
 | 
						|
	 *
 | 
						|
	 * @since 2.2.0
 | 
						|
	 * @access private
 | 
						|
	 *
 | 
						|
	 * @returns string
 | 
						|
	 */
 | 
						|
	private function get_base_url() {
 | 
						|
		return defined( 'W3TC_API2_URL' ) && W3TC_API2_URL ?
 | 
						|
			esc_url( W3TC_API2_URL, 'https', '' ) : $this->base_url;
 | 
						|
	}
 | 
						|
}
 |