/**
  * Uses the Brightcove oAuth API to retrieve and store an access key for use with requests. The token is stored as a transient
  * with an expiration time matching that which is returned from Brightcove. The call to the API is only performed if that transient
  * is invalid or expired. Return a WP_Error object for use in WordPress in the case of failure.
  *
  * @since  1.0.0
  *
  * @see    BC_Utility::get_cache_item()
  * @see    set_transient()
  * @see    BC_Utility::delete_cache_item()
  * @see    wp_remote_post()
  *
  * @param bool $force_new_token whether or not to obtain a new OAuth token
  * @param bool $retry           true to retry on failure or false
  *
  * @return string|WP_Error
  */
 public function _request_access_token($force_new_token = false, $retry = true)
 {
     $transient_name = $this->transient_name;
     $token = $force_new_token ? false : BC_Utility::get_cache_item($transient_name);
     if (!$token) {
         $endpoint = esc_url_raw(self::ENDPOINT_BASE . '/access_token?grant_type=client_credentials');
         $request = wp_remote_post($endpoint, $this->_http_headers);
         if ('400' == wp_remote_retrieve_response_code($request)) {
             // Just in case
             BC_Utility::delete_cache_item($transient_name);
             $oauth_error = new WP_Error('oauth_access_token_failure', sprintf(__('There is a problem with your Brightcove %1$s or %2$s', 'brightcove'), '<code>client_id</code>', '<code>client_secret</code>'));
             BC_Logging::log(sprintf('BC OAUTH ERROR: %s', $oauth_error->get_error_message()));
             return $oauth_error;
         }
         $body = wp_remote_retrieve_body($request);
         $data = json_decode($body);
         if (isset($data->access_token)) {
             $token = $data->access_token;
             BC_Utility::set_cache_item($transient_name, 'oauth', $token, $data->expires_in);
         } else {
             if (!$retry) {
                 return new WP_Error('oauth_access_token_response_failure', sprintf(esc_html__('oAuth API did not return us an access token', 'brightcove')));
             }
             return $this->_request_access_token($force_new_token, false);
         }
     }
     return $token;
 }
 /**
  * Provides the handler for saving/updating source data
  *
  * @return bool/WP_Error
  */
 public function save_account()
 {
     global $bc_accounts;
     if (!isset($_POST['brightcove-check_oauth'])) {
         return false;
     }
     if (!current_user_can('brightcove_manipulate_accounts')) {
         $error_message = esc_html__('You do not have permission to manage this account.', 'brightcove');
         BC_Logging::log(sprintf('ACCOUNT: %s', $error_message));
         $this->notices[] = array('message' => $error_message, 'type' => 'error');
         return new WP_Error('brightcove-account-manage-permissions', $error_message);
     }
     if (!wp_verify_nonce($_POST['brightcove-check_oauth'], '_brightcove_check_oauth_for_source')) {
         return false;
     }
     // Only go through the oAuth credential validation when we're adding a new account or editing the account's credentials (not default players etc)
     if ('create' === $_POST['source-action']) {
         $required_keys = array('brightcove-check_oauth', 'source-account-id', 'source-client-id', 'source-client-secret', 'source-name');
         foreach ($required_keys as $key) {
             if (!array_key_exists($key, $_POST)) {
                 return false;
             }
         }
         $account_id = BC_Utility::sanitize_id($_POST['source-account-id']);
         $client_id = sanitize_text_field($_POST['source-client-id']);
         $client_secret = BC_Utility::get_sanitized_client_secret($_POST['source-client-secret']);
         $account_name = sanitize_text_field(stripslashes_deep($_POST['source-name']));
         $set_default = isset($_POST['source-default-account']) && 'on' === $_POST['source-default-account'] ? 'default' : '';
         $hash = BC_Utility::get_hash_for_account(array('account_id' => $account_id, 'client_id' => $client_id, 'client_secret' => $client_secret));
         $account = $bc_accounts->get_account_by_hash($hash);
         if ($account) {
             // Account already exists.
             $error_message = esc_html__('The Brightcove credentials provided already exist.', 'brightcove');
             BC_Logging::log(sprintf('BC ACCOUNTS: %s', $error_message));
             $this->notices[] = array('message' => $error_message, 'type' => 'error');
             return new WP_Error('bc-account-exists-error', $error_message);
         }
         if (!$bc_accounts->add_account($account_id, $client_id, $client_secret, $account_name, $set_default, false)) {
             $error_message = esc_html__('We could not authenticate your credentials with Brightcove', 'brightcove');
             BC_Logging::log(sprintf('BC OAUTH ERROR: %s', $error_message));
             $this->notices[] = array('message' => $error_message, 'type' => 'error');
             return new WP_Error('bc-oauth-error', $error_message);
         }
         BC_Utility::delete_cache_item('*');
         $bc_accounts->set_current_account_by_id($account_id);
     }
     if ('update' === $_POST['source-action']) {
         if (isset($_POST['source-default-account']) && 'on' === $_POST['source-default-account']) {
             update_option('_brightcove_default_account', sanitize_text_field($_POST['hash']));
         }
     }
     // Deleting transient to allow syncing from the new account, otherwise we won't be able to sync it until this transient expires.
     BC_Utility::delete_cache_item('brightcove_sync_videos');
     $this->notices[] = array('message' => sprintf('%s <a href="%s">%s</a>.', esc_html__('Congratulations! Your credentials have been authenticated. Return to', 'brightcove'), admin_url('admin.php?page=brightcove-sources '), esc_html__('Settings', 'brightcove')), 'type' => 'updated');
     BC_Utility::delete_cache_item('*');
     return true;
 }
 /**
  * When an API call hits our server, automatically flush cached Brightcove information
  *
  * This method is meant to be invoked
  * - Whenever a Dynamic Ingest request completes
  * - Whenever a video is updated on the server
  */
 public static function flush_cache()
 {
     BC_Utility::delete_cache_item('*');
 }
 /**
  * Delete video or playlist
  *
  * Process call to delete video or playlist which is sent to the Brightcove API
  *
  * @since 1.0
  *
  * @return void
  */
 public function bc_ajax_delete_video_or_playlist()
 {
     global $bc_accounts;
     // Call this to check if we are allowed to continue.
     $this->bc_helper_check_ajax();
     $type = sanitize_key($_POST['type']);
     $type_msg = '';
     $id = BC_Utility::sanitize_id($_POST['id']);
     // Get type brightcove-playlist or brightcove-video.
     if (!in_array($type, array('playlists', 'videos'))) {
         wp_send_json_error(esc_html__('Type is not specified!', 'brightcove'));
     }
     // Try to get the existing post based on id.
     if ('playlists' === $type) {
         // Get playlist.
         $type_msg = 'playlist';
     } elseif ('videos' === $type) {
         // Find existing video.
         $type_msg = 'video';
     } else {
         wp_send_json_error(esc_html__('Wrong type is specified!', 'brightcove'));
     }
     $hash = sanitize_text_field($_POST['account']);
     if (false === $bc_accounts->get_account_by_hash($hash)) {
         wp_send_json_error(__('No such account exists', 'brightcove'));
     }
     $bc_accounts->set_current_account($hash);
     // Remove from Brightcove.
     $delete_status = false;
     $delete_message = '';
     if ('videos' === $type) {
         $delete_status = $this->cms_api->video_delete($id);
         if (!$delete_status) {
             // We were not able to delete video from Brightcove.
             $delete_message = esc_html__('Unable to remove video from Brightcove!', 'brightcove');
         } else {
             $delete_message = esc_html__('Successfully deleted your video.', 'brightcove');
         }
     } elseif ('playlists' === $type) {
         $delete_status = $this->cms_api->playlist_delete($id);
         if (!$delete_status) {
             // We were not able to delete playlist from Brightcove.
             $delete_message = esc_html__('Unable to remove playlist from Brightcove!', 'brightcove');
         } else {
             $delete_message = esc_html__('Successfully deleted your playlist.', 'brightcove');
         }
     }
     BC_Utility::delete_cache_item('*');
     $bc_accounts->restore_default_account();
     if ($delete_status) {
         wp_send_json_success($delete_message);
     } else {
         wp_send_json_error($delete_message);
     }
 }