Как добавить функциональность, чтобы заказы woocommerce были видны пользователю-водителю в том же городе?

#php #wordpress #function #woocommerce

#php #wordpress #функция #woocommerce

Вопрос:

У меня есть WordPress магазин Woo-commerce с Pro-версией плагина драйверы доставки для woo-commerce (https://wordpress.org/plugins/delivery-drivers-for-woocommerce /).

Все работает нормально, поскольку любой пользователь с пользовательской ролью: «водитель доставки» может просматривать и запрашивать все заказы, которые обрабатываются через веб-сайт, на данный момент с помощью настроек зон доставки / доставки woo-commerce я настроил его так, что только клиенты, которые проживают в определенном городе, могут размещать заказ, и яя утверждаю только водителей доставки в этой области.

Но я хочу распространить это на другие города, я могу добавить почтовые индексы, чтобы пользователи могли делать заказы по этим почтовым кодам, но проблема с плагином драйверов доставки — водители будут видеть все заказы из всех городов на своей панели управления. Я хочу, чтобы водители просматривали и запрашивали заказы только в том городе, в котором они проживают (город, к которому они себя причислили).

Вот код функции, которая отображает все заказы, размещенные на веб-сайте, для типа роли пользователя «водитель доставки» :

driver-dashboard-shortcode.php

 <?php
/**
* The Unclaimed Orders Shortcode.

**/

function ddwc_pro_dashboard_shortcode() {

// Check if user is logged in.
if ( is_user_logged_in() ) {
    // Get the user ID.
    $user_id = get_current_user_id();

    // Get the user object.
    $user_meta = get_userdata( $user_id );

    // If user_id doesn't equal zero.
    if ( 0 != $user_id ) {

        // If claim delivery button is pushed.
        if ( ! empty( $_GET['claim_delivery'] ) ) {

            // Get deliver ID to claim.
            $claim_delivery = $_GET['claim_delivery'];

            // Update order status.
            $order = wc_get_order( $claim_delivery );
            $order->update_status( 'driver-assigned' );

            // Update order with driver ID.
            update_post_meta( $claim_delivery, 'ddwc_driver_id', $user_id, -1 );

            // Redirect URL.
            $redirect_url = apply_filters( 'ddwc_pro_claim_order_redirect_url', get_permalink( get_option( 'woocommerce_myaccount_page_id' ) ) . '/driver-dashboard/?orderid=' . $claim_delivery, $claim_delivery );

            // Redirect driver to the order details.
            wp_redirect( $redirect_url );
        }

        // Get all the user roles as an array.
        $user_roles = $user_meta->roles;

        // Check if the role you're interested in, is present in the array.
        if ( in_array( 'driver', $user_roles, true ) ) {

            // Set variable for driver ID.
            if ( isset( $_GET['orderid'] ) amp;amp; ( '' != $_GET['orderid'] ) ) {
                $driver_id = get_post_meta( $_GET['orderid'], 'ddwc_driver_id', true );
            }

            /**
             * Args for Orders with no driver ID attached.
             */
            $args = array(
                'post_type'      => 'shop_order',
                'posts_per_page' => -1,
                'post_status'    => 'any',
                'post_parent'    => 0
            );

            /**
             * Get Orders with Driver ID attached
             */
            $unclaimed_orders = get_posts( $args );

            /**
             * If there are orders to loop through.
             */
            if ( $unclaimed_orders ) {

                // Total for table thead.
                $total_title = '<td>' . esc_attr__( 'Total', 'ddwc' ) . '</td>';

                do_action( 'ddwc_pro_unclaimed_orders_table_before' );

                echo '<table class="ddwc-dashboard">';
                echo '<thead><tr><td>' . esc_attr__( 'Date', 'ddwc-pro' ) . '</td><td>' . esc_attr__( 'Address', 'ddwc-pro' ) . '</td>' . apply_filters( 'ddwc_pro_driver_dashboard_unclaimed_orders_total_title', $total_title ) . '<td></td></tr></thead>';
                echo '<tbody>';

                do_action( 'ddwc_pro_unclaimed_orders_table_tbody_before' );

                foreach ( $unclaimed_orders as $driver_order ) {

                    // Get Driver ID (if set).
                    $driver_id_setting = get_post_meta( $driver_order->ID, 'ddwc_driver_id', TRUE );

                    // Get an instance of the WC_Order object.
                    $order = wc_get_order( $driver_order->ID );

                    // Get the required order data.
                    $order_data         = $order->get_data();
                    $currency_code      = $order_data['currency'];
                    $currency_symbol    = get_woocommerce_currency_symbol( $currency_code );
                    $order_id           = $order_data['id'];
                    $order_status       = $order_data['status'];
                    $order_date_created = $order_data['date_created']->date( 'm-d-Y' );

                    ## CART INFORMATION:

                    $order_total = $order_data['total'];

                    ## BILLING INFORMATION:

                    $order_billing_city     = $order_data['billing']['city'];
                    $order_billing_state    = $order_data['billing']['state'];
                    $order_billing_postcode = $order_data['billing']['postcode'];

                    ## SHIPPING INFORMATION:

                    $order_shipping_city     = $order_data['shipping']['city'];
                    $order_shipping_state    = $order_data['shipping']['state'];
                    $order_shipping_postcode = $order_data['shipping']['postcode'];

                    // Create address to use in the table.
                    $address = $order_billing_city . ' ' . $order_billing_state . ', ' . $order_billing_postcode;

                    // Set address to shipping (if available).
                    if ( isset( $order_shipping_city ) ) {
                        $address = $order_shipping_city . ' ' . $order_shipping_state . ', ' . $order_shipping_postcode;
                    }

                    // Allowed statuses.
                    $status_array = apply_filters( 'ddwc_pro_driver_dashboard_unclaimed_orders_status_array', array( 'processing' ) );

                    // Display unassigned orders.
                    if ( in_array( $order_status, $status_array ) amp;amp; ( -1 == $driver_id_setting || '' === $driver_id_setting ) ) {
                        echo '<tr>';

                        echo '<td>' . $order_date_created . '</td>';
                        echo '<td>' . apply_filters( 'ddwc_pro_driver_dashboard_unclaimed_orders_table_address', $address ) . '</td>';

                        if ( isset( $order_total ) ) {
                            $order_total = '<td>'  . $currency_symbol . $order_total . '</td>';
                            echo apply_filters( 'ddwc_pro_driver_dashboard_unclaimed_orders_total', $order_total );
                        } else {
                            echo '<td>-</td>';
                        }

                        echo '<td><a href="' . apply_filters( 'ddwc_pro_driver_dashboard_unclaimed_orders_button_url', '?claim_delivery=' . $order_id, $order_id ) . '" class="button">' . apply_filters( 'ddwc_pro_driver_dashboard_unclaimed_orders_button_text', __( 'CLAIM', 'ddwc-pro' ) ) . '</a></td>';

                        echo '</tr>';
                    } else {
                        // Do nothing.
                    }
                }

                do_action( 'ddwc_pro_unclaimed_orders_table_tbody_after' );

                echo '</tbody>';
                echo '</table>';

                do_action( 'ddwc_pro_unclaimed_orders_table_after' );

                // Driver dashboard button.
                $dashboard_button = '<a href="' . apply_filters( 'ddwc_pro_back_to_driver_dashboard_link', get_permalink( get_option( 'woocommerce_myaccount_page_id' ) ) . 'driver-dashboard/' ) . '">amp;larr; ' . __( 'Driver Dashboard', 'ddwc-pro' ) . '</a>';

                // Filter "Driver Dashboard" button.
                echo apply_filters( 'ddwc_pro_back_to_driver_dashboard_button', $dashboard_button );

            } else {

                do_action( 'ddwc_pro_assigned_orders_empty_before' );

                // Message - No assigned orders.
                $empty  = '<h3 class="ddwc assigned-orders">' . __( 'Assigned Orders', 'ddwc-pro' ) . '</h3>';
                $empty .= '<p>' . __( 'You do not have any assigned orders.', 'ddwc-pro' ) . '</p>';

                echo apply_filters( 'ddwc_pro_assigned_orders_empty', $empty );

                do_action( 'ddwc_pro_assigned_orders_empty_after' );

            }
        } else {

            // Set the Access Denied page text.
            $access_denied = '<h3 class="ddwc access-denied">' . __( 'Access Denied', 'ddwc-pro' ) . '</h3><p>' . __( 'Sorry, but you are not able to view this page.', 'ddwc-pro' ) . '</p>';

            // Filter Access Denied text.
            echo apply_filters( 'ddwc_access_denied', $access_denied );
        }

    } else {
        // Do nothing.
    }
} else {
    apply_filters( 'ddwc_pro_dashboard_login_form', wp_login_form() );
}
}
add_shortcode( 'ddwc_pro_dashboard', 'ddwc_pro_dashboard_shortcode' );
  

Я придумал способ реализовать эту функциональность — я создал настраиваемое поле (только для водителей доставки) в разделе сведений об учетной записи woocommerce «моя учетная запись / редактировать учетную запись». Поле представляет собой выпадающий список городов, которые водитель доставки может назначить себе в данных своей учетной записи.

И я хочу вызвать функцию, которая проверяет, соответствует ли метка адреса ‘town / city’ выбранному городу в профиле водителя, если это так, то водитель может видеть этот заказ (заказы). Если водитель не выбрал город в этом раскрывающемся списке, он не увидит никаких заказов.

Вот как я добавил выпадающий список городов:

   <?php

   /**
   * Get additional account fields.
   *
   * @return array
   */
   function iconic_get_account_fields() {
    return apply_filters( 'iconic_account_fields', array(
        'city_select'              => array(
           'type'                  => 'select',
           'label'                 => __( 'Select City', 'iconic' ),
           'hide_in_account'       => false,
            'hide_in_admin'        => false,
            'required'             => false,
           'options' => array(
               ''    => __( 'Select an option...', 'iconic' ),
               1     => __( 'Manchester', 'iconic' ),
               2     => __( 'Birmingham', 'iconic' ),
               3     => __( 'London', 'iconic' ),
           ),
        'bank_name'                 => array(
            'type'                 => 'text',
            'label'                => __( 'Bank Name', 'iconic' ),
            'hide_in_account'      => false,
            'hide_in_admin'        => false,
            'required'             => false,
        ),

    ) );
}

/**
 * Add post values to account fields if set.
 *
 * @param array $fields
 *
 * @return array
 */
function iconic_add_post_data_to_account_fields( $fields ) {
    if ( empty( $_POST ) ) {
        return $fields;
    }

    foreach ( $fields as $key => $field_args ) {
        if ( empty( $_POST[ $key ] ) ) {
            $fields[ $key ]['value'] = '';
            continue;
        }

        $fields[ $key ]['value'] = $_POST[ $key ];
    }

    return $fields;
}

add_filter( 'iconic_account_fields', 'iconic_add_post_data_to_account_fields', 10, 1 );

/**
 * Add field to account area.
 */
function iconic_print_user_frontend_fields() {
    $fields            = iconic_get_account_fields();
    $is_user_logged_in = is_user_logged_in();

    foreach ( $fields as $key => $field_args ) {
        $value = null;

        if ( ! iconic_is_field_visible( $field_args ) ) {
            continue;
        }

        if ( $is_user_logged_in ) {
            $user_id = iconic_get_edit_user_id();
            $value   = iconic_get_userdata( $user_id, $key );
        }

        $value = isset( $field_args['value'] ) ? $field_args['value'] : $value;

        woocommerce_form_field( $key, $field_args, $value );
    }
}
add_action( 'woocommerce_edit_account_form', 'iconic_print_user_frontend_fields', 10 ); // my account

/**
 * Get user data.
 *
 * @param $user_id
 * @param $key
 *
 * @return mixed|string
 */
function iconic_get_userdata( $user_id, $key ) {
    if ( ! iconic_is_userdata( $key ) ) {
        return get_user_meta( $user_id, $key, true );
    }

    $userdata = get_userdata( $user_id );

    if ( ! $userdata || ! isset( $userdata->{$key} ) ) {
        return '';
    }

    return $userdata->{$key};
}


/**
 * Get currently editing user ID (frontend account/edit profile/edit other user).
 *
 * @return int
 */
function iconic_get_edit_user_id() {
    return isset( $_GET['user_id'] ) ? (int) $_GET['user_id'] : get_current_user_id();
}


/**
 * Save registration fields.
 *
 * @param int $customer_id
 */
function iconic_save_account_fields( $customer_id ) {
    $fields         = iconic_get_account_fields();
    $sanitized_data = array();

    foreach ( $fields as $key => $field_args ) {
        if ( ! iconic_is_field_visible( $field_args ) ) {
            continue;
        }

        $sanitize = isset( $field_args['sanitize'] ) ? $field_args['sanitize'] : 'wc_clean';
        $value    = isset( $_POST[ $key ] ) ? call_user_func( $sanitize, $_POST[ $key ] ) : '';

        if ( iconic_is_userdata( $key ) ) {
            $sanitized_data[ $key ] = $value;
            continue;
        }

        update_user_meta( $customer_id, $key, $value );
    }

    if ( ! empty( $sanitized_data ) ) {
        $sanitized_data['ID'] = $customer_id;
        wp_update_user( $sanitized_data );
    }
}


add_action( 'personal_options_update', 'iconic_save_account_fields' ); // edit own account admin
add_action( 'edit_user_profile_update', 'iconic_save_account_fields' ); // edit other account
add_action( 'woocommerce_save_account_details', 'iconic_save_account_fields' ); // edit WC account

/**
 * Is this field core user data.
 *
 * @param $key
 *
 * @return bool
 */
function iconic_is_userdata( $key ) {
    $userdata = array(
        'user_pass',
        'user_login',
        'user_nicename',
        'user_url',
        'user_email',
        'display_name',
        'nickname',
        'first_name',
        'last_name',
        'description',
        'rich_editing',
        'user_registered',
        'role',
        'jabber',
        'aim',
        'yim',
        'show_admin_bar_front',
    );

    return in_array( $key, $userdata );
}

/**
 * Is field visible.
 *
 * @param $field_args
 *
 * @return bool
 */
function iconic_is_field_visible( $field_args ) {
    $visible = true;
    $action  = filter_input( INPUT_POST, 'action' );

    if ( is_admin() amp;amp; ! empty( $field_args['hide_in_admin'] ) ) {
        $visible = false;
    } elseif ( ( is_account_page() || $action === 'save_account_details' ) amp;amp; is_user_logged_in() amp;amp; ! empty( $field_args['hide_in_account'] ) ) {
        $visible = false;
    } 

    return $visible;
}

/**
 * Add fields to admin area.
 */
function iconic_print_user_admin_fields() {
    $fields = iconic_get_account_fields();
    ?>
    <h2><?php _e( 'Additional Information', 'iconic' ); ?></h2>
    <table class="form-table" id="iconic-additional-information">
        <tbody>
        <?php foreach ( $fields as $key => $field_args ) { ?>
            <?php
            if ( ! iconic_is_field_visible( $field_args ) ) {
                continue;
            }

            $user_id = iconic_get_edit_user_id();
            $value   = iconic_get_userdata( $user_id, $key );
            ?>
            <tr>
                <th>
                    <label for="<?php echo $key; ?>"><?php echo $field_args['label']; ?></label>
                </th>
                <td>
                    <?php $field_args['label'] = false; ?>
                    <?php woocommerce_form_field( $key, $field_args, $value ); ?>
                </td>
            </tr>
        <?php } ?>
        </tbody>
    </table>
    <?php
}

add_action( 'show_user_profile', 'iconic_print_user_admin_fields', 30 ); // admin: edit profile
add_action( 'edit_user_profile', 'iconic_print_user_admin_fields', 30 ); // admin: edit other users

/**
 * Validate fields on frontend.
 *
 * @param WP_Error $errors
 *
 * @return WP_Error
 */
function iconic_validate_user_frontend_fields( $errors ) {
    $fields = iconic_get_account_fields();

    foreach ( $fields as $key => $field_args ) {
        if ( empty( $field_args['required'] ) ) {
            continue;
        }

        if ( ! isset( $_POST['register'] ) amp;amp; ! empty( $field_args['hide_in_account'] ) ) {
            continue;
        }

    
        if ( empty( $_POST[ $key ] ) ) {
            $message = sprintf( __( '%s is a required field.', 'iconic' ), '<strong>' . $field_args['label'] . '</strong>' );
            $errors->add( $key, $message );
        }
    }

    return $errors;
}

add_filter( 'woocommerce_save_account_details_errors', 'iconic_validate_user_frontend_fields', 10 )
  

Я новичок в программировании (особенно PHP) Я пробовал разные способы добавления оператора if, чтобы проверить, могу ли я создать функциональность, где перед отображением списка заказов в таблице проверяется, соответствует ли выбранный город водителей городу в адресе клиентов, а затем отображаются те же заказы, что и город, в котором проживает водитель, если нет, нетзаказы должны отображаться.

Но я продолжаю ломать свой сайт, буду признателен за любую помощь (поскольку я начинаю думать, что, возможно, это не тот файл, в который можно добавить такую функцию).

Комментарии:

1. Какими различными способами вы пытались добавить эту логику? Любая дополнительная информация облегчит помощь. На мой взгляд, похоже, что вы хорошо начали — вам просто нужно получить информацию об учетной записи водителя (похоже, это вызов iconic_get_userdata ), а затем внутри цикла невостребованных заказов: foreach ( $unclaimed_orders as $driver_order ) {... проверьте, совпадает ли город адреса доставки заказа (при условии, что я правильно понял проблему).

2. Одним из возможных решений может быть изменение массива $ args, добавив предложение «where», чтобы показывать заказы только в пределах досягаемости драйвера. Логика была бы такой: «где order.postcode в $arrayOfPostcodesNearDriver». $arrayOfPostcodesNearDriver = get_postcode_api($driver_postcode, $allowed_range). Это решение позволяет водителям работать в одном или нескольких близлежащих районах, в зависимости от заданного вами ограничения диапазона. Я попытаюсь что-нибудь закодировать на выходных, если у меня будет такая возможность.

Ответ №1:

Вот что я бы сделал:

На стороне параметров сайта (пользовательские или через параметры зоны доставки woocommerce):

  • Администратор хранит список городов с именем и идентификатором
  • Вы могли бы создать список полей параметров ACF, где вы можете ввести название города и идентификатор (или почтовый индекс) (чтобы предотвратить создание запросов только на основе названий городов)
  • В Woocommerce также есть варианты доставки, в которых вы можете хранить области доставки, чтобы вы могли хранить здесь свои города и использовать их. В зависимости от того, как вы интегрировались с Woocommerce.

На стороне пользователя / водителя:

  • Ваше дополнительное поле города должно позволять пользователю выбирать несколько городов из определенного вами списка
  • Данные будут храниться как user_meta сериализованный массив идентификаторов или почтовых индексов из выбранных городов
  • Таким образом, у каждого водителя есть почтовый индекс / идентификаторы городов, сохраненные как пользовательские мета, которые он может редактировать

На стороне процесса оформления заказа :

  • Если почтовый индекс адреса доставки «привязан» к списку доступных городов, который вы создали: отлично
  • Если почтовый индекс является свободным полем, вам нужно будет добавить что-то, чтобы заказ был связан с почтовым индексом / идентификатором доступного города, который вы определили. Чтобы иметь возможность сопоставлять драйверы и заказы.
  • В зависимости от вашего процесса оформления заказа вы можете добавить поле заказа, чтобы клиент выбирал город на основе вашего списка администраторов. Или сделайте поле postal_code ограниченным вашим списком. Вам нужно что-то, чтобы заказ можно было сопоставить с одним из городов из вашего списка.

На странице списка заказов водителей :

  • Вы отредактируете запрос WP_Query, запрашивающий этот запрос заказов, чтобы добавить мета_запрос
  • meta_query будет запрашивать заказы на основе почтового индекса / идентификаторов user_meta из текущего пользовательского драйвера
  • Вы можете получить доступ к значениям пользовательского мета-массива и добавить мета_запрос «ИЛИ» для каждого идентификатора / почтового индекса городов драйверов в запрос заказов
  • будет отображаться заказ, соответствующий одному из идентификаторов / почтовых индексов города водителя