wp_http = $wp_http; $this->auth = $auth; $this->endpoints = $endpoints; $this->clonedSitesHandler = $clonedSitesHandler; $this->fingerprintGenerator = $fingerprintGenerator; } /** * @param array $params * * @see https://bitbucket.org/emartini_crossover/ate/wiki/API/V1/jobs/create * * @return mixed * @throws \InvalidArgumentException */ public function create_jobs( array $params ) { return $this->requestWithLog( $this->endpoints->get_ate_jobs(), [ 'method' => 'POST', 'body' => $params, ] ); } /** * @param int|string|array $ate_job_id * * @return array|WP_Error * @throws \InvalidArgumentException */ public function confirm_received_job( $ate_job_id ) { return $this->requestWithLog( $this->endpoints->get_ate_confirm_job( $ate_job_id ) ); } /** * @param int $job_id * @param string $return_url * * @return string|WP_Error * @throws \InvalidArgumentException */ public function get_editor_url( $job_id, $return_url ) { $lock = $this->clonedSitesHandler->checkCloneSiteLock(); if ( $lock ) { return new WP_Error( 'communication_error', 'ATE communication is locked, please update configuration' ); } $url = $this->endpoints->get_ate_editor(); $url = str_replace( [ '{job_id}', '{translator_email}', '{return_url}', ], [ $job_id, urlencode( filter_var( wp_get_current_user()->user_email, FILTER_SANITIZE_URL ) ), urlencode( filter_var( $return_url, FILTER_SANITIZE_URL ) ), ], $url ); return $this->auth->get_signed_url_with_parameters( 'GET', $url, null ); } /** * @param int $ate_job_id * @param WPML_Element_Translation_Job $job_object * * @return array */ public function clone_job( $ate_job_id, WPML_Element_Translation_Job $job_object ) { $url = $this->endpoints->get_clone_job( $ate_job_id ); $result = $this->requestWithLog( $url, [ 'method' => 'POST', 'body' => [ 'id' => $ate_job_id, 'notify_url' => WPML_TM_REST_ATE_Public::get_receive_ate_job_url( $job_object->get_id() ), 'site_identifier' => wpml_get_site_id( WPML_TM_ATE::SITE_ID_SCOPE ), 'source_id' => wpml_tm_get_records() ->icl_translate_job_by_job_id( $job_object->get_id() ) ->rid(), 'permalink' => $job_object->get_url( true ), 'ate_ams_console_url' => wpml_tm_get_ams_ate_console_url(), ], ] ); if ( $result && ! is_wp_error( $result ) ) { return [ 'id' => $result->job_id, 'ate_status' => isset( $result->status ) ? $result->status : WPML_TM_ATE_AMS_Endpoints::ATE_JOB_STATUS_CREATED, ]; } else { return false; } } /** * @param int $ate_job_id * * @return array|WP_Error * @throws \InvalidArgumentException */ public function get_job( $ate_job_id ) { if ( ! $ate_job_id ) { return null; } return $this->requestWithLog( $this->endpoints->get_ate_jobs( $ate_job_id ) ); } /** * If `$job_ids` is not an empty array, * the `$statuses` parameter will be ignored in ATE's endpoint. * * @see https://bitbucket.org/emartini_crossover/ate/wiki/API/V1/jobs/status * * @param null|array $job_ids * @param null|array $statuses * * @return array|mixed|null|object|WP_Error * @throws \InvalidArgumentException */ public function get_jobs( $job_ids, $statuses = null ) { return $this->requestWithLog( $this->endpoints->get_ate_jobs( $job_ids, $statuses ) ); } /** * @param $wpml_job_ids * * @return array|mixed|object|WP_Error|null */ public function get_jobs_by_wpml_ids( $wpml_job_ids ) { return $this->requestWithLog( $this->endpoints->get_ate_jobs_by_wpml_job_ids( $wpml_job_ids ) ); } /** * @param array $pairs * @see https://bitbucket.org/emartini_crossover/ate/wiki/API/V1/migration/migrate * @return bool */ public function migrate_source_id( array $pairs ) { $lock = $this->clonedSitesHandler->checkCloneSiteLock(); if ( $lock ) { return false; } $verb = 'POST'; $url = $this->auth->get_signed_url_with_parameters( $verb, $this->endpoints->get_source_id_migration(), $pairs ); if ( is_wp_error( $url ) ) { return $url; } $result = $this->wp_http->request( $url, array( 'timeout' => 60, 'method' => $verb, 'headers' => $this->json_headers(), 'body' => wp_json_encode( $pairs, JSON_UNESCAPED_UNICODE | JSON_UNESCAPED_SLASHES ), ) ); if ( ! is_wp_error( $result ) ) { $result = $this->clonedSitesHandler->handleClonedSiteError( $result ); } return $this->get_response_errors( $result ) === null; } private function get_response( $result ) { $errors = $this->get_response_errors( $result ); if ( is_wp_error( $errors ) ) { return $errors; } return $this->get_response_body( $result ); } private function get_response_body( $result ) { if ( is_array( $result ) && array_key_exists( 'body', $result ) && ! is_wp_error( $result ) ) { $body = json_decode( $result['body'] ); if ( isset( $body->authenticated ) && ! (bool) $body->authenticated ) { return new WP_Error( 'ate_auth_failed', $body->message ); } return $body; } return $result; } private function get_response_errors( $response ) { $response_errors = null; if ( is_wp_error( $response ) ) { $response_errors = $response; } elseif ( array_key_exists( 'body', $response ) && $response['response']['code'] >= 400 ) { $errors = array(); $response_body = json_decode( $response['body'], true ); if ( is_array( $response_body ) && array_key_exists( 'errors', $response_body ) ) { $errors = $response_body['errors']; } $response_errors = new WP_Error( $response['response']['code'], $response['response']['message'], $errors ); } return $response_errors; } /** * @return array */ private function json_headers() { return [ 'Accept' => 'application/json', 'Content-Type' => 'application/json', FingerprintGenerator::SITE_FINGERPRINT_HEADER => $this->fingerprintGenerator->getSiteFingerprint(), ]; } /** * @param array $args * * @return string */ private function encode_body_args( array $args ) { return wp_json_encode( $args, JSON_UNESCAPED_UNICODE | JSON_UNESCAPED_SLASHES ); } /** * @param string $xliff_url * * @return string * @throws Requests_Exception */ public function get_remote_xliff_content( $xliff_url ) { /** @var \WP_Error|array $response */ $response = wp_remote_get( $xliff_url ); if ( is_wp_error( $response ) ) { throw new Requests_Exception( $response->get_error_message(), $response->get_error_code() ); } elseif ( isset( $response['response']['code'] ) && 200 !== (int) $response['response']['code'] ) { throw new Requests_Exception( $response['response']['message'], $response['response']['code'] ); } elseif ( ! isset( $response['body'] ) || ! trim( $response['body'] ) ) { throw new Requests_Exception( 'Missing body', 0 ); } return $response['body']; } public function override_site_id( $site_id ) { $this->auth->override_site_id( $site_id ); } public function get_website_id( $site_url ) { $lock = $this->clonedSitesHandler->checkCloneSiteLock(); if ( $lock ) { return null; } $signed_url = $this->auth->get_signed_url_with_parameters( 'GET', $this->endpoints->get_websites() ); if ( is_wp_error( $signed_url ) ) { return null; } $requestArguments = [ 'headers' => $this->json_headers() ]; $response = $this->wp_http->request( $signed_url, $requestArguments ); if ( ! is_wp_error( $response ) ) { $response = $this->clonedSitesHandler->handleClonedSiteError( $response ); } $sites = $this->get_response( $response ); foreach ( $sites as $site ) { if ( $site->url === $site_url ) { return $site->uuid; } } return null; } /** * @see https://bitbucket.org/emartini_crossover/ate/wiki/API/V1/sync/all * * @param array $ateJobIds * * @return array|mixed|null|object|WP_Error * @throws \InvalidArgumentException */ public function sync_all( array $ateJobIds ) { return $this->requestWithLog( $this->endpoints->get_sync_all(), [ 'method' => 'POST', 'body' => [ 'ids' => $ateJobIds ], ] ); } /** * @see https://bitbucket.org/emartini_crossover/ate/wiki/API/V1/sync/page * * @param string $token * @param int $page * * @return array|mixed|null|object|WP_Error * @throws \InvalidArgumentException */ public function sync_page( $token, $page ) { return $this->requestWithLog( $this->endpoints->get_sync_page( $token, $page ) ); } /** * @param string $url * @param array $requestArgs * * @return array|mixed|object|string|WP_Error|null */ private function request( $url, array $requestArgs = [] ) { $lock = $this->clonedSitesHandler->checkCloneSiteLock(); if ( $lock ) { return $lock; } $requestArgs = array_merge( [ 'timeout' => 60, 'method' => 'GET', 'headers' => $this->json_headers(), ], $requestArgs ); $bodyArgs = isset( $requestArgs['body'] ) && is_array( $requestArgs['body'] ) ? $requestArgs['body'] : null; $signedUrl = $this->auth->get_signed_url_with_parameters( $requestArgs['method'], $url, $bodyArgs ); if ( is_wp_error( $signedUrl ) ) { return $signedUrl; } if ( $bodyArgs ) { $requestArgs['body'] = $this->encode_body_args( $bodyArgs ); } $result = $this->wp_http->request( $signedUrl, $requestArgs ); if ( ! is_wp_error( $result ) ) { $result = $this->clonedSitesHandler->handleClonedSiteError( $result ); } return $this->get_response( $result ); } /** * @param string $url * @param array $requestArgs * * @return array|mixed|object|string|WP_Error|null */ private function requestWithLog( $url, array $requestArgs = [] ) { $response = $this->request( $url, $requestArgs ); if ( is_wp_error( $response ) ) { $entry = new Entry(); $entry->event = ErrorEvents::SERVER_ATE; $entry->description = $response->get_error_message(); $entry->extraData = [ 'url' => $url, 'requestArgs' => $requestArgs, ]; wpml_tm_ate_ams_log( $entry ); } return $response; } }