id; } /** * Create an API URL. * * @param string $endpoint The API endpoint. * @param ?array $query The query parameters. * @return string */ function aict_build_api_url( string $endpoint, ?array $query = null ): string { $url = AICT_DOMAIN . $endpoint; if ( ! $query ) { return $url; } return $url . '?' . http_build_query( $query ); } /** * Get Text App URL with optional path and query parameters. * * @param string $path Optional path starting with "/". * @param ?array $query Optional query parameters, e.g. for Amplitude tracking in the Text App. * @return string */ function aict_get_app_url( string $path = '', ?array $query = null ): string { $base_url = defined( 'AICT_APP_URL' ) && AICT_APP_URL ? untrailingslashit( AICT_APP_URL ) : 'https://text.com/app'; if ( '' !== $path && '/' !== substr( $path, 0, 1 ) ) { $path = '/' . $path; } $url = $base_url . $path; if ( ! $query ) { return $url; } return $url . '?' . http_build_query( $query ); } /** * Get the visitor data. * * @return ?stdClass */ function aict_get_visitor_data(): ?stdClass { if ( ! is_user_logged_in() ) { return null; } $user = wp_get_current_user(); $visitor = new stdClass(); $visitor->email = $user->user_email; $visitor->name = $user->display_name; return $visitor; } /** * Generate a one-time OAuth verification token and store it in a transient. * * @return string 32-character hex token. */ function aict_generate_wp_token(): string { $wp_token = bin2hex( random_bytes( 16 ) ); set_transient( 'aict_oauth_' . $wp_token, true, HOUR_IN_SECONDS ); return $wp_token; } /** * Verify a wp_token from an OAuth callback and consume it (one-time use). * * @param string $token The token to verify. * @return bool True if valid, false otherwise. */ function aict_verify_wp_token( string $token ): bool { if ( empty( $token ) || ! get_transient( 'aict_oauth_' . $token ) ) { return false; } delete_transient( 'aict_oauth_' . $token ); return true; } /** * Return the URL for the /v1/platforms/wordpress/install endpoint. * * @return string */ function aict_get_oauth_initiate_url(): string { $success_url = add_query_arg( array( '_nonce' => wp_create_nonce( 'aict_connect' ), '_token' => aict_generate_wp_token(), ), admin_url( 'admin.php?page=aict_settings' ) ); $query_params = array( 'email' => wp_get_current_user()->user_email, 'url' => get_site_url(), 'adminUrl' => admin_url(), 'phpVer' => phpversion(), 'wpVer' => get_bloginfo( 'version' ), 'pluginVer' => AICT_PLUGIN_VERSION, 'successUrl' => $success_url, ); if ( defined( 'WOOCOMMERCE_VERSION' ) ) { $query_params['woocommerceVer'] = WOOCOMMERCE_VERSION; } return aict_build_api_url( '/v1/platforms/wordpress/install', $query_params ); } /** * Check whether WooCommerce is active on this site, evaluated live. * * @return bool */ function aict_is_woocommerce_active(): bool { return class_exists( 'WooCommerce' ) || defined( 'WOOCOMMERCE_VERSION' ); } /** * Resolve the outcome of the WooCommerce connection from the install return. * * @param bool $is_valid_callback Whether the nonce and callback token were already verified. * @return string 'success', 'failure', or '' when this is not a WooCommerce return. */ function aict_get_woocommerce_return_state( bool $is_valid_callback ): string { // phpcs:ignore WordPress.Security.NonceVerification.Recommended -- Only checking for presence; validity is passed in. if ( ! aict_is_woocommerce_active() || ! array_key_exists( 'success', $_GET ) || ! array_key_exists( '_nonce', $_GET ) ) { return ''; } if ( ! $is_valid_callback ) { return 'failure'; } // phpcs:ignore WordPress.Security.NonceVerification.Recommended -- Verified by the caller. return '1' === sanitize_text_field( wp_unslash( $_GET['success'] ) ) ? 'success' : 'failure'; } /** * Return the URL for the deactivation-feedback endpoint. * * @return ?string */ function aict_get_deactivation_feedback_url(): ?string { return null; } /** * Delete widget URL option from the database. * * @return bool */ function aict_cleanup(): bool { delete_option( 'aict_organization_id' ); delete_option( 'aict_woocommerce_connected' ); return delete_option( 'aict_widget_url' ); } /** * Get widget script URL from the database. * * @return ?string */ function aict_get_widget_url(): ?string { $widget_url = get_option( 'aict_widget_url', null ); return $widget_url ? $widget_url : null; }