laipower/wp-content/plugins/w3-total-cache/Extension_ImageService_Api.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;
}
}