'Facebook', 'whatsapp' => 'WhatsApp', 'telegram' => 'Telegram', 'x' => 'X', 'linkedin' => 'LinkedIn', 'copy' => __( 'Copy link', 'refmora' ) ); } public static function defaults() { return array( 'enabled' => 'yes', 'product_section' => 'yes', 'title' => 'Share & Earn', 'description' => '', 'platforms' => array( 'facebook', 'whatsapp', 'copy' ) ); } public static function get( $key = null ) { $value = wp_parse_args( get_option( 'refm_sharing', array() ), self::defaults() ); return null === $key ? $value : ( $value[ $key ] ?? null ); } public static function clean( $input ) { $input = is_array( $input ) ? $input : array(); $clean = self::defaults(); foreach ( array( 'enabled', 'product_section' ) as $key ) { $clean[ $key ] = isset( $input[ $key ] ) && 'yes' === $input[ $key ] ? 'yes' : 'no'; } foreach ( array( 'title' => 100, 'description' => 500 ) as $key => $length ) { $clean[ $key ] = isset( $input[ $key ] ) && is_scalar( $input[ $key ] ) ? substr( sanitize_text_field( $input[ $key ] ), 0, $length ) : ''; } if ( ! $clean['title'] ) { $clean['title'] = self::defaults()['title']; } $requested = array_filter( (array) ( $input['platforms'] ?? array() ), 'is_string' ); $clean['platforms'] = array_values( array_intersect( array_keys( self::platforms() ), $requested ) ); return $clean; } public static function init() { add_action( 'admin_post_refm_save_sharing', array( __CLASS__, 'save' ) ); add_action( 'wp_ajax_refm_generate_link', array( __CLASS__, 'ajax' ) ); add_action( 'woocommerce_after_add_to_cart_form', array( __CLASS__, 'product_section' ), 20 ); add_action( 'template_redirect', function () { if ( is_product() && self::allowed( get_current_user_id() ) && 'yes' === self::get( 'enabled' ) && 'yes' === self::get( 'product_section' ) ) { REFM_Cache::no_cache( 'Refmora personalized product sharing' ); } } ); add_action( 'wp_enqueue_scripts', array( __CLASS__, 'enqueue' ) ); } public static function allowed( $id ) { return REFM_Settings::program_enabled() && REFM_Tracking::active( $id ); } public static function link( $id, $url ) { if ( ! self::allowed( $id ) ) { return new WP_Error( 'inactive', __( 'An active affiliate account is required.', 'refmora' ) ); } if ( ! is_string( $url ) || strlen( $url ) > 2048 || preg_match( '/[\x00-\x20\\\\]/', $url ) ) { return new WP_Error( 'url', __( 'Enter a valid product or page URL from this store.', 'refmora' ) ); } $parts = wp_parse_url( $url ); $home = wp_parse_url( home_url( '/' ) ); $port = isset( $parts['port'] ) ? (int) $parts['port'] : ( 'https' === strtolower( $parts['scheme'] ?? '' ) ? 443 : 80 ); $home_port = isset( $home['port'] ) ? (int) $home['port'] : ( 'https' === strtolower( $home['scheme'] ?? '' ) ? 443 : 80 ); $base = rtrim( $home['path'] ?? '', '/' ); $path = $parts['path'] ?? '/'; if ( ! $parts || ! in_array( strtolower( $parts['scheme'] ?? '' ), array( 'http', 'https' ), true ) || strtolower( $parts['host'] ?? '' ) !== strtolower( $home['host'] ?? '' ) || $port !== $home_port || isset( $parts['user'] ) || isset( $parts['pass'] ) || ( $base && $path !== $base && 0 !== strpos( $path, $base . '/' ) ) ) { return new WP_Error( 'url', __( 'Use a product or page URL from this store only.', 'refmora' ) ); } if ( ! self::public_url( $url, $parts ) ) { return new WP_Error( 'private_url', __( 'Use a public product or page link. Account, checkout, admin and action links cannot be shared.', 'refmora' ) ); } return add_query_arg( REFM_Settings::referral_parameter(), REFM_Tracking::token( $id ), remove_query_arg( REFM_Settings::referral_keys(), esc_url_raw( $url, array( 'http', 'https' ) ) ) ); } private static function public_url( $url, $parts ) { $path = strtolower( rawurldecode( rawurldecode( $parts['path'] ?? '/' ) ) ); if ( preg_match( '~(?:^|/)(?:wp-admin|wp-login\.php|wp-json|\.\.?)(?:/|$)~', $path ) || preg_match( '/[\x00-\x20\\\\]/', $path ) ) { return false; } foreach ( array( 'myaccount', 'checkout', 'cart' ) as $page ) { $base = wp_parse_url( wc_get_page_permalink( $page ), PHP_URL_PATH ); if ( ! $base || '/' === $base ) { continue; } $base = strtolower( rtrim( rawurldecode( $base ), '/' ) ); if ( rtrim( $path, '/' ) === $base || 0 === strpos( $path, $base . '/' ) ) { return false; } } parse_str( $parts['query'] ?? '', $query ); foreach ( array_keys( $query ) as $key ) { $key = strtolower( $key ); if ( false !== strpos( $key, 'nonce' ) || in_array( $key, array( 'action', 'wc-ajax', 'rest_route', 'key', 'order_key', 'pay_for_order', 'reset_key', 'password', 'token', 'access_token' ), true ) ) { return false; } } $post_id = absint( REFM_Security::value( $query, 'p', REFM_Security::value( $query, 'page_id' ) ) ) ?: url_to_postid( $url ); if ( $post_id ) { $post = get_post( $post_id ); $status = $post ? get_post_status_object( $post->post_status ) : null; if ( ! $post || ! $status || ! $status->public || $post->post_password ) { return false; } if ( in_array( $post_id, array( wc_get_page_id( 'myaccount' ), wc_get_page_id( 'checkout' ), wc_get_page_id( 'cart' ) ), true ) ) { return false; } } return true; } public static function ajax() { if ( 'POST' !== ( isset( $_SERVER['REQUEST_METHOD'] ) && is_string( $_SERVER['REQUEST_METHOD'] ) ? sanitize_text_field( wp_unslash( $_SERVER['REQUEST_METHOD'] ) ) : '' ) ) { wp_send_json_error( array( 'message' => __( 'Use the link generator form.', 'refmora' ) ), 405 ); } if ( ! is_user_logged_in() ) { wp_send_json_error( array( 'message' => __( 'Please sign in to generate a referral link.', 'refmora' ) ), 403 ); } // phpcs:ignore WordPress.Security.NonceVerification.Missing -- Read the scalar nonce only to validate it immediately with wp_verify_nonce; no state change occurs before validation. $nonce = sanitize_text_field( ( isset( $_POST[ 'nonce' ] ) && is_scalar( $_POST[ 'nonce' ] ) ? wp_unslash( $_POST[ 'nonce' ] ) : '' ) ); if ( ! wp_verify_nonce( $nonce, 'refm_generate_link' ) ) { wp_send_json_error( array( 'message' => __( 'Your session expired. Refresh and try again.', 'refmora' ) ), 403 ); } $url = isset( $_POST['url'] ) && is_scalar( $_POST['url'] ) ? esc_url_raw( wp_unslash( $_POST['url'] ), array( 'http', 'https' ) ) : ''; $result = self::link( get_current_user_id(), $url ); if ( is_wp_error( $result ) ) { wp_send_json_error( array( 'message' => $result->get_error_message() ), 400 ); } wp_send_json_success( array( 'url' => $result ) ); } public static function enqueue() { $account = is_account_page() && is_wc_endpoint_url( 'refmora' ); $product = is_product() && 'yes' === self::get( 'enabled' ) && 'yes' === self::get( 'product_section' ) && REFM_Settings::program_enabled(); if ( ! $account && ! $product ) { return; } wp_enqueue_style( 'refm-sharing', REFM_URL . 'assets/sharing.css', array(), (string) filemtime( REFM_PATH . 'assets/sharing.css' ) ); REFM_Design::enqueue( 'refm-sharing' ); wp_enqueue_script( 'refm-sharing', REFM_URL . 'assets/sharing.js', array(), REFM_VERSION, true ); wp_localize_script( 'refm-sharing', 'refmSharing', array( 'ajax' => admin_url( 'admin-ajax.php' ), 'nonce' => self::allowed( get_current_user_id() ) ? wp_create_nonce( 'refm_generate_link' ) : '', 'error' => __( 'Unable to generate the link. Please try again.', 'refmora' ), 'copied' => __( 'Link copied.', 'refmora' ), 'manual' => __( 'Select and copy the link above, then paste it into your message or post.', 'refmora' ) ) ); } public static function generator() { if ( ! self::allowed( get_current_user_id() ) ) { return; } echo '
' . esc_html__( 'Paste a product or page URL from this store to create your own affiliate link.', 'refmora' ) . '