| @@ -21,9 +21,9 @@ | ||
| 21 | 21 | * Holds the base class object. |
| 22 | 22 | * |
| 23 | 23 | * @since 3.4.7 |
| 24 | 24 | * |
| 25 | - * @var object. | |
| 25 | + * @var object | |
| 26 | 26 | */ |
| 27 | 27 | public $base; |
| 28 | 28 | |
| 29 | 29 | /** |
| @@ -30,9 +30,9 @@ | ||
| 30 | 30 | * Holds the Buffer Application's Client ID |
| 31 | 31 | * |
| 32 | 32 | * @since 3.3.3 |
| 33 | 33 | * |
| 34 | - * @var string. | |
| 34 | + * @var string | |
| 35 | 35 | */ |
| 36 | 36 | private $client_id = 'd1Lk26lma4iEgb-20v1BWmdKrlopiGwP9pu9ri7JG0e'; |
| 37 | 37 | |
| 38 | 38 | /** |
| @@ -39,9 +39,9 @@ | ||
| 39 | 39 | * Holds the oAuth Authorize URL |
| 40 | 40 | * |
| 41 | 41 | * @since 6.0.0 |
| 42 | 42 | * |
| 43 | - * @var string. | |
| 43 | + * @var string | |
| 44 | 44 | */ |
| 45 | 45 | private $oauth_authorize_url = 'https://auth.buffer.com/'; |
| 46 | 46 | |
| 47 | 47 | /** |
| @@ -48,27 +48,18 @@ | ||
| 48 | 48 | * Holds the oAuth Gateway endpoint, used to exchange a code for an access token |
| 49 | 49 | * |
| 50 | 50 | * @since 3.3.3 |
| 51 | 51 | * |
| 52 | - * @var string. | |
| 52 | + * @var string | |
| 53 | 53 | */ |
| 54 | 54 | private $redirect_uri = 'https://www.wpzinc.com/?oauth=bufferv2'; |
| 55 | 55 | |
| 56 | 56 | /** |
| 57 | - * Holds the Proxy endpoint, which might be used to pass requests through | |
| 58 | - * | |
| 59 | - * @since 4.2.1 | |
| 60 | - * | |
| 61 | - * @var string. | |
| 62 | - */ | |
| 63 | - private $proxy_endpoint = 'https://proxy.wpzinc.net/'; | |
| 64 | - | |
| 65 | - /** | |
| 66 | 57 | * Holds the API endpoint |
| 67 | 58 | * |
| 68 | 59 | * @since 3.4.7 |
| 69 | 60 | * |
| 70 | - * @var string. | |
| 61 | + * @var string | |
| 71 | 62 | */ |
| 72 | 63 | private $api_endpoint = 'https://api.buffer.com/'; |
| 73 | 64 | |
| 74 | 65 | /** |
| @@ -93,9 +84,9 @@ | ||
| 93 | 84 | * Token Expiry Timestamp |
| 94 | 85 | * |
| 95 | 86 | * @since 3.5.0 |
| 96 | 87 | * |
| 97 | - * @var int | |
| 88 | + * @var int|bool | |
| 98 | 89 | */ |
| 99 | 90 | public $token_expires = false; |
| 100 | 91 | |
| 101 | 92 | /** |
| @@ -125,9 +116,9 @@ | ||
| 125 | 116 | ?> |
| 126 | 117 | <div class="wpzinc-option"> |
| 127 | 118 | <div class="full"> |
| 128 | 119 | <a href="<?php echo esc_attr( $this->get_oauth_url() ); ?>" class="button button-primary"> |
| 129 | - <?php esc_html_e( 'Connect a Buffer Account', 'wp-to-buffer' ); ?> | |
| 120 | + <?php esc_html_e( 'Connect an additional Buffer Account', 'wp-to-buffer' ); ?> | |
| 130 | 121 | </a> |
| 131 | 122 | </div> |
| 132 | 123 | </div> |
| 133 | 124 | <?php |
| @@ -340,8 +331,13 @@ | ||
| 340 | 331 | * @param bool|int $token_expires Token Expiry. |
| 341 | 332 | */ |
| 342 | 333 | public function set_tokens( $access_token = '', $refresh_token = '', $token_expires = false ) { |
| 343 | 334 | |
| 335 | + $this->base->get_class( 'log' )->add_to_debug_log( 'Buffer API: set_tokens(): Started.' ); | |
| 336 | + $this->base->get_class( 'log' )->add_to_debug_log( 'Buffer API: set_tokens(): access_token = ' . $access_token ); | |
| 337 | + $this->base->get_class( 'log' )->add_to_debug_log( 'Buffer API: set_tokens(): refresh_token = ' . $refresh_token ); | |
| 338 | + $this->base->get_class( 'log' )->add_to_debug_log( 'Buffer API: set_tokens(): token_expires = ' . $token_expires ); | |
| 339 | + | |
| 344 | 340 | $this->access_token = $access_token; |
| 345 | 341 | $this->refresh_token = $refresh_token; |
| 346 | 342 | $this->token_expires = $token_expires; |
| 347 | 343 | |
| @@ -352,9 +348,9 @@ | ||
| 352 | 348 | * |
| 353 | 349 | * @since 6.0.0 |
| 354 | 350 | * |
| 355 | 351 | * @param string $authorization_code Authorization Code, returned from get_oauth_url() flow. |
| 356 | - * @return WP_Error|array | |
| 352 | + * @return \WP_Error|array | |
| 357 | 353 | */ |
| 358 | 354 | public function get_access_token( $authorization_code ) { |
| 359 | 355 | |
| 360 | 356 | $result = $this->oauth_request( |
| @@ -397,18 +393,30 @@ | ||
| 397 | 393 | * @since 2.0.0 |
| 398 | 394 | */ |
| 399 | 395 | public function refresh_token() { |
| 400 | 396 | |
| 401 | - // Bail if no refresh token is available to use, otherwise we'll | |
| 402 | - // send a request to Buffer with an empty refresh_token, which | |
| 403 | - // will fail. | |
| 397 | + $this->base->get_class( 'log' )->add_to_debug_log( 'Buffer API: refresh_token(): Started.' ); | |
| 398 | + | |
| 399 | + // Bail if we don't have a refresh token. | |
| 404 | 400 | if ( empty( $this->refresh_token ) ) { |
| 405 | - return new \WP_Error( | |
| 406 | - $this->base->plugin->filter_name . '_api_refresh_token_error', | |
| 407 | - __( 'No refresh token available; cannot refresh access token.', 'wp-to-buffer' ) | |
| 408 | - ); | |
| 401 | + $this->base->get_class( 'log' )->add_to_debug_log( 'Buffer API: refresh_token(): Error: No refresh token available; cannot refresh.' ); | |
| 402 | + return new \WP_Error( 'missing_refresh_token', __( 'No refresh token exists', 'wp-to-buffer' ) ); | |
| 409 | 403 | } |
| 410 | 404 | |
| 405 | + $this->base->get_class( 'log' )->add_to_debug_log( 'Buffer API: refresh_token(): access_token = ' . $this->access_token ); | |
| 406 | + $this->base->get_class( 'log' )->add_to_debug_log( 'Buffer API: refresh_token(): refresh_token = ' . $this->refresh_token ); | |
| 407 | + $this->base->get_class( 'log' )->add_to_debug_log( 'Buffer API: refresh_token(): token_expires = ' . $this->token_expires ); | |
| 408 | + $this->base->get_class( 'log' )->add_to_debug_log( 'Buffer API: refresh_token(): token_expires = ' . ( $this->token_expires && time() > (int) $this->token_expires ? 'expired ' . ( time() - (int) $this->token_expires ) . 's ago' : 'expires in ' . ( (int) $this->token_expires - time() ) . 's' ) ); | |
| 409 | + | |
| 410 | + // Bail if the access token hasn't yet expired. | |
| 411 | + if ( strtotime( '+15 minutes' ) < $this->token_expires ) { | |
| 412 | + $this->base->get_class( 'log' )->add_to_debug_log( 'Buffer API: refresh_token(): Skipped: Access token not yet within the 15 minute refresh window.' ); | |
| 413 | + return false; | |
| 414 | + } | |
| 415 | + | |
| 416 | + $this->base->get_class( 'log' )->add_to_debug_log( 'Buffer API: refresh_token(): Requesting new access token.' ); | |
| 417 | + | |
| 418 | + // Send request. | |
| 411 | 419 | $result = $this->oauth_request( |
| 412 | 420 | $this->oauth_authorize_url . 'token', |
| 413 | 421 | array( |
| 414 | 422 | 'client_id' => $this->client_id, |
| @@ -418,14 +426,16 @@ | ||
| 418 | 426 | ); |
| 419 | 427 | |
| 420 | 428 | // If an error occured, log and return it now. |
| 421 | 429 | if ( is_wp_error( $result ) ) { |
| 430 | + $this->base->get_class( 'log' )->add_to_debug_log( sprintf( 'Buffer API: refresh_token(): Error: [%s] %s', $result->get_error_code(), $result->get_error_message() ) ); | |
| 431 | + | |
| 422 | 432 | /** |
| 423 | 433 | * Perform any actions when refreshing an expired access token fails. |
| 424 | 434 | * |
| 425 | 435 | * @since 6.0.0 |
| 426 | 436 | * |
| 427 | - * @param WP_Error $result Error from API. | |
| 437 | + * @param \WP_Error $result Error from API. | |
| 428 | 438 | * @param string $client_id OAuth Client ID. |
| 429 | 439 | * @param string $access_token Access Token. |
| 430 | 440 | * @param string $refresh_token Refresh Token. |
| 431 | 441 | */ |
| @@ -440,8 +450,14 @@ | ||
| 440 | 450 | 'refresh_token' => $result['refresh_token'], |
| 441 | 451 | 'token_expires' => strtotime( '+' . $result['expires_in'] . ' seconds' ), |
| 442 | 452 | ); |
| 443 | 453 | |
| 454 | + $this->base->get_class( 'log' )->add_to_debug_log( 'Buffer API: refresh_token(): Success' ); | |
| 455 | + $this->base->get_class( 'log' )->add_to_debug_log( 'Buffer API: refresh_token(): New access_token = ' . $result['access_token'] ); | |
| 456 | + $this->base->get_class( 'log' )->add_to_debug_log( 'Buffer API: refresh_token(): New refresh_token = ' . $result['refresh_token'] ); | |
| 457 | + $this->base->get_class( 'log' )->add_to_debug_log( 'Buffer API: refresh_token(): New token_expires = ' . $result['token_expires'] ); | |
| 458 | + $this->base->get_class( 'log' )->add_to_debug_log( 'Buffer API: refresh_token(): New token_expires = ' . ( $result['token_expires'] && time() > (int) $result['token_expires'] ? 'expired ' . ( time() - (int) $result['token_expires'] ) . 's ago' : 'expires in ' . ( (int) $result['token_expires'] - time() ) . 's' ) ); | |
| 459 | + | |
| 444 | 460 | /** |
| 445 | 461 | * Perform any actions with the new access token, such as saving it. |
| 446 | 462 | * |
| 447 | 463 | * @since 6.0.0 |
| @@ -467,9 +483,9 @@ | ||
| 467 | 483 | * @since 6.0.1 |
| 468 | 484 | * |
| 469 | 485 | * @param bool $force Force API call (false = use stored option). |
| 470 | 486 | * |
| 471 | - * @return WP_Error|array | |
| 487 | + * @return \WP_Error|array | |
| 472 | 488 | */ |
| 473 | 489 | public function organizations( $force = false ) { |
| 474 | 490 | |
| 475 | 491 | // Return stored organizations from the non-autoloaded option, unless |
| @@ -529,9 +545,9 @@ | ||
| 529 | 545 | * |
| 530 | 546 | * @since 6.0.0 |
| 531 | 547 | * |
| 532 | 548 | * @param string $account_id Account ID. |
| 533 | - * @return WP_Error|array | |
| 549 | + * @return \WP_Error|array | |
| 534 | 550 | */ |
| 535 | 551 | public function account( $account_id = '' ) { |
| 536 | 552 | |
| 537 | 553 | $organizations = $this->organizations( false ); |
| @@ -560,9 +576,9 @@ | ||
| 560 | 576 | * @since 3.0.0 |
| 561 | 577 | * |
| 562 | 578 | * @param bool $force Force API call (false = use stored option). |
| 563 | 579 | * @param string $account_id Account ID. |
| 564 | - * @return WP_Error|array | |
| 580 | + * @return \WP_Error|array | |
| 565 | 581 | */ |
| 566 | 582 | public function profiles( $force = false, $account_id = 'default' ) { |
| 567 | 583 | |
| 568 | 584 | // Return stored profiles if available and not forcing a refresh. |
| @@ -568,11 +584,14 @@ | ||
| 568 | 584 | // Return stored profiles if available and not forcing a refresh. |
| 569 | 585 | $option_name = $this->base->plugin->name . '-profiles-' . $account_id; |
| 570 | 586 | $profiles = get_option( $option_name ); |
| 571 | 587 | if ( ! $force && is_array( $profiles ) ) { |
| 588 | + $this->base->get_class( 'log' )->add_to_debug_log( sprintf( 'Buffer API: profiles(): account=%s: returning %d cached profile(s).', $account_id, count( $profiles ) ) ); | |
| 572 | 589 | return $profiles; |
| 573 | 590 | } |
| 574 | 591 | |
| 592 | + $this->base->get_class( 'log' )->add_to_debug_log( sprintf( 'Buffer API: profiles(): account=%s: fetching profiles from Buffer (force=%s).', $account_id, $force ? 'yes' : 'no' ) ); | |
| 593 | + | |
| 575 | 594 | // Build GraphQL query. |
| 576 | 595 | $query = ' |
| 577 | 596 | query GetChannels($organizationId: OrganizationId!) { |
| 578 | 597 | channels(input: { organizationId: $organizationId }) { |
| @@ -603,8 +622,9 @@ | ||
| 603 | 622 | ); |
| 604 | 623 | |
| 605 | 624 | // Check for errors. |
| 606 | 625 | if ( is_wp_error( $results ) ) { |
| 626 | + $this->base->get_class( 'log' )->add_to_debug_log( sprintf( 'Buffer API: profiles(): account=%s: FAILED to fetch profiles: [%s] %s', $account_id, $results->get_error_code(), $results->get_error_message() ) ); | |
| 607 | 627 | return $results; |
| 608 | 628 | } |
| 609 | 629 | |
| 610 | 630 | // Build profiles array from results. |
| @@ -647,9 +667,9 @@ | ||
| 647 | 667 | * |
| 648 | 668 | * @since 6.0.0 |
| 649 | 669 | * |
| 650 | 670 | * @param string $post_id Post ID. |
| 651 | - * @return WP_Error|array | |
| 671 | + * @return \WP_Error|array | |
| 652 | 672 | */ |
| 653 | 673 | public function get_post( $post_id ) { |
| 654 | 674 | |
| 655 | 675 | $query = ' |
| @@ -693,9 +713,9 @@ | ||
| 693 | 713 | * @since 3.0.0 |
| 694 | 714 | * |
| 695 | 715 | * @param array $params Params. |
| 696 | 716 | * @param string $service Service. |
| 697 | - * @return WP_Error|array | |
| 717 | + * @return \WP_Error|array | |
| 698 | 718 | */ |
| 699 | 719 | public function updates_create( $params, $service ) { |
| 700 | 720 | |
| 701 | 721 | // Build GraphQL variables. |
| @@ -751,9 +771,9 @@ | ||
| 751 | 771 | switch ( $service ) { |
| 752 | 772 | |
| 753 | 773 | case 'instagram': |
| 754 | 774 | $metadata = array( |
| 755 | - 'type' => $params['post_type'] === 'story' ? 'story' : 'post', | |
| 775 | + 'type' => in_array( $params['post_type'], array( 'story', 'video_story' ), true ) ? 'story' : 'post', | |
| 756 | 776 | 'shouldShareToFeed' => true, |
| 757 | 777 | ); |
| 758 | 778 | |
| 759 | 779 | // First Comment. |
| @@ -759,8 +779,13 @@ | ||
| 759 | 779 | // First Comment. |
| 760 | 780 | if ( ! empty( $params['first_comment'] ) ) { |
| 761 | 781 | $metadata['firstComment'] = $params['first_comment']; |
| 762 | 782 | } |
| 783 | + | |
| 784 | + // Shop Grid Link. | |
| 785 | + if ( ! empty( $params['url'] ) ) { | |
| 786 | + $metadata['link'] = $params['url']; | |
| 787 | + } | |
| 763 | 788 | break; |
| 764 | 789 | |
| 765 | 790 | case 'facebook': |
| 766 | 791 | $metadata = array( |
| @@ -773,14 +798,10 @@ | ||
| 773 | 798 | } |
| 774 | 799 | |
| 775 | 800 | // OpenGraph / Link Attachment. |
| 776 | 801 | if ( $params['post_type'] === 'link' && ! empty( $params['url'] ) ) { |
| 777 | - $assets = array( | |
| 778 | - array( | |
| 779 | - 'link' => array( | |
| 780 | - 'url' => $params['url'], | |
| 781 | - ), | |
| 782 | - ), | |
| 802 | + $metadata['linkAttachment'] = array( | |
| 803 | + 'url' => $params['url'], | |
| 783 | 804 | ); |
| 784 | 805 | } |
| 785 | 806 | |
| 786 | 807 | // Annotations. |
| @@ -796,14 +817,10 @@ | ||
| 796 | 817 | } |
| 797 | 818 | |
| 798 | 819 | // OpenGraph / Link Attachment. |
| 799 | 820 | if ( $params['post_type'] === 'link' && ! empty( $params['url'] ) ) { |
| 800 | - $assets = array( | |
| 801 | - array( | |
| 802 | - 'link' => array( | |
| 803 | - 'url' => $params['url'], | |
| 804 | - ), | |
| 805 | - ), | |
| 821 | + $metadata['linkAttachment'] = array( | |
| 822 | + 'url' => $params['url'], | |
| 806 | 823 | ); |
| 807 | 824 | } |
| 808 | 825 | |
| 809 | 826 | // Annotations. |
| @@ -814,13 +831,11 @@ | ||
| 814 | 831 | |
| 815 | 832 | case 'twitter': |
| 816 | 833 | // First Comment. |
| 817 | 834 | if ( ! empty( $params['first_comment'] ) ) { |
| 818 | - $metadata = array( | |
| 819 | - 'thread' => array( | |
| 820 | - array( | |
| 821 | - 'text' => $params['first_comment'], | |
| 822 | - ), | |
| 835 | + $metadata['thread'] = array( | |
| 836 | + array( | |
| 837 | + 'text' => $params['first_comment'], | |
| 823 | 838 | ), |
| 824 | 839 | ); |
| 825 | 840 | } |
| 826 | 841 | |
| @@ -878,24 +893,18 @@ | ||
| 878 | 893 | |
| 879 | 894 | case 'threads': |
| 880 | 895 | // OpenGraph / Link Attachment. |
| 881 | 896 | if ( $params['post_type'] === 'link' && ! empty( $params['url'] ) ) { |
| 882 | - $assets = array( | |
| 883 | - array( | |
| 884 | - 'link' => array( | |
| 885 | - 'url' => $params['url'], | |
| 886 | - ), | |
| 887 | - ), | |
| 897 | + $metadata['linkAttachment'] = array( | |
| 898 | + 'url' => $params['url'], | |
| 888 | 899 | ); |
| 889 | 900 | } |
| 890 | 901 | |
| 891 | 902 | // First Comment. |
| 892 | 903 | if ( ! empty( $params['first_comment'] ) ) { |
| 893 | - $metadata = array( | |
| 894 | - 'thread' => array( | |
| 895 | - array( | |
| 896 | - 'text' => $params['first_comment'], | |
| 897 | - ), | |
| 904 | + $metadata['thread'] = array( | |
| 905 | + array( | |
| 906 | + 'text' => $params['first_comment'], | |
| 898 | 907 | ), |
| 899 | 908 | ); |
| 900 | 909 | } |
| 901 | 910 | break; |
| @@ -902,24 +911,18 @@ | ||
| 902 | 911 | |
| 903 | 912 | case 'bluesky': |
| 904 | 913 | // OpenGraph / Link Attachment. |
| 905 | 914 | if ( $params['post_type'] === 'link' && ! empty( $params['url'] ) ) { |
| 906 | - $assets = array( | |
| 907 | - array( | |
| 908 | - 'link' => array( | |
| 909 | - 'url' => $params['url'], | |
| 910 | - ), | |
| 911 | - ), | |
| 915 | + $metadata['linkAttachment'] = array( | |
| 916 | + 'url' => $params['url'], | |
| 912 | 917 | ); |
| 913 | 918 | } |
| 914 | 919 | |
| 915 | 920 | // First Comment. |
| 916 | 921 | if ( ! empty( $params['first_comment'] ) ) { |
| 917 | - $metadata = array( | |
| 918 | - 'thread' => array( | |
| 919 | - array( | |
| 920 | - 'text' => $params['first_comment'], | |
| 921 | - ), | |
| 922 | + $metadata['thread'] = array( | |
| 923 | + array( | |
| 924 | + 'text' => $params['first_comment'], | |
| 922 | 925 | ), |
| 923 | 926 | ); |
| 924 | 927 | } |
| 925 | 928 | break; |
| @@ -926,13 +929,11 @@ | ||
| 926 | 929 | |
| 927 | 930 | case 'mastodon': |
| 928 | 931 | // First Comment. |
| 929 | 932 | if ( ! empty( $params['first_comment'] ) ) { |
| 930 | - $metadata = array( | |
| 931 | - 'thread' => array( | |
| 932 | - array( | |
| 933 | - 'text' => $params['first_comment'], | |
| 934 | - ), | |
| 933 | + $metadata['thread'] = array( | |
| 934 | + array( | |
| 935 | + 'text' => $params['first_comment'], | |
| 935 | 936 | ), |
| 936 | 937 | ); |
| 937 | 938 | } |
| 938 | 939 | |
| @@ -973,18 +974,31 @@ | ||
| 973 | 974 | 'image' => array( |
| 974 | 975 | 'url' => $media['image'], |
| 975 | 976 | 'thumbnailUrl' => $media['thumbnail'], |
| 976 | 977 | 'metadata' => array( |
| 977 | - 'altText' => $media['alt_text'], | |
| 978 | - 'dimensions' => array( | |
| 979 | - 'width' => $media['width'], | |
| 980 | - 'height' => $media['height'], | |
| 981 | - ), | |
| 978 | + 'altText' => $media['alt_text'], | |
| 982 | 979 | ), |
| 983 | 980 | ), |
| 984 | 981 | ); |
| 985 | 982 | } |
| 986 | 983 | break; |
| 984 | + | |
| 985 | + case 'video': | |
| 986 | + case 'video_story': | |
| 987 | + // Bail if no video URL is defined. | |
| 988 | + if ( empty( $params['video_url'] ) ) { | |
| 989 | + break; | |
| 990 | + } | |
| 991 | + | |
| 992 | + // Buffer fetches the video from a public URL, so we only send the URL. | |
| 993 | + $assets = array( | |
| 994 | + array( | |
| 995 | + 'video' => array( | |
| 996 | + 'url' => $params['video_url'], | |
| 997 | + ), | |
| 998 | + ), | |
| 999 | + ); | |
| 1000 | + break; | |
| 987 | 1001 | } |
| 988 | 1002 | |
| 989 | 1003 | // Include assets. Always overwrites the default empty array |
| 990 | 1004 | // initialised above, if the service branch built any. |
| @@ -1061,9 +1075,9 @@ | ||
| 1061 | 1075 | * @since 3.0.0 |
| 1062 | 1076 | * |
| 1063 | 1077 | * @param string $url URL. |
| 1064 | 1078 | * @param array $params Parameters (optional). |
| 1065 | - * @return WP_Error|array | |
| 1079 | + * @return \WP_Error|array | |
| 1066 | 1080 | */ |
| 1067 | 1081 | private function oauth_request( $url, $params = array() ) { |
| 1068 | 1082 | |
| 1069 | 1083 | // Send request. |
| @@ -1100,13 +1114,40 @@ | ||
| 1100 | 1114 | * @since 6.0.0 |
| 1101 | 1115 | * |
| 1102 | 1116 | * @param string $query GraphQL Query. |
| 1103 | 1117 | * @param array $variables GraphQL Variables. |
| 1104 | - * @param bool $is_retry Whether this is a retry following a token refresh. | |
| 1105 | - * @return WP_Error|array | |
| 1118 | + * @return \WP_Error|array | |
| 1106 | 1119 | */ |
| 1107 | - private function graphql_query( $query, $variables = array(), $is_retry = false ) { | |
| 1120 | + private function graphql_query( $query, $variables = array() ) { | |
| 1108 | 1121 | |
| 1122 | + $this->base->get_class( 'log' )->add_to_debug_log( 'Buffer API: graphql_query(): Started.' ); | |
| 1123 | + $this->base->get_class( 'log' )->add_to_debug_log( 'Buffer API: graphql_query(): query = ' . $query ); | |
| 1124 | + $this->base->get_class( 'log' )->add_to_debug_log( 'Buffer API: graphql_query(): variables = ' . print_r( $variables, true ) ); // phpcs:ignore WordPress.PHP.DevelopmentFunctions.error_log_print_r | |
| 1125 | + $this->base->get_class( 'log' )->add_to_debug_log( 'Buffer API: graphql_query(): access_token = ' . $this->access_token ); | |
| 1126 | + $this->base->get_class( 'log' )->add_to_debug_log( 'Buffer API: graphql_query(): refresh_token = ' . $this->refresh_token ); | |
| 1127 | + $this->base->get_class( 'log' )->add_to_debug_log( 'Buffer API: graphql_query(): token_expires = ' . $this->token_expires ); | |
| 1128 | + $this->base->get_class( 'log' )->add_to_debug_log( 'Buffer API: graphql_query(): token_expires = ' . ( $this->token_expires && time() > (int) $this->token_expires ? 'expired ' . ( time() - (int) $this->token_expires ) . 's ago' : 'expires in ' . ( (int) $this->token_expires - time() ) . 's' ) ); | |
| 1129 | + | |
| 1130 | + // Check required parameters exist. | |
| 1131 | + if ( empty( $this->access_token ) ) { | |
| 1132 | + $this->base->get_class( 'log' )->add_to_debug_log( 'Buffer API: graphql_query(): Error: No access token was specified' ); | |
| 1133 | + return new \WP_Error( 'missing_access_token', __( 'No access token was specified', 'wp-to-buffer' ) ); | |
| 1134 | + } | |
| 1135 | + | |
| 1136 | + // Fetch a new access token and refresh token. | |
| 1137 | + $result = $this->refresh_token(); | |
| 1138 | + | |
| 1139 | + // Bail if something went wrong. | |
| 1140 | + if ( is_wp_error( $result ) ) { | |
| 1141 | + $this->base->get_class( 'log' )->add_to_debug_log( 'Buffer API: graphql_query(): Error: ' . $result->get_error_message() ); | |
| 1142 | + return $result; | |
| 1143 | + } | |
| 1144 | + | |
| 1145 | + $this->base->get_class( 'log' )->add_to_debug_log( 'Buffer API: graphql_query(): access_token = ' . $this->access_token ); | |
| 1146 | + $this->base->get_class( 'log' )->add_to_debug_log( 'Buffer API: graphql_query(): refresh_token = ' . $this->refresh_token ); | |
| 1147 | + $this->base->get_class( 'log' )->add_to_debug_log( 'Buffer API: graphql_query(): token_expires = ' . $this->token_expires ); | |
| 1148 | + $this->base->get_class( 'log' )->add_to_debug_log( 'Buffer API: graphql_query(): token_expires = ' . ( $this->token_expires && time() > (int) $this->token_expires ? 'expired ' . ( time() - (int) $this->token_expires ) . 's ago' : 'expires in ' . ( (int) $this->token_expires - time() ) . 's' ) ); | |
| 1149 | + | |
| 1109 | 1150 | // Build body. |
| 1110 | 1151 | $body = array( 'query' => $query ); |
| 1111 | 1152 | if ( ! empty( $variables ) ) { |
| 1112 | 1153 | $body['variables'] = $variables; |
| @@ -1124,41 +1165,22 @@ | ||
| 1124 | 1165 | ); |
| 1125 | 1166 | |
| 1126 | 1167 | // If an error occured, return it now. |
| 1127 | 1168 | if ( is_wp_error( $result ) ) { |
| 1169 | + $this->base->get_class( 'log' )->add_to_debug_log( sprintf( 'Buffer API: graphql_query(): Error: [%s] %s', $result->get_error_code(), $result->get_error_message() ) ); | |
| 1128 | 1170 | return $result; |
| 1129 | 1171 | } |
| 1130 | 1172 | |
| 1131 | - // Parse result. | |
| 1173 | + // Parse the response. | |
| 1132 | 1174 | $response = $this->parse_response( $result ); |
| 1133 | 1175 | |
| 1134 | - // If this is a retry, return the parsed response. | |
| 1135 | - // This prevents an infinite loop of retries when a token refresh fails. | |
| 1136 | - if ( $is_retry ) { | |
| 1137 | - return $response; | |
| 1176 | + // Log any API error, so failures that would otherwise be silent are captured. | |
| 1177 | + if ( is_wp_error( $response ) ) { | |
| 1178 | + $this->base->get_class( 'log' )->add_to_debug_log( sprintf( 'Buffer API: graphql_query(): API returned error: [%s] %s', $response->get_error_code(), $response->get_error_message() ) ); | |
| 1138 | 1179 | } |
| 1139 | 1180 | |
| 1140 | - // If the request was successful, return the response. | |
| 1141 | - if ( ! is_wp_error( $response ) ) { | |
| 1142 | - return $response; | |
| 1143 | - } | |
| 1181 | + return $response; | |
| 1144 | 1182 | |
| 1145 | - // If the error isn't an unauthenticated error, return it. | |
| 1146 | - if ( strtolower( $response->get_error_code() ) !== 'unauthenticated' ) { | |
| 1147 | - return $response; | |
| 1148 | - } | |
| 1149 | - | |
| 1150 | - // Attempt to refresh the token. | |
| 1151 | - $refresh_result = $this->refresh_token(); | |
| 1152 | - | |
| 1153 | - // Bail if the refresh token attempt failed. | |
| 1154 | - if ( is_wp_error( $refresh_result ) ) { | |
| 1155 | - return $refresh_result; | |
| 1156 | - } | |
| 1157 | - | |
| 1158 | - // Attempt the request again, now we have a new access token. | |
| 1159 | - return $this->graphql_query( $query, $variables, true ); | |
| 1160 | - | |
| 1161 | 1183 | } |
| 1162 | 1184 | |
| 1163 | 1185 | /** |
| 1164 | 1186 | * Returns the headers to use in an authenticated GraphQL API request. |
| @@ -1245,15 +1267,15 @@ | ||
| 1245 | 1267 | |
| 1246 | 1268 | } |
| 1247 | 1269 | |
| 1248 | 1270 | /** |
| 1249 | - * Parses the response body, returning a WP_Error | |
| 1271 | + * Parses the response body, returning a \WP_Error | |
| 1250 | 1272 | * if the response body contains an error. |
| 1251 | 1273 | * |
| 1252 | 1274 | * @since 3.9.8 |
| 1253 | 1275 | * |
| 1254 | - * @param string $response Response Body. | |
| 1255 | - * @return WP_Error|array | |
| 1276 | + * @param array|\WP_Error $response HTTP Response. | |
| 1277 | + * @return \WP_Error|array | |
| 1256 | 1278 | */ |
| 1257 | 1279 | private function parse_response( $response ) { |
| 1258 | 1280 | |
| 1259 | 1281 | // Get HTTP code and body. |
| @@ -1268,10 +1290,20 @@ | ||
| 1268 | 1290 | '403 Forbidden' |
| 1269 | 1291 | ); |
| 1270 | 1292 | } |
| 1271 | 1293 | |
| 1294 | + // Retain-and-retry on server errors: return without touching stored tokens. | |
| 1295 | + if ( $http_code >= 500 ) { | |
| 1296 | + return new \WP_Error( 'buffer_api_server_error', $http_code . ' server error' ); | |
| 1297 | + } | |
| 1298 | + | |
| 1272 | 1299 | // Decode response. |
| 1273 | 1300 | $body = json_decode( $http_body, true ); |
| 1301 | + | |
| 1302 | + // Bail if the response isn't valid JSON. | |
| 1303 | + if ( ! is_array( $body ) ) { | |
| 1304 | + return new \WP_Error( 'buffer_api_invalid_response', 'Invalid API response' ); | |
| 1305 | + } | |
| 1274 | 1306 | |
| 1275 | 1307 | // If an error is detected, return it. |
| 1276 | 1308 | if ( array_key_exists( 'error', $body ) ) { |
| 1277 | 1309 | return new \WP_Error( |