| @@ -67,10 +67,17 @@ | ||
| 67 | 67 | $order_items = $order->get_items(); |
| 68 | 68 | foreach ( $order_items as $order_item ) { |
| 69 | 69 | $product = Subscription::get_subs_product( $order_item['product_id'] ); |
| 70 | 70 | |
| 71 | - if ( $product->is_type( 'simple' ) && ! subscrpt_pro_activated() ) { | |
| 72 | - if ( $product->is_enabled() ) { | |
| 71 | + // Plan items are created by Frontend\PlanCheckout on `subscrpt_product_checkout` | |
| 72 | + // below (resolution order: tied plan first, else classic meta). Skipping | |
| 73 | + // them here keeps the classic path from creating a second subscription. | |
| 74 | + if ( $product->is_type( 'simple' ) && ! subscrpt_pro_activated() && ! $order_item->get_meta( '_subscrpt_plan_id' ) ) { | |
| 75 | + // A plan product bought as One-Time carries no plan id — it is not a | |
| 76 | + // subscription, so never record one for it. | |
| 77 | + $is_one_time = function_exists( 'subscrpt_product_has_plan' ) && subscrpt_product_has_plan( $product->get_id() ); | |
| 78 | + | |
| 79 | + if ( $product->is_enabled() && ! $is_one_time ) { | |
| 73 | 80 | $is_renew = isset( $order_item['renew_subscrpt'] ); |
| 74 | 81 | |
| 75 | 82 | $timing_option = $product->get_timing_option(); |
| 76 | 83 | $trial = $product->get_trial(); |
| @@ -113,166 +120,8 @@ | ||
| 113 | 120 | } |
| 114 | 121 | } |
| 115 | 122 | |
| 116 | 123 | do_action( 'subscrpt_product_checkout', $order_item, $product, $post_status ); |
| 117 | - } | |
| 118 | - } | |
| 119 | - | |
| 120 | - /** | |
| 121 | - * Build user info from order or customer object. | |
| 122 | - * | |
| 123 | - * @param \WC_Order|\WC_Customer $order_or_customer Order or Customer object. | |
| 124 | - */ | |
| 125 | - public function build_user_info( $order_or_customer ): array { | |
| 126 | - $user_info = []; | |
| 127 | - | |
| 128 | - // Billing info. | |
| 129 | - $user_info['billing_first_name'] = $order_or_customer->get_billing_first_name(); | |
| 130 | - $user_info['billing_last_name'] = $order_or_customer->get_billing_last_name(); | |
| 131 | - $user_info['billing_company'] = $order_or_customer->get_billing_company(); | |
| 132 | - $user_info['billing_address_1'] = $order_or_customer->get_billing_address_1(); | |
| 133 | - $user_info['billing_address_2'] = $order_or_customer->get_billing_address_2(); | |
| 134 | - $user_info['billing_city'] = $order_or_customer->get_billing_city(); | |
| 135 | - $user_info['billing_postcode'] = $order_or_customer->get_billing_postcode(); | |
| 136 | - $user_info['billing_country'] = $order_or_customer->get_billing_country(); | |
| 137 | - $user_info['billing_state'] = $order_or_customer->get_billing_state(); | |
| 138 | - $user_info['billing_email'] = $order_or_customer->get_billing_email(); | |
| 139 | - $user_info['billing_phone'] = $order_or_customer->get_billing_phone(); | |
| 140 | - | |
| 141 | - // Shipping info. | |
| 142 | - $user_info['shipping_first_name'] = ! empty( $order_or_customer->get_shipping_first_name() ) ? $order_or_customer->get_shipping_first_name() : $user_info['billing_first_name']; | |
| 143 | - $user_info['shipping_last_name'] = ! empty( $order_or_customer->get_shipping_last_name() ) ? $order_or_customer->get_shipping_last_name() : $user_info['billing_last_name']; | |
| 144 | - $user_info['shipping_company'] = ! empty( $order_or_customer->get_shipping_company() ) ? $order_or_customer->get_shipping_company() : $user_info['billing_company']; | |
| 145 | - $user_info['shipping_address_1'] = ! empty( $order_or_customer->get_shipping_address_1() ) ? $order_or_customer->get_shipping_address_1() : $user_info['billing_address_1']; | |
| 146 | - $user_info['shipping_address_2'] = ! empty( $order_or_customer->get_shipping_address_2() ) ? $order_or_customer->get_shipping_address_2() : $user_info['billing_address_2']; | |
| 147 | - $user_info['shipping_city'] = ! empty( $order_or_customer->get_shipping_city() ) ? $order_or_customer->get_shipping_city() : $user_info['billing_city']; | |
| 148 | - $user_info['shipping_postcode'] = ! empty( $order_or_customer->get_shipping_postcode() ) ? $order_or_customer->get_shipping_postcode() : $user_info['billing_postcode']; | |
| 149 | - $user_info['shipping_country'] = ! empty( $order_or_customer->get_shipping_country() ) ? $order_or_customer->get_shipping_country() : $user_info['billing_country']; | |
| 150 | - $user_info['shipping_state'] = ! empty( $order_or_customer->get_shipping_state() ) ? $order_or_customer->get_shipping_state() : $user_info['billing_state']; | |
| 151 | - $user_info['shipping_phone'] = ! empty( $order_or_customer->get_shipping_phone() ) ? $order_or_customer->get_shipping_phone() : $user_info['billing_phone']; | |
| 152 | - | |
| 153 | - return $user_info; | |
| 154 | - } | |
| 155 | - | |
| 156 | - /** | |
| 157 | - * Maybe create user from user info. | |
| 158 | - * | |
| 159 | - * @param array $user_info User info array. | |
| 160 | - */ | |
| 161 | - public function maybe_create_user( $user_info ): ?int { | |
| 162 | - // Don't proceed if guest checkout is not allowed. | |
| 163 | - $is_guest_checkout_allowed = in_array( get_option( 'wp_subscription_allow_guest_checkout', '0' ), [ 1, '1', 'yes', 'on' ], true ); | |
| 164 | - if ( ! $is_guest_checkout_allowed ) { | |
| 165 | - return null; | |
| 166 | - } | |
| 167 | - | |
| 168 | - $is_new_customer = false; | |
| 169 | - | |
| 170 | - // Check if user exists with email. | |
| 171 | - $user = get_user_by( 'email', $user_info['billing_email'] ); | |
| 172 | - $user_id = $user ? $user->ID : 0; | |
| 173 | - | |
| 174 | - if ( ! $user_id ) { | |
| 175 | - $is_new_customer = true; | |
| 176 | - $username = sanitize_user( current( explode( '@', $user_info['billing_email'] ) ), true ); | |
| 177 | - if ( username_exists( $username ) ) { | |
| 178 | - $username .= '_' . wp_generate_password( 4, false ); | |
| 179 | - } | |
| 180 | - | |
| 181 | - // Create user. | |
| 182 | - $args = [ | |
| 183 | - 'user_login' => $username, | |
| 184 | - 'user_email' => $user_info['billing_email'], | |
| 185 | - 'first_name' => $user_info['billing_first_name'], | |
| 186 | - 'last_name' => $user_info['billing_last_name'], | |
| 187 | - 'display_name' => trim( "{$user_info['billing_first_name']} {$user_info['billing_last_name']}" ), | |
| 188 | - 'role' => 'customer', | |
| 189 | - ]; | |
| 190 | - | |
| 191 | - $user_id = wp_insert_user( $args ); | |
| 192 | - | |
| 193 | - if ( is_wp_error( $user_id ) ) { | |
| 194 | - subscrpt_write_log( 'Failed to auto-create user during checkout. Error: ' . $user_id->get_error_message() ); | |
| 195 | - return null; | |
| 196 | - } | |
| 197 | - | |
| 198 | - // Set billing info. | |
| 199 | - update_user_meta( $user_id, 'billing_first_name', $user_info['billing_first_name'] ); | |
| 200 | - update_user_meta( $user_id, 'billing_last_name', $user_info['billing_last_name'] ); | |
| 201 | - update_user_meta( $user_id, 'billing_company', $user_info['billing_company'] ); | |
| 202 | - update_user_meta( $user_id, 'billing_address_1', $user_info['billing_address_1'] ); | |
| 203 | - update_user_meta( $user_id, 'billing_address_2', $user_info['billing_address_2'] ); | |
| 204 | - update_user_meta( $user_id, 'billing_city', $user_info['billing_city'] ); | |
| 205 | - update_user_meta( $user_id, 'billing_postcode', $user_info['billing_postcode'] ); | |
| 206 | - update_user_meta( $user_id, 'billing_country', $user_info['billing_country'] ); | |
| 207 | - update_user_meta( $user_id, 'billing_state', $user_info['billing_state'] ); | |
| 208 | - update_user_meta( $user_id, 'billing_email', $user_info['billing_email'] ); | |
| 209 | - update_user_meta( $user_id, 'billing_phone', $user_info['billing_phone'] ); | |
| 210 | - | |
| 211 | - // Set shipping info. | |
| 212 | - update_user_meta( $user_id, 'shipping_first_name', $user_info['shipping_first_name'] ); | |
| 213 | - update_user_meta( $user_id, 'shipping_last_name', $user_info['shipping_last_name'] ); | |
| 214 | - update_user_meta( $user_id, 'shipping_company', $user_info['shipping_company'] ); | |
| 215 | - update_user_meta( $user_id, 'shipping_address_1', $user_info['shipping_address_1'] ); | |
| 216 | - update_user_meta( $user_id, 'shipping_address_2', $user_info['shipping_address_2'] ); | |
| 217 | - update_user_meta( $user_id, 'shipping_city', $user_info['shipping_city'] ); | |
| 218 | - update_user_meta( $user_id, 'shipping_postcode', $user_info['shipping_postcode'] ); | |
| 219 | - update_user_meta( $user_id, 'shipping_country', $user_info['shipping_country'] ); | |
| 220 | - update_user_meta( $user_id, 'shipping_state', $user_info['shipping_state'] ); | |
| 221 | - update_user_meta( $user_id, 'shipping_phone', $user_info['shipping_phone'] ); | |
| 222 | - | |
| 223 | - // User creation notification. | |
| 224 | - do_action( 'woocommerce_created_customer', $user_id, [], true ); | |
| 225 | - } | |
| 226 | - | |
| 227 | - // Auto-login the newly created account so the subscription can be associated with the user. | |
| 228 | - // This ONLY runs when $is_new_customer is true — i.e. when wp_insert_user() succeeded | |
| 229 | - // just above in this same request. It never fires for returning/existing users. | |
| 230 | - // wc_set_customer_auth_cookie() is the WooCommerce-sanctioned way to log a customer in | |
| 231 | - // during checkout; wp_set_auth_cookie() is the WP fallback if WC is not available. | |
| 232 | - if ( ! is_user_logged_in() && $is_new_customer && $user_id ) { | |
| 233 | - wp_set_current_user( $user_id ); | |
| 234 | - if ( function_exists( 'wc_set_customer_auth_cookie' ) ) { | |
| 235 | - wc_set_customer_auth_cookie( $user_id ); | |
| 236 | - } else { | |
| 237 | - wp_set_auth_cookie( $user_id ); | |
| 238 | - } | |
| 239 | - | |
| 240 | - // Set flag for manual login tracking. | |
| 241 | - set_transient( 'subscrpt_manual_login_' . $user_id, true, 15 * MINUTE_IN_SECONDS ); | |
| 242 | - | |
| 243 | - subscrpt_write_debug_log( 'Auto-logged in newly created user ID: ' . $user_id . ' after checkout.' ); | |
| 244 | - } | |
| 245 | - | |
| 246 | - return $user_id; | |
| 247 | - } | |
| 248 | - | |
| 249 | - /** | |
| 250 | - * Maybe assign user to order. | |
| 251 | - * | |
| 252 | - * @param int $order_id Order ID. | |
| 253 | - */ | |
| 254 | - public function maybe_assign_user_to_order( $order_id ) { | |
| 255 | - // Don't proceed if guest checkout is not allowed. | |
| 256 | - $is_guest_checkout_allowed = in_array( get_option( 'wp_subscription_allow_guest_checkout', '0' ), [ 1, '1', 'yes', 'on' ], true ); | |
| 257 | - if ( ! $is_guest_checkout_allowed ) { | |
| 258 | - return; | |
| 259 | - } | |
| 260 | - | |
| 261 | - $order = wc_get_order( $order_id ); | |
| 262 | - | |
| 263 | - // Don't proceed if order already have an user. | |
| 264 | - if ( $order->get_customer_id() ) { | |
| 265 | - return; | |
| 266 | - } | |
| 267 | - | |
| 268 | - // Build and maybe create a user. | |
| 269 | - $user_info = $this->build_user_info( $order ); | |
| 270 | - $user_id = $this->maybe_create_user( $user_info ); | |
| 271 | - | |
| 272 | - if ( $user_id ) { | |
| 273 | - $order->set_customer_id( $user_id ); | |
| 274 | - $order->save(); | |
| 275 | 124 | } |
| 276 | 125 | } |
| 277 | 126 | |
| 278 | 127 | /** |