order_table = $wpdb->prefix . self::ORDER_DATA_TABLE; } /** * @param string|null $token * * @return int Order number, or 0 when the token is empty or no active order matches. */ public static function get_order_number( ?string $token ): int { if ( empty( $token ) ) { return 0; } global $wpdb; $result = $wpdb->get_results( $wpdb->prepare( "select order_number from {$wpdb->prefix}prodigy_orders where token = %s and status <> 1", $token ), ARRAY_A ); if ( isset( $result[0] ) ) { return (int) json_decode( $result[0]['order_number'], true ); } return 0; } /** * @param string $user_session * * @return array|object|\stdClass|null */ public static function get_last_guest_active_order_data( string $user_session ) { global $wpdb; return $wpdb->get_row( $wpdb->prepare( "select * from {$wpdb->prefix}prodigy_orders where local_user_hash = %s and status = 0 and deleted_at is null ", $user_session ), ARRAY_A ); } /** * @param string $user_id * * @return array|object|\stdClass|null */ public static function get_last_user_active_order_data( string $user_id ) { global $wpdb; return $wpdb->get_row( $wpdb->prepare( "select * from {$wpdb->prefix}prodigy_orders where customer_id = %s and status = 0 and deleted_at is null ", $user_id ), ARRAY_A ); } /** * @param string $order_token * @param int $status * * @return bool */ public function update_status_orders( string $order_token, int $status = self::PRODIGY_ORDER_IN_PROGRESS ): bool { global $wpdb; $is_update = $wpdb->update( $this->order_table, array( 'status' => $status, 'updated_at' => gmdate( 'Y-m-d H:i:s', time() ), ), array( 'token' => $order_token, ), array( '%d', '%s' ), array( '%s' ) ); return (bool) $is_update; } /** * @param string $order_token * @param string $old_user_hash * @param string $new_user_hash * @param int $user_id * * @return bool */ public function update_user_order( string $order_token, string $old_user_hash, string $new_user_hash, int $user_id ): bool { global $wpdb; $is_update = $wpdb->update( $this->order_table, array( 'local_user_hash' => '', 'customer_id' => $user_id, 'updated_at' => gmdate( 'Y-m-d H:i:s', time() ), ), array( 'local_user_hash' => $old_user_hash, 'token' => $order_token, ), array( '%s', '%d', '%s' ), array( '%s' ) ); return (bool) $is_update; } /** * @param int $user_id * * @return mixed */ public function get_active_user_order( int $user_id ) { global $wpdb; $result = $wpdb->get_row( $wpdb->prepare( "SELECT * FROM {$this->order_table} WHERE customer_id = %d AND deleted_at IS NULL", $user_id ), ARRAY_A ); return $result; } /** * @param int $user_id * * @return bool */ public function close_active_user_order( int $user_id ): bool { global $wpdb; return $wpdb->query( $wpdb->prepare( "UPDATE {$this->order_table} SET deleted_at = %s WHERE customer_id = %d AND deleted_at IS NULL", gmdate( 'Y-m-d H:i:s' ), $user_id ) ); } /** * @param string $order_token * @param string $user_session * @param array $data * * @return bool */ public function update_order_data( string $order_token, string $user_session, array $data ): bool { global $wpdb; $is_update = $wpdb->update( $this->order_table, array( 'includes' => json_encode( $data, true ), 'updated_at' => gmdate( 'Y-m-d H:i:s', time() ), ), array( // Token is unique, do not rely on local_user_hash (it can be empty or rotated). 'token' => $order_token, ), array( '%s', '%s' ), array( '%s' ) ); return (bool) $is_update; } /** * @param array $response * @param string $user_session * * @return string */ public function create_order( array $response, string $user_session ): string { global $wpdb; $result = ''; $order_number = $response['data']['id'] ?? null; $token = $response['data']['attributes']['token'] ?? false; $data_query = array( 'order_number' => $order_number, 'token' => $token, 'status' => $this->get_order_status( $token ), 'created_at' => gmdate( 'Y-m-d H:i:s', time() ), 'includes' => wp_json_encode( $response ), ); if ( Prodigy_User::is_logged_in() ) { $data_query['customer_id'] = $user_session; } else { $data_query['local_user_hash'] = $user_session; } $external_checkout_id = Prodigy_User::get_external_checkout_id(); if ( $external_checkout_id !== null ) { $data_query['external_checkout_id'] = $external_checkout_id; } if ( isset( $order_number ) && $token ) { $result = $wpdb->insert( $this->order_table, $data_query, array_fill( 0, count( $data_query ), '%s' ) ); } if ( $result ) { return $token; } } /** * @param string $token * * @return int */ public function get_order_status( string $token ): int { global $wpdb; $completed_status = self::PRODIGY_ORDER_COMPLETED; $status = $wpdb->get_results( $wpdb->prepare( "select * from {$wpdb->prefix}prodigy_orders where token = %s and status <> %d", $token, $completed_status ), ARRAY_A ); return (int) $status; } /** * @param string $token * * @return mixed */ public function get_in_process_order_for_token( string $token ) { global $wpdb; $result = $wpdb->get_results( $wpdb->prepare( "select * from {$wpdb->prefix}prodigy_orders where token = %s and status = %d", $token, self::PRODIGY_ORDER_IN_PROGRESS ), ARRAY_A ); if ( ! empty( $result ) ) { return $result[0]; } return false; } /** * @param string $user_session * * @return mixed|null */ public function get_order_token( string $user_session ) { global $wpdb; if ( '' === trim( $user_session ) ) { return null; } Prodigy_Install_Wizard::ensure_tables_exist(); if ( Prodigy_User::is_logged_in() ) { $customer_id = (int) $user_session; if ( $customer_id <= 0 ) { return null; } $external_checkout_id = Prodigy_User::get_external_checkout_id(); if ( $external_checkout_id !== null ) { $result = $wpdb->get_results( $wpdb->prepare( "select token from {$wpdb->prefix}prodigy_orders where customer_id = %d and external_checkout_id = %s and status <> 1 and deleted_at IS NULL ORDER BY created_at DESC LIMIT 1", $customer_id, $external_checkout_id ), ARRAY_A ); } else { $result = $wpdb->get_results( $wpdb->prepare( "select token from {$wpdb->prefix}prodigy_orders where customer_id = %d and status <> 1 and deleted_at IS NULL ORDER BY created_at DESC LIMIT 1", $customer_id ), ARRAY_A ); } } else { $result = $wpdb->get_results( $wpdb->prepare( "select token from {$wpdb->prefix}prodigy_orders where local_user_hash = %s and local_user_hash <> '' and status <> 1 and deleted_at IS NULL ORDER BY created_at DESC LIMIT 1", $user_session ), ARRAY_A ); } return $result[0]['token'] ?? null; } /** * @param string $order_token * * @return bool */ public function delete_local_order( string $order_token ): bool { global $wpdb; $is_update = $wpdb->update( $this->order_table, array( 'deleted_at' => gmdate( 'Y-m-d H:i:s', time() ), ), array( 'token' => $order_token, ), array( '%s' ), array( '%s' ) ); return (bool) $is_update; } /** * @param string $order_token * * @return bool */ public function is_deleted_order( string $order_token ): bool { global $wpdb; $result = $wpdb->get_row( $wpdb->prepare( "select deleted_at from {$wpdb->prefix}prodigy_orders where token = %s", $order_token ), ARRAY_A ); return ! empty( $result['deleted_at'] ); } /** * @param string $order_token * * @return array */ public function get_order_data( string $order_token ): array { global $wpdb; // Table name uses prefix + literal (no user input); %i not available before WP 6.2. // phpcs:ignore WordPress.DB.PreparedSQL.NotPrepared $results = $wpdb->get_row( $wpdb->prepare( 'SELECT includes FROM ' . $wpdb->prefix . 'prodigy_orders WHERE token = %s', $order_token ) ); return json_decode( $results->includes ?? '', true ); } }