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;
 | |
| 	}
 | |
| }
 |