url = 'https://api.stockpack.co/api'; } else { $this->url = STOCKPACK_URL; } $this->api_key = add_action( 'plugins_loaded', array( $this, 'init' ) ); } /** * */ public function init() { $this->actions(); } /** * */ public function actions() { add_action( 'wp_ajax_query-stockpack', array( $this, 'query' ) ); // executed when logged in add_action( 'wp_ajax_license_cost-stockpack', array( $this, 'license_cost' ) ); // executed when logged in add_action( 'wp_ajax_download-stockpack', array( $this, 'download' ) ); // executed when logged in add_action( 'wp_ajax_cache-stockpack', array( $this, 'cache' ) ); // executed when logged in add_action( 'wp_ajax_validate-stockpack', array( $this, 'validate' ) ); // executed when logged in add_action( 'wp_ajax_terms-stockpack', array( $this, 'terms' ) ); // executed when logged in add_action( 'wp_ajax_token-stockpack', array( $this, 'token' ) ); // executed when logged in } public function terms() { check_ajax_referer( 'stockpack_terms', 'security' ); $provider = ''; if ( isset( $_REQUEST['provider'] ) ) { $provider = sanitize_key( $_REQUEST['provider'] ); } wp_send_json_success( update_option( 'terms_accepted_' . $provider, true ) ); } public function license_cost() { check_ajax_referer( 'stockpack_license_cost', 'security' ); $media_id = ''; if ( isset( $_REQUEST['media_id'] ) ) { $media_id = sanitize_text_field( $_REQUEST['media_id'] ); } $response = $this->get_license_cost( $media_id ); if ( isset( $response->data->error ) ) { wp_send_json_error( $this->handle_license_errors( $response->data ) ); die(); } if ( is_wp_error( $response ) ) { wp_send_json_error( $this->handle_license_errors( $response ) ); die(); } if ( $response->data->cost == - 1 ) { $response->data->cost_message = __( 'You already own the asset, you can proceed without additional cost', 'stockpack' ); } if ( $response->data->cost == 1 && ! $response->data->cost_message ) { $response->data->cost_message = __( 'You will be charged for one image on you provider account', 'stockpack' ); } wp_send_json_success( $response->data, true ); } public function token() { global $stockpack; check_ajax_referer( 'stockpack_token', 'security' ); $token = ''; if ( isset( $_REQUEST['token'] ) ) { $token = sanitize_text_field( $_REQUEST['token'] ); } wp_send_json_success( $stockpack->admin->set_api_key( $token ), true ); } /** * */ public function validate() { check_ajax_referer( 'stockpack_validate', 'security' ); $key = ''; if ( isset( $_REQUEST['key'] ) ) { $key = sanitize_key( $_REQUEST['key'] ); } wp_send_json_success( $this->call( 'GET', 'validate/token', array( 'key' => $key ))); } /** * */ public function query() { check_ajax_referer( 'stockpack_query', 'security' ); if ( ! current_user_can( 'upload_files' ) ) { wp_send_json_error(); } $query=array(); if ( isset( $_REQUEST['query'] ) ) { $query = array_map( 'sanitize_text_field', wp_unslash($_REQUEST['query'])); } if ( ! $query['query'] ) { return wp_send_json_success( array() ); } $images = $this->images( $query ); if ( is_wp_error( $images ) ) { /** @var WP_Error $images */ wp_send_json_error( $images ); die(); } if ( isset( $images->data->error ) ) { wp_send_json_error( $this->handle_search_errors( $images->data ) ); die(); } wp_send_json_success( $this->format( $images->data ) ); } /** * */ public function cache() { check_ajax_referer( 'stockpack_cache', 'security' ); if ( ! current_user_can( 'upload_files' ) ) { wp_send_json_error(); } $id=0; if ( isset( $_REQUEST['media_id'] ) ) { $id = sanitize_text_field($_REQUEST['media_id']); } $args = array( 'post_type' => 'attachment', 'post_status' => 'inherit', 'meta_query' => array( array( 'key' => 'stockpack_id', 'value' => $id ) ) ); $query = new WP_Query( $args ); if ( ! $query->have_posts() ) { wp_send_json_error( array( 'message' => __( 'Image not found in cache', 'stockpack' ) ) ); } wp_send_json_success( wp_prepare_attachment_for_js( $query->post->ID ) ); } /** * */ public function download() { check_ajax_referer( 'stockpack_download', 'security' ); if ( ! current_user_can( 'upload_files' ) ) { wp_send_json_error( array( 'message' => __( 'You are not allowed to upload files', 'stockpack' ) ) ); } $id = 0; if ( isset( $_REQUEST['media_id'] ) ) { $id = sanitize_text_field($_REQUEST['media_id']); } $post_id=0; if ( isset( $_REQUEST['post_id'] ) ) { $post_id = sanitize_text_field($_REQUEST['post_id']); } $must_license=false; if ( isset( $_REQUEST['must_license'] ) ) { $must_license = sanitize_text_field($_REQUEST['must_license']); } $search = isset( $_REQUEST['search'] ) ? sanitize_title( $_REQUEST['search'] ) : $this->get_domain(); $description = isset( $_REQUEST['description'] ) ? sanitize_textarea_field( $_REQUEST['description'] ) : ''; $image = $this->image( $id, $post_id, $description, $search, $must_license ); if ( is_wp_error( $image ) ) { if ( strpos( $image->get_error_code(), 'limit_reached' ) !== false ) { wp_send_json_error( $image ); die(); } wp_send_json_error( array( 'message' => $image->get_error_message() ) ); } wp_send_json_success( wp_prepare_attachment_for_js( $image ) ); } /** * @param $data * * @return array */ private function format( $data ) { return $data; } /** * @param $image * * @return array */ private function individual( $image ) { return [ 'id' => $image->id, 'description' => $image->description, 'caption' => $image->caption ? $image->caption : '', 'url' => $image->assets->huge_thumb->url, 'sizes' => [ 'full' => $this->size( $image, 'huge_thumb' ), 'medium' => $this->size( $image, 'preview' ), 'thumbnail' => $this->size( $image, 'large_thumb' ) ] ]; } private function size( $image, $format ) { return [ 'height' => $image->assets->$format->height, 'width' => $image->assets->$format->width, 'orientation' => ( $image->aspect > 1 ? 'landscape' : 'portrait' ), 'url' => $image->assets->$format->url ]; } private function get_license_cost( $media_id ) { $response = $this->call( 'GET', 'images/license-cost', array( 'id' => $media_id, 'locale' => get_locale(), ) ); return $response; } private function image( $media_id, $post_id, $description = '', $search = '', $must_license = 0 ) { $image = $this->call( 'GET', 'images/download', array( 'id' => $media_id, 'must_license' => $must_license ) ); if ( ! isset( $image->data->download ) ) { if ( is_wp_error( $image ) ) { return $image; } return $this->handle_download_errors( $image->data ); } $caption = $image->data->caption ?: ''; $attachment_id = $this->upload_remote_image_and_attach( $image->data->download, $post_id, $description, $image->data->name, $search, $caption ); if ( is_wp_error( $attachment_id ) ) { return $attachment_id; } if ( ! $attachment_id ) { return new WP_Error( __( 'upload_failure', 'There has been a problem with the upload. Please try again', 'stockpack' ) ); } update_post_meta( $attachment_id, 'stockpack_id', $media_id ); return $attachment_id; } private function handle_license_errors( $response ) { if ( isset( $response->code ) ) { switch ( $response->code ) { case 'token_expired': return new WP_Error( 'license_cost_failure', __( 'Please reconnect the account on shutterstock, the permissions have expired. Go the providers page on stockpack.co/providers', 'stockpack' ) ); } } return new WP_Error( 'license_cost_failure', __( 'There has been a problem fetching the cost. Please try to reconnect the account on the providers page on shutterstock.co/providers', 'stockpack' ) ); } private function handle_download_errors( $response ) { if ( isset( $response->code ) ) { switch ( $response->code ) { case 'token_expired': return new WP_Error( 'download_failure', __( 'Please reconnect the account on shutterstock, the permissions have expired. Go the providers page on stockpack.co/providers', 'stockpack' ) ); } } return new WP_Error( 'download_failure', __( 'There has been a problem with the download. Try to reconnect the account for the provider on StockPack. If the issue persists, contact stockpack support.', 'stockpack' ) ); } private function handle_search_errors( $response ) { if ( isset( $response->code ) ) { switch ( $response->code ) { case 'token_expired': return new WP_Error( 'search_failure', __( 'Please reconnect the account on stockpack, the permissions have expired. Go to the providers page on stockpack.co/providers', 'stockpack' ) ); } } return new WP_Error( 'search_failure', __( 'There has been a problem with the api, please check the accounts on the providers page in stockpack.co/providers', 'stockpack' ) ); } private function images( $query = [] ) { return $this->call( 'GET', 'images/search', $query ); } /** * @param $method * @param $path * @param array $query * * @return mixed|null */ private function call( $method, $path, $query = [] ) { /** @var StockPack $stockpack */ global $stockpack; try { if ( ! isset( $query['key'] ) ) { $api_key = $stockpack->admin->get_api_key(); if ( $api_key ) { $query = array_merge( $query, [ 'api_token' => $api_key ] ); } else { $path .= '-trial'; } } $query = array_merge( $query, [ 'referral' => get_bloginfo( 'url' ), 'safe_search' => $stockpack->admin->get_safe_search(), 'user_data' => $stockpack->admin->get_license_state(), ] ); $response = $this->client()->request( $method, $path, [ 'query' => $query ] ); return json_decode( $response->getBody() ); } catch ( GuzzleException $exception ) { switch ( $exception->getCode() ) { case 429: // too many requests return $this->limit_exceeded( $exception ); default: return new WP_Error( 1, __( 'Can\'t connect to StockPack server.', 'stockpack' ) ); } } } private function limit_exceeded( $exception ) { /** @var StockPack $stockpack */ global $stockpack; $response = $exception->getResponse(); $limit = $response->getHeaderLine( 'x-ratelimit-limit' ); $retry_after = $response->getHeaderLine( 'retry-after' ); $retry_after = $this->human_seconds( $retry_after ); $retry_after = '' . $retry_after . ''; if ( $limit > 50 ) { return new WP_Error( 'premium_limit_reached', __( 'Request limit reached, the reset will be in ', 'stockpack' ) . $retry_after ); } $api_key = $stockpack->admin->get_api_key(); if ( $api_key ) { return new WP_Error( 'free_limit_reached', __( 'Request limit reached, the reset will be in ', 'stockpack' ) . $retry_after ); } return new WP_Error( 'anonymous_limit_reached', __( 'Request limit reached, the reset will be in ', 'stockpack' ) . $retry_after ); } /** * @return Client */ private function client() { if ( ! $this->client ) { $this->client = new Client( [ 'base_uri' => $this->url . '/' . self::VERSION . '/', ] ); } return $this->client; } private function support_caption_translation( $caption ) { if ( ! $caption ) { return ''; } $caption = str_replace( 'Photo by', __( 'Photo by', 'stockpack' ), $caption ); $caption = str_replace( ' on ', _x( ' on ', 'Make sure to keep the space', 'stockpack' ), $caption ); return $caption; } /** * @param $image_url * @param $parent_id * * @param $description * * @param $name * @param string $search * * @param string $caption * * @return bool|int|WP_Error */ private function upload_remote_image_and_attach( $image_url, $parent_id, $description, $name, $search = '', $caption = '' ) { $image = $image_url; $get = wp_remote_get( $image, array( 'timeout' => 30 ) ); if ( is_wp_error( $get ) ) { return new WP_Error( 100, __( 'Image download failed, please try again. Errors:', 'stockpack' ) . PHP_EOL . $get->get_error_message() ); } $type = wp_remote_retrieve_header( $get, 'content-type' ); if ( ! $type ) { return new WP_Error( 100, __( 'Image type couldn\'t be determined', 'stockpack' ) ); } $mirror = wp_upload_bits( $name, '', wp_remote_retrieve_body( $get ) ); $attachment = array( 'post_title' => $name, 'post_content' => $description, 'post_excerpt' => $this->support_caption_translation( $caption ), 'post_mime_type' => $type ); $attach_id = wp_insert_attachment( $attachment, $mirror['file'], $parent_id ); require_once( ABSPATH . 'wp-admin/includes/image.php' ); $attach_data = wp_generate_attachment_metadata( $attach_id, $mirror['file'] ); wp_update_attachment_metadata( $attach_id, $attach_data ); update_post_meta( $attach_id, '_wp_attachment_image_alt', $description ); return $attach_id; } /** * @return mixed */ private function get_domain() { $url = get_bloginfo( 'url' ); $parse = wp_parse_url( $url ); return strtok( $parse['host'], '.' ); } private function human_seconds( $seconds, $separator = ":" ) { return sprintf( "%02d%s%02d%s%02d", floor( $seconds / 3600 ), $separator, ( $seconds / 60 ) % 60, $separator, $seconds % 60 ); } } $GLOBALS['stockpack_query'] = StockpackQuery::get_instance(); }