# speechkit/4.0.6/src/Core/ApiClient.php

BeyondWords – AI audio for publishers, version 4.0.6. 457 lines.

- Page: https://pluginprobe.com/plugins/speechkit/4.0.6/code/src/Core/ApiClient.php
- Raw: https://pluginprobe.com/plugins/speechkit/4.0.6/raw/src/Core/ApiClient.php
- Modified: 2023-09-07T17:37:44+00:00

Line numbers below start at 1. Link to a line or a range by appending a fragment to the
page URL, for example `https://pluginprobe.com/plugins/speechkit/4.0.6/code/src/Core/ApiClient.php#L10-L20`.

```php
<?php

declare(strict_types=1);

namespace Beyondwords\Wordpress\Core;

use Beyondwords\Wordpress\Core\Environment;
use Beyondwords\Wordpress\Core\Request;
use Beyondwords\Wordpress\Component\Post\PostContentUtils;
use Beyondwords\Wordpress\Component\Post\PostMetaUtils;
use Beyondwords\Wordpress\Component\Settings\SettingsUtils;

class ApiClient
{
    public const ERROR_FORMAT = '#%s: %s';

    public $errors;

    /**
     * Constructor
     *
     * @since 3.0.0
     */
    public function __construct()
    {
        add_action('admin_notices', array($this, 'adminNotices'));

        $this->errors = [];
    }

    /**
     * POST /projects/:id/content.
     *
     * @since 3.0.0
     *
     * @param $postId WordPress Post ID
     *
     * @return Response|false Response, or false
     **/
    public function createAudio($postId)
    {
        $projectId = PostMetaUtils::getProjectId($postId);

        $url = sprintf('%s/projects/%d/content', Environment::getApiUrl(), $projectId);

        $body = PostContentUtils::getBodyJson($postId);

        $request = new Request('POST', $url, $body);

        return $this->callApi($postId, $request);
    }

    /**
     * PUT /projects/:id/content/:id.
     *
     * @since 3.0.0
     *
     * @param $postId WordPress Post ID
     *
     * @return Response|false Response, or false
     **/
    public function updateAudio($postId)
    {
        $projectId = PostMetaUtils::getProjectId($postId);
        $contentId = PostMetaUtils::getContentId($postId);

        $url = sprintf('%s/projects/%d/content/%s', Environment::getApiUrl(), $projectId, $contentId);

        $body = PostContentUtils::getBodyJson($postId);

        $request = new Request('PUT', $url, $body);

        return $this->callApi($postId, $request);
    }

    /**
     * DELETE /projects/:id/content/:id.
     *
     * @since 3.0.0
     *
     * @param $postId WordPress Post ID
     *
     * @return Response|false Response, or false
     **/
    public function deleteAudio($postId)
    {
        $projectId = PostMetaUtils::getProjectId($postId);
        $contentId = PostMetaUtils::getContentId($postId);

        $url = sprintf('%s/projects/%d/content/%s', Environment::getApiUrl(), $projectId, $contentId);

        $request = new Request('DELETE', $url);

        return $this->callApi($postId, $request);
    }

    /**
     * GET /organization/languages
     *
     * @since 4.0.0 Introduced
     * @since 4.0.2 Prefix endpoint with /organization
     *
     * @return array|object Array of voices or API error object.
     **/
    public function getLanguages()
    {
        $url = sprintf('%s/organization/languages', Environment::getApiUrl());

        $request = new Request('GET', $url);

        $args = array(
            'blocking'    => true,
            'headers'     => $request->getHeaders(),
            'method'      => $request->getMethod(),
            'sslverify'   => true,
        );

        $response = wp_remote_request($request->getUrl(), $args);

        // WordPress error performing API call
        if (is_wp_error($response) && get_the_ID()) {
            return $this->error(
                get_the_ID(),
                $response->get_error_message(),
                $response->get_error_code()
            );
        }

        $responseBody = wp_remote_retrieve_body($response);

        return json_decode($responseBody, true);
    }

    /**
     * GET /organization/voices
     *
     * @since 4.0.0 Introduced
     * @since 4.0.2 Prefix endpoint with /organization
     *
     * @param $languageId BeyondWords Language ID
     *
     * @return array|object Array of voices or API error object.
     **/
    public function getVoices($languageId)
    {
        $url = sprintf('%s/organization/voices?filter[language.id]=%s', Environment::getApiUrl(), urlencode(strval($languageId))); // phpcs:ignore Generic.Files.LineLength.TooLong

        $request = new Request('GET', $url);

        $args = array(
            'blocking'    => true,
            'headers'     => $request->getHeaders(),
            'method'      => $request->getMethod(),
            'sslverify'   => true,
        );

        $response = wp_remote_request($request->getUrl(), $args);

        // WordPress error performing API call
        if (is_wp_error($response) && get_the_ID()) {
            return $this->error(
                get_the_ID(),
                $response->get_error_message(),
                $response->get_error_code()
            );
        }

        $responseBody = wp_remote_retrieve_body($response);

        return json_decode($responseBody, true);
    }

    /**
     * GET /projects/:id.
     *
     * @since 4.0.0
     *
     * @return Response|false Response, or false
     **/
    public function getProject()
    {
        $projectId = get_option('beyondwords_project_id');

        if (! $projectId) {
            return false;
        }

        $url = sprintf('%s/projects/%d', Environment::getApiUrl(), $projectId);

        $request = new Request('GET', $url);

        $args = array(
            'blocking'    => true,
            'headers'     => $request->getHeaders(),
            'method'      => $request->getMethod(),
            'sslverify'   => true,
        );

        $response = wp_remote_request($request->getUrl(), $args);

        // WordPress error performing API call
        if (is_wp_error($response) && get_the_ID()) {
            return $this->error(
                get_the_ID(),
                $response->get_error_message(),
                $response->get_error_code()
            );
        }

        $responseBody = wp_remote_retrieve_body($response);

        return json_decode($responseBody, true);
    }

    /**
     * GET /projects/:id/player_settings.
     *
     * @since 4.0.0
     *
     * @param array $settings Associative array if player settings.
     *
     * @return Response|false Response, or false
     **/
    public function getPlayerSettings()
    {
        $projectId = get_option('beyondwords_project_id');

        if (! $projectId) {
            return false;
        }

        $url = sprintf('%s/projects/%d/player_settings', Environment::getApiUrl(), $projectId);

        $request = new Request('GET', $url);

        $args = array(
            'blocking'    => true,
            'headers'     => $request->getHeaders(),
            'method'      => $request->getMethod(),
            'sslverify'   => true,
        );

        $response = wp_remote_request($request->getUrl(), $args);

        // WordPress error performing API call
        if (is_wp_error($response) && get_the_ID()) {
            return $this->error(
                get_the_ID(),
                $response->get_error_message(),
                $response->get_error_code()
            );
        }

        $responseBody = wp_remote_retrieve_body($response);

        return json_decode($responseBody, true);
    }

    /**
     * PUT /projects/:id/player_settings.
     *
     * @since 4.0.0
     *
     * @param array $settings Associative array if player settings.
     *
     * @return Response|false Response, or false
     **/
    public function updatePlayerSettings($settings)
    {
        $projectId = get_option('beyondwords_project_id');

        if (! $projectId) {
            return false;
        }

        $url = sprintf('%s/projects/%d/player_settings', Environment::getApiUrl(), $projectId);

        $request = new Request('PUT', $url, $settings);

        $args = array(
            'blocking'    => true,
            'body'        => wp_json_encode($settings),
            'headers'     => $request->getHeaders(),
            'method'      => $request->getMethod(),
            'sslverify'   => true,
        );

        $response = wp_remote_request($request->getUrl(), $args);

        // WordPress error performing API call
        if (is_wp_error($response) && get_the_ID()) {
            return $this->error(
                get_the_ID(),
                $response->get_error_message(),
                $response->get_error_code()
            );
        }

        $responseBody = wp_remote_retrieve_body($response);

        return json_decode($responseBody, true);
    }

    /**
     * Call the BeyondWords API backend.
     *
     * @since 3.0.0
     * @since 3.9.0 Stop saving the speechkit_status post meta - downgrades to plugin v2.x are no longer expected.
     * @since 4.0.0 Removed hash comparison.
     *
     * @param int     $postId  Post ID.
     * @param Request $request Request.
     *
     * @return array|false JSON-decoded response body, or false on failure
     **/
    public function callApi($postId, $request)
    {
        $args = array(
            'blocking'    => true,
            'body'        => $request->getBody(),
            'headers'     => $request->getHeaders(),
            'method'      => $request->getMethod(),
            'sslverify'   => true,
        );

        // Reset any existing errors before making this API call
        delete_post_meta($postId, 'speechkit_error_message');
        delete_post_meta($postId, 'beyondwords_error_message');

        // Log the request URL and args for debugging
        // (these are removed for successful requests)
        update_post_meta($postId, 'beyondwords_request_url', $request->getUrl());
        update_post_meta($postId, 'beyondwords_request_args', var_export($args, true)); // phpcs:ignore

        $response = wp_remote_request($request->getUrl(), $args);

        // WordPress error performing API call
        if (is_wp_error($response)) {
            $errorMessage = $response->get_error_message();

            return $this->error($postId, $errorMessage, $response->get_error_code());
        }

        $responseCode = wp_remote_retrieve_response_code($response);

        $responseBody = wp_remote_retrieve_body($response);
        $responseBody = json_decode($responseBody, true);

        // Response had a HTTP error code (3XX, 4XX, 5XX)
        if ($responseCode > 299) {
            if (is_array($responseBody) && array_key_exists('message', $responseBody)) {
                $errorMessage = $responseBody['message'];
            } else {
                $errorMessage = wp_remote_retrieve_response_message($response);
            }

            if (! $errorMessage) {
                $errorMessage = sprintf(
                    /* translators: %s is replaced with the support email link */
                    esc_html__('API request error. Please contact %s.', 'speechkit'),
                    '<a href="mailto:support@beyondwords.io">support@beyondwords.io</a>'
                );
            }

            return $this->error($postId, $errorMessage, $responseCode);
        }

        // Response was invalid JSON
        if (json_last_error() !== JSON_ERROR_NONE) {
            $errorMessage = sprintf(
                /* translators: %s is replaced with the reason that JSON parsing failed */
                __('Unable to parse JSON in BeyondWords API response. Reason: %s.', 'speechkit'),
                // Don't allow any tags
                wp_kses(json_last_error_msg(), [])
            );

            return $this->error($postId, $errorMessage, 500);
        }

        // Success, so remove request URL and args log
        delete_post_meta($postId, 'beyondwords_request_url');
        delete_post_meta($postId, 'beyondwords_request_args');

        return $responseBody;
    }

    /**
     * Handle API Error.
     *
     * @since 3.0.0
     * @since 4.0.0 Removed hash comparison and display 403 errors.
     *
     * @param int    $postId  Post ID.
     * @param string $message Error Message.
     * @param int    $code    Error Code.
     *
     * @throws \Exception
     */
    public function error($postId, $message, $code = 0)
    {
        $error = sprintf(self::ERROR_FORMAT, $code, $message);

        // Log the error message for this Post in the db
        update_post_meta($postId, 'beyondwords_error_message', $error);

        return false;
    }

    /**
     * Get error message.
     *
     * @since 3.0.0
     *
     * @param error
     *
     * @return string
     */
    public function getErrorMessage($error)
    {
        return $error['message'];
    }

    /**
     * Print admin notices.
     *
     * @since 3.0.0
     *
     * @return void
     */
    public function adminNotices()
    {
        $screen = get_current_screen();

        // Only add for enabled Posts screen
        $postTypes = SettingsUtils::getSupportedPostTypes();

        if (! in_array($screen->id, $postTypes)) {
            return;
        }

        $errorMessage = PostMetaUtils::getErrorMessage(get_the_ID());

        if (!$errorMessage) {
            return;
        }

        ?>
        <div class="notice notice-error">
            <p>
                <span class="dashicons dashicons-controls-volumeon"></span>
                <?php echo esc_html($errorMessage); ?>
            </p>
        </div>
        <?php
    }
}

```
