Plugin Directory

Changeset 3471293


Ignore:
Timestamp:
02/27/2026 06:36:42 PM (5 weeks ago)
Author:
sovlix
Message:

v1.25.1

Location:
meetinghub
Files:
1507 added
6 edited

Legend:

Unmodified
Added
Removed
  • meetinghub/trunk/includes/API/Mhub_Zoom_Reports.php

    r3115818 r3471293  
    124124
    125125            $zoom_response = json_decode( $this->zoom_api->get_daily_report( $month, $year ), true );
     126            error_log(print_r($zoom_response,true));
    126127            return $zoom_response;
    127128        }
  • meetinghub/trunk/includes/API/Webex_Api.php

    r3467758 r3471293  
    102102
    103103        if ( is_array( $this->webex_settings ) && ! empty( $this->webex_settings ) ) {
    104             $this->client_id     = $this->webex_settings['client_id'];
    105             $this->client_secret = $this->webex_settings['client_secret'];
     104            $this->client_id     = isset( $this->webex_settings['client_id'] ) ? $this->webex_settings['client_id'] : '';
     105            $this->client_secret = isset( $this->webex_settings['client_secret'] ) ? $this->webex_settings['client_secret'] : '';
    106106        }
    107107
     
    116116        add_rewrite_rule( '^mhub-webex-oauth/?', 'index.php?mhub_webex_oauth=1', 'top' );
    117117
    118         if ( ! get_option( 'mhub_webex_rules_flushed' ) ) {
     118        // Use v2 to force re-flush if there were previous issues
     119        if ( ! get_option( 'mhub_webex_rules_flushed_v2' ) ) {
    119120            flush_rewrite_rules();
    120             update_option( 'mhub_webex_rules_flushed', true );
    121         }
     121            update_option( 'mhub_webex_rules_flushed_v2', true );
     122        }
     123    }
     124
     125    /**
     126     * Force flush rewrite rules (useful for debugging).
     127     * Can be called manually if redirect isn't working.
     128     */
     129    public function force_flush_rewrite_rules() {
     130        delete_option( 'mhub_webex_rules_flushed_v2' );
     131        flush_rewrite_rules();
     132        update_option( 'mhub_webex_rules_flushed_v2', true );
    122133    }
    123134
     
    138149    public function handle_oauth_redirect() {
    139150        if ( get_query_var( 'mhub_webex_oauth' ) == 1 ) {
    140             // Ensure user is logged in
     151            // Ensure user is logged in and has permissions
    141152            if ( ! is_user_logged_in() || ! current_user_can( 'manage_options' ) ) {
    142153                wp_die( 'You do not have permission to access this page.' );
    143154            }
    144155
    145             $code = isset( $_GET['code'] ) ? sanitize_text_field( $_GET['code'] ) : '';
     156            // Capture Authorization Code
     157            $code  = isset( $_GET['code'] ) ? sanitize_text_field( wp_unslash( $_GET['code'] ) ) : '';
     158            $error = isset( $_GET['error'] ) ? sanitize_text_field( wp_unslash( $_GET['error'] ) ) : '';
     159
     160            if ( ! empty( $error ) ) {
     161                // Handle error
     162                wp_redirect( admin_url( 'admin.php?page=meetinghub-settings&error=' . urlencode( $error ) . '#/webex' ) );
     163                exit;
     164            }
    146165
    147166            if ( ! empty( $code ) ) {
     167                // Exchange code for token
    148168                $this->fetch_access_token();
    149169               
    150                 // If we are here, it means redirection didn't happen in fetch_access_token
    151                 wp_redirect( admin_url( 'admin.php?page=meetinghub-settings&error=authentication_failed#/webex' ) );
     170                // If we are here, fetch_access_token returned (failed)
     171                // Redirect with error
     172                wp_redirect( admin_url( 'admin.php?page=meetinghub-settings&error=' . urlencode( 'Authentication failed. Please check error logs or try again.' ) . '#/webex' ) );
    152173                exit;
    153174            }
     
    187208     */
    188209    private function save_access_token( $token_data ) {
     210        // Add timestamp when token was saved for expiry calculation
     211        if ( ! isset( $token_data['token_saved_at'] ) ) {
     212            $token_data['token_saved_at'] = time();
     213        }
    189214        update_user_meta( $this->current_user_id, 'mhub_webex_access_token', $token_data );
     215        // Update the instance variable so it's immediately available
     216        $this->access_token_data = $token_data;
    190217    }
    191218
     
    211238     */
    212239    public function fetch_access_token() {
    213         $code = filter_input( INPUT_GET, 'code' );
     240        $code = filter_input( INPUT_GET, 'code', FILTER_SANITIZE_FULL_SPECIAL_CHARS );
    214241        if ( empty( $code ) ) {
    215242            return;
     
    230257
    231258        if ( is_wp_error( $response ) ) {
    232             // Handle error.
    233             return;
    234         }
    235 
     259            // Handle error - redirect with error message
     260            wp_safe_redirect( admin_url( 'admin.php?page=meetinghub-settings&error=connection_failed#/webex' ) );
     261            exit;
     262        }
     263
     264        $response_code = wp_remote_retrieve_response_code( $response );
    236265        $body = json_decode( wp_remote_retrieve_body( $response ), true );
     266
     267        // Check if the response was successful
     268        if ( $response_code !== 200 || empty( $body['access_token'] ) ) {
     269            // Handle authentication error
     270            wp_safe_redirect( admin_url( 'admin.php?page=meetinghub-settings&error=authentication_failed#/webex' ) );
     271            exit;
     272        }
     273
    237274        $this->save_access_token( $body );
    238275        wp_safe_redirect( admin_url( 'admin.php?page=meetinghub-settings#/webex' ) );
     
    245282    public function revoke_access_token() {
    246283        delete_user_meta( $this->current_user_id, 'mhub_webex_access_token' );
     284    }
     285
     286    /**
     287     * Refreshes the access token using the refresh token.
     288     *
     289     * @return bool True if refresh was successful, false otherwise.
     290     */
     291    private function refresh_access_token() {
     292        if ( empty( $this->access_token_data['refresh_token'] ) ) {
     293            error_log( 'Webex: Cannot refresh token - no refresh_token available' );
     294            return false;
     295        }
     296
     297        $response = wp_remote_post(
     298            self::ACCESS_TOKEN_URI,
     299            array(
     300                'body' => array(
     301                    'grant_type'    => 'refresh_token',
     302                    'client_id'     => $this->client_id,
     303                    'client_secret' => $this->client_secret,
     304                    'refresh_token' => $this->access_token_data['refresh_token'],
     305                ),
     306            )
     307        );
     308
     309        if ( is_wp_error( $response ) ) {
     310            error_log( 'Webex: Token refresh failed - ' . $response->get_error_message() );
     311            return false;
     312        }
     313
     314        $response_code = wp_remote_retrieve_response_code( $response );
     315        $body = json_decode( wp_remote_retrieve_body( $response ), true );
     316
     317        if ( $response_code !== 200 || empty( $body['access_token'] ) ) {
     318            error_log( 'Webex: Token refresh failed - Invalid response' );
     319            return false;
     320        }
     321
     322        // Save the new token data
     323        $this->access_token_data = $body;
     324        $this->save_access_token( $body );
     325       
     326        error_log( 'Webex: Token refreshed successfully' );
     327        return true;
     328    }
     329
     330    /**
     331     * Checks if the access token is expired or about to expire.
     332     *
     333     * @return bool True if token is expired or will expire in the next 5 minutes.
     334     */
     335    private function is_token_expired() {
     336        if ( empty( $this->access_token_data['expires_in'] ) ) {
     337            return false; // No expiry info, assume valid
     338        }
     339
     340        // Check if we have a timestamp of when the token was saved
     341        if ( empty( $this->access_token_data['token_saved_at'] ) ) {
     342            // No timestamp, add one now and assume token is still valid
     343            $this->access_token_data['token_saved_at'] = time();
     344            $this->save_access_token( $this->access_token_data );
     345            return false;
     346        }
     347
     348        $token_age = time() - $this->access_token_data['token_saved_at'];
     349        $expires_in = $this->access_token_data['expires_in'];
     350       
     351        // Refresh if token will expire in the next 5 minutes (300 seconds buffer)
     352        return ( $token_age >= ( $expires_in - 300 ) );
    247353    }
    248354
     
    257363    private function api_request( $endpoint, $method = 'GET', $data = array() ) {
    258364        if ( empty( $this->access_token_data['access_token'] ) ) {
     365            error_log( 'Webex: No access token available' );
    259366            return false;
     367        }
     368
     369        // Check if token is expired and refresh if needed
     370        if ( $this->is_token_expired() ) {
     371            error_log( 'Webex: Token expired, attempting refresh' );
     372            if ( ! $this->refresh_access_token() ) {
     373                error_log( 'Webex: Token refresh failed' );
     374                return false;
     375            }
    260376        }
    261377
     
    272388
    273389        if ( is_wp_error( $response ) ) {
     390            error_log( 'Webex API request failed: ' . $response->get_error_message() );
    274391            return false;
    275392        }
    276393
    277         return json_decode( wp_remote_retrieve_body( $response ), true );
     394        $response_code = wp_remote_retrieve_response_code( $response );
     395        $body = json_decode( wp_remote_retrieve_body( $response ), true );
     396
     397        // If we get a 401 Unauthorized, the token might be invalid - try refreshing once
     398        if ( 401 === $response_code ) {
     399            error_log( 'Webex: Received 401 Unauthorized, attempting token refresh' );
     400            if ( $this->refresh_access_token() ) {
     401                // Retry the request with the new token
     402                $args['headers']['Authorization'] = 'Bearer ' . $this->access_token_data['access_token'];
     403                $response = wp_remote_request( $this->api_base_uri . $endpoint, $args );
     404               
     405                if ( is_wp_error( $response ) ) {
     406                    error_log( 'Webex API retry failed: ' . $response->get_error_message() );
     407                    return false;
     408                }
     409               
     410                $body = json_decode( wp_remote_retrieve_body( $response ), true );
     411            } else {
     412                error_log( 'Webex: Token refresh failed after 401' );
     413                return false;
     414            }
     415        }
     416
     417        return $body;
    278418    }
    279419
  • meetinghub/trunk/includes/Mhub_Assets.php

    r3467758 r3471293  
    4343         */
    4444        public function mhub_admin_enqueue() {
    45             $create_meeting_url        = admin_url( 'admin.php?page=meetinghub#/meeting/create' );
     45            $create_meeting_url        = admin_url( 'admin.php?page=meetinghub#/meeting/create');
    4646            $oauth_data                = get_option( 'mhub_zoom_global_oauth_data' );
    4747            $mhub_google_account       = get_option( 'mhub_google_meet_account' );
     
    4949            $mhub_jitsi_settings       = get_option( 'mhub_jitsi_settings' );
    5050            $mhub_webex_settings       = get_option( 'mhub_webex_settings' );
    51             $mhub_zoom_settings        = get_option( 'mhub_zoom_settings' );
     51            $mhub_zoom_settings        = get_option( 'mhub_zoom_settings');
    5252            $mhub_google_meet_settings = get_option( 'mhub_google_meet_settings' );
    5353            $mhub_msteams_settings     = get_option( 'mhub_msteams_settings' );
  • meetinghub/trunk/includes/Mhub_Shortcodes.php

    r3309733 r3471293  
    15131513                                                        $hours   = floor( $meeting_duration / 60 );
    15141514                                                        $minutes = $meeting_duration % 60;
    1515                            
     1515
    15161516                                                        // Get the correct translation for "hour" or "hours".
    15171517                                                        $hour_text   = ( 1 == $hours ) ? __( 'hour', 'meetinghub' ) : __( 'hours', 'meetinghub' );
    15181518                                                        $minute_text = ( 1 == $minutes ) ? __( 'minute', 'meetinghub' ) : __( 'minutes', 'meetinghub' );
    1519                            
     1519                       
    15201520                                                        // Print hours.
    15211521                                                        echo esc_html( number_format_i18n( $hours ) ) . ' ' . esc_html( $hour_text );
  • meetinghub/trunk/meetinghub.php

    r3467758 r3471293  
    33 * Plugin Name:      MeetingHub
    44 * Description:      Power up your virtual meetings, webinars, and online classes by integrating Zoom Meeting, Google Meeting, Jitsi Meet, MS Team, & Webex with MeetingHub: the All-in-one Video Conference Plugin with Branded Meetings.
    5  * Version:          1.25.0
     5 * Version:          1.25.1
    66 * Author:           Sovlix
    77 * Author URI:       https://sovlix.com/
     
    7272
    7373if ( ! defined( 'MHUB_VERSION' ) ) {
    74     define( 'MHUB_VERSION', '1.25.0' );
     74    define( 'MHUB_VERSION', '1.25.1' );
    7575    define( 'MHUB_FILE', __FILE__ );
    7676    define( 'MHUB_PATH', dirname( MHUB_FILE ) );
  • meetinghub/trunk/readme.txt

    r3467758 r3471293  
    55**Tested up to:** 6.9
    66**Requires PHP:** 7.4
    7 **Stable tag:** 1.25.0 
     7**Stable tag:** 1.25.1 
    88**License:** GPL-2.0+ 
    99**License URL:** [GPL-2.0](http://www.gnu.org/licenses/gpl-2.0.txt)
     
    315315== Changelog ==
    316316
     317= 1.25.1 - 28 Feb, 2026 =
     318* **Fix:** Fixed critical WooCommerce cart fatal error that prevented customers from completing purchases when meeting settings were corrupted or invalid.
     319* **Fix:** Fixed Webex OAuth redirect issue while connecting - resolved intermittent "OAuth credentials not set up properly" errors.
     320* **Fix:** Fixed Webex OAuth token expiration issue causing connection errors after token expires.
     321* **Enhancement:** Added automatic Webex token refresh before expiration to ensure seamless API connectivity.
     322* **Enhancement:** Added comprehensive error logging for Webex API requests for better debugging.
     323* **Enhancement:** Improved WooCommerce integration stability with graceful error handling for invalid meeting data.
     324
    317325= 1.25.0 - 23 Feb, 2025 =
    318326* **New:** Microsoft Teams Integration! Support for OAuth, meeting scheduling, shortcodes, recordings, and more.
Note: See TracChangeset for help on using the changeset viewer.