gruene-seele/dev/dhl-for-woocommerce/includes/front-end/class-pr-dhl-front-end-paket.php
Kevin Adametz 0f641ef33a Housekeeping: offene Dev-Dateien eingecheckt + Sidebar „Bestellungen"→„Versand"
- Sidebar-Menü „Bestellungen" in „Versand" umbenannt (layout-sidenav), sonst nur
  Blade-Formatierung.
- Entwicklungspläne in ISO-Datumsformat umbenannt (entwicklungsplan-aktualisiert-*).
- dev/dhl-for-woocommerce/ (DHL-Plugin) + dev/partnercenter-api.zip + PastedGraphic
  hinzugefügt.
- .claude/ bewusst NICHT eingecheckt (lokale Claude-Code-Konfiguration).

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
2026-08-28 12:04:41 +00:00

1181 lines
50 KiB
PHP

<?php
if (! defined('ABSPATH')) {
exit; // Exit if accessed directly
}
/**
* WooCommerce DHL Shipping Order.
*
* @category Shipping
*
* @author Shadi Manna
*/
if (! class_exists('PR_DHL_Front_End_Paket')) {
class PR_DHL_Front_End_Paket
{
private $preferred_services = [];
private $preferred_location_neighbor = [];
private $cdp_service = [];
private $shipping_dhl_settings = [];
/**
* Init and hook in the integration.
*/
public function __construct()
{
$this->shipping_dhl_settings = PR_DHL()->get_shipping_dhl_settings();
$this->init_hooks();
$this->preferred_services = [
'pr_dhl_preferred_day' => esc_html__('Delivery Day', 'dhl-for-woocommerce'),
'pr_dhl_preferred_location_neighbor' => esc_html__('Preferred Location or Neighbor', 'dhl-for-woocommerce'),
'pr_dhl_preferred_location' => esc_html__('Preferred Location Address', 'dhl-for-woocommerce'),
'pr_dhl_preferred_neighbour_name' => esc_html__('Preferred Neighbor Name', 'dhl-for-woocommerce'),
'pr_dhl_preferred_neighbour_address' => esc_html__('Preferred Neighbor Address', 'dhl-for-woocommerce'),
];
$this->preferred_location_neighbor = [
'preferred_location' => esc_html__('Location', 'dhl-for-woocommerce'),
'preferred_neighbor' => esc_html__('Neighbor', 'dhl-for-woocommerce'),
];
$this->cdp_service = [
'pr_dhl_cdp_delivery' => esc_html__('Delivery option', 'dhl-for-woocommerce'),
];
}
public function init_hooks()
{
add_action('wp_enqueue_scripts', [$this, 'load_styles_scripts']);
if ($this->is_tracking_enabled() && ($this->is_preferredservice_enabled() || $this->is_parcelfinder_enabled() || $this->is_cdp_enabled())) {
// Add DHL meta tag
add_action('wp_head', [$this, 'dhl_add_meta_tags']);
}
if ($this->is_cdp_enabled()) {
add_action('woocommerce_review_order_after_shipping', [$this, 'add_cdp_fields']);
add_action('woocommerce_checkout_order_processed', [$this, 'process_cdp_fields'], 10, 2);
}
if ($this->is_preferredservice_enabled()) {
add_action('woocommerce_review_order_after_shipping', [$this, 'add_preferred_fields']);
add_action('woocommerce_cart_calculate_fees', [$this, 'add_cart_fees']);
add_action('woocommerce_checkout_process', [$this, 'verify_preferred_services_fields']);
add_action('woocommerce_checkout_order_processed', [$this, 'process_dhl_preferred_fields'], 10, 2);
add_filter('woocommerce_get_order_item_totals', [$this, 'display_dhl_preferred_free_services_values'], 10, 2);
}
// Parcel finder hooks
if ($this->is_parcelfinder_enabled()) {
// add_action( 'woocommerce_after_checkout_billing_form', array( $this, 'add_parcel_finder_btn' ) );
add_action('woocommerce_before_checkout_shipping_form', [$this, 'add_registration_text_above_shipping_fields']);
add_action('woocommerce_before_checkout_shipping_form', [$this, 'add_parcel_finder_btn']);
add_action('woocommerce_after_checkout_form', [$this, 'add_parcel_finder_form']);
add_action('wp_ajax_wc_shipment_dhl_parcelfinder_search', [$this, 'call_parcel_finder']);
add_action('wp_ajax_nopriv_wc_shipment_dhl_parcelfinder_search', [$this, 'call_parcel_finder']);
add_filter('woocommerce_checkout_fields', [$this, 'add_postnum_field'], 101);
add_action('woocommerce_checkout_process', [$this, 'validate_post_number']);
add_action('woocommerce_checkout_order_processed', [$this, 'clear_post_number_for_regular_address'], 10, 2);
// add_action( 'woocommerce_process_checkout_field_shipping_dhl_postnum_ps', array( $this, 'validate_post_number_required' ) );
add_filter('woocommerce_order_formatted_shipping_address', [$this, 'display_post_number'], 10, 2);
add_filter('woocommerce_localisation_address_formats', [$this, 'set_format_post_number']);
add_filter('woocommerce_formatted_address_replacements', [$this, 'add_format_post_number'], 10, 2);
add_filter('woocommerce_admin_shipping_fields', [$this, 'admin_order_add_postnum_field'], 10);
}
if ($this->is_email_notification_enabled()) {
$pos = apply_filters('pr_shipping_dhl_email_notification_position', 'woocommerce_review_order_before_submit');
add_action($pos, [$this, 'add_email_notification_checkbox'], 10);
add_action('woocommerce_checkout_order_processed', [$this, 'process_email_notification_fields'], 30, 2);
}
}
/**
* Add DHL registration link above the shipping fields.
*/
public function add_registration_text_above_shipping_fields(): void
{
$link = DHL_GERMAN_REGISTRATION_LINK;
if (get_locale() === 'en_US') {
$link = DHL_ENGLISH_REGISTRATION_LINK;
}
echo '<div class="registration_info" >';
echo sprintf(esc_html__('For deliveries to DHL Parcel Lockers you have to %1screate a DHL account%2s and get a Post Number.', 'dhl-for-woocommerce'), '<a href="'.esc_url($link).'" target="_blank">', '</a>');
echo '</div>';
}
/**
* is_using_checkout_block
*
* @param array is_using_checkout_block local fields.
* @return bool
*/
protected function is_using_checkout_block()
{
$checkout_page_id = wc_get_page_id('checkout');
$has_block_checkout = $checkout_page_id && has_block('woocommerce/checkout', $checkout_page_id);
if ($has_block_checkout) {
$is_using_checkout_block = true;
} else {
$is_using_checkout_block = false;
}
return $is_using_checkout_block;
}
protected function is_tracking_enabled()
{
return false;
}
protected function is_preferredservice_enabled()
{
if ((isset($this->shipping_dhl_settings['dhl_preferred_day']) && ($this->shipping_dhl_settings['dhl_preferred_day'] == 'yes')) || (isset($this->shipping_dhl_settings['dhl_preferred_location']) && ($this->shipping_dhl_settings['dhl_preferred_location'] == 'yes')) || (isset($this->shipping_dhl_settings['dhl_preferred_neighbour']) && ($this->shipping_dhl_settings['dhl_preferred_neighbour'] == 'yes'))) {
return true;
} else {
return false;
}
}
protected function is_cdp_enabled()
{
if (isset($this->shipping_dhl_settings['dhl_closest_drop_point']) && ($this->shipping_dhl_settings['dhl_closest_drop_point'] === 'yes')) {
return true;
}
return false;
}
public function dhl_add_meta_tags()
{
echo '<meta name="58vffw8g4r9_t3e38g4og588915" content="Yes">';
}
/**
* Localization for NL address fields.
*
* @param array $checkout_fields Checkout fields.
* @return array
*/
public function get_country_locale($checkout_fields)
{
if ($this->is_using_checkout_block()) {
$fields_to_order = [
'pr-dhl/address_type' => ['priority' => 1],
'first_name' => ['priority' => 3],
'last_name' => ['priority' => 4],
'company' => ['priority' => 5],
'country' => ['priority' => 6],
'postcode' => ['priority' => 7],
'shipping_pr_dhl/postnum' => ['priority' => 8],
];
}
foreach ($fields_to_order as $field_key => $field) {
foreach ($field as $override => $value) {
$checkout_fields['DE'][$field_key][$override] = $value;
}
}
/**
* Hide extra fields from the other countries .
*/
$countries_codes = array_keys(WC()->countries->get_countries());
foreach ($countries_codes as $country_code) {
if ($country_code !== 'DE') {
$checkout_fields[$country_code]['pr-dhl/address_type']['hidden'] = true;
$checkout_fields[$country_code]['pr-dhl/address_type']['required'] = false;
$checkout_fields[$country_code]['pr-dhl/postnum']['hidden'] = true;
$checkout_fields[$country_code]['pr-dhl/postnum']['required'] = false;
}
}
return $checkout_fields;
}
public function load_styles_scripts()
{
$is_parcelfinder_enabled = $this->is_parcelfinder_enabled();
if ($this->is_tracking_enabled() && ($this->is_preferredservice_enabled() || $is_parcelfinder_enabled)) {
wp_enqueue_script('pr-dhl-frontend-pixel', PR_DHL_PLUGIN_DIR_URL.'/assets/js/pr-dhl-frontend-pixel.js', [], PR_DHL_VERSION, true);
}
// load scripts on checkout page only
if (! is_checkout()) {
return;
}
$frontend_data = [
'ajax_url' => admin_url('admin-ajax.php'),
'packstation_icon' => PR_DHL_PLUGIN_DIR_URL.'/assets/img/packstation.png',
'parcelshop_icon' => PR_DHL_PLUGIN_DIR_URL.'/assets/img/parcelshop.png',
'post_office_icon' => PR_DHL_PLUGIN_DIR_URL.'/assets/img/post_office.png',
'opening_times' => esc_html__('Opening Times', 'dhl-for-woocommerce'),
'monday' => esc_html__('Monday', 'dhl-for-woocommerce'),
'tueday' => esc_html__('Tuesday', 'dhl-for-woocommerce'),
'wednesday' => esc_html__('Wednesday', 'dhl-for-woocommerce'),
'thrusday' => esc_html__('Thursday', 'dhl-for-woocommerce'),
'friday' => esc_html__('Friday', 'dhl-for-woocommerce'),
'satuday' => esc_html__('Saturday', 'dhl-for-woocommerce'),
'sunday' => esc_html__('Sunday', 'dhl-for-woocommerce'),
'services' => esc_html__('Services', 'dhl-for-woocommerce'),
'yes' => esc_html__('Yes', 'dhl-for-woocommerce'),
'no' => esc_html__('No', 'dhl-for-woocommerce'),
'parking' => esc_html__('Parking', 'dhl-for-woocommerce'),
'handicap' => esc_html__('Handicap Accessible', 'dhl-for-woocommerce'),
'packstation' => PR_DHL_PACKSTATION,
'parcelShop' => PR_DHL_PARCELSHOP,
'postoffice' => PR_DHL_POST_OFFICE,
'branch' => esc_html__('Branch', 'dhl-for-woocommerce'),
'select' => esc_html__('Select ', 'dhl-for-woocommerce'),
'select_drop' => esc_html__('Select a drop-off point', 'dhl-for-woocommerce'),
'post_number' => esc_html__('Post Number ', 'dhl-for-woocommerce'),
'post_number_tip' => esc_html__('<span class="dhl-tooltip" title="Indicate a preferred time, which suits you best for your parcel delivery by choosing one of the displayed time windows.">?</span>', 'dhl-for-woocommerce'),
// Translators: %1$s is an opening HTML tag and %2$s is a closing HTML tag for styling the error message.
'no_api_key' => sprintf(esc_html__('%1$sPlease insert an API Key to enable the display of locations in the frontend on a map.%2$s', 'dhl-for-woocommerce'), '<div class="woocommerce-error">', '</div>'),
'post_code_error' => esc_html__('Please enter a postcode to search locations.', 'dhl-for-woocommerce'),
];
if (! empty($this->shipping_dhl_settings['dhl_payment_gateway'])) {
$frontend_data['cod_enabled'] = true;
} else {
$frontend_data['cod_enabled'] = false;
}
if ($this->is_preferredservice_enabled() || $is_parcelfinder_enabled) {
$frontend_data['map_type'] = $this->get_map_type();
$frontend_data['ship_to_different_address_text'] = esc_html__('Ship to a different address or Packstation/Branch?', 'dhl-for-woocommerce');
// Register and load our styles and scripts
wp_register_script('pr-dhl-checkout-frontend', PR_DHL_PLUGIN_DIR_URL.'/assets/js/pr-dhl-checkout-frontend.js', ['jquery', 'wc-checkout'], PR_DHL_VERSION, true);
wp_localize_script('pr-dhl-checkout-frontend', 'pr_dhl_checkout_frontend', $frontend_data);
wp_enqueue_script('pr-dhl-checkout-frontend');
wp_enqueue_style('pr-dhl-checkout-frontend', PR_DHL_PLUGIN_DIR_URL.'/assets/css/pr-dhl-frontend.css', [], PR_DHL_VERSION);
}
if ($this->is_preferredservice_enabled()) {
// jquery UI for tool tip
wp_enqueue_style('pr-dhl-jquery-ui-style', PR_DHL_PLUGIN_DIR_URL.'/assets/css/jquery-ui-tooltip.css', [], '1.0');
wp_enqueue_script('jquery-effects-core');
wp_enqueue_script('jquery-ui-tooltip');
}
if ($is_parcelfinder_enabled && $this->is_map_enabled()) {
// Enqueue Fancybox
wp_enqueue_script('pr-dhl-fancybox-js', PR_DHL_PLUGIN_DIR_URL.'/assets/js/jquery.fancybox.min.js', ['jquery']);
wp_enqueue_style('pr-dhl-fancybox-css', PR_DHL_PLUGIN_DIR_URL.'/assets/css/jquery.fancybox.min.css', '', PR_DHL_VERSION);
if ($this->get_map_type() === 'osm') {
// Enqueue Leaflet
wp_enqueue_style('leaflet_css', 'https://unpkg.com/leaflet/dist/leaflet.css', '', PR_DHL_VERSION);
wp_enqueue_script('leaflet_js', 'https://unpkg.com/leaflet/dist/leaflet.js', '', PR_DHL_VERSION);
} else {
// Enqueue Google Maps
wp_enqueue_script('pr-dhl-google-maps', 'https://maps.googleapis.com/maps/api/js?key='.$this->shipping_dhl_settings['dhl_google_maps_api_key']);
}
}
}
protected function validate_is_german_customer()
{
$billing_country = WC()->customer ? WC()->customer->get_billing_country() : '';
$shipping_country = WC()->customer ? WC()->customer->get_shipping_country() : '';
$base_country_code = PR_DHL()->get_base_country();
$display_preferred = false;
// Preferred options are only for Germany customers
if ($base_country_code == 'DE' && ($shipping_country == 'DE' || $billing_country == 'DE')) {
return true;
} else {
return false;
}
}
public function validate_extra_services_available($check_day_transfer = false)
{
// woocommerce_form_field('pr_dhl_paket_preferred_location');
$chosen_shipping_methods = WC()->session->get('chosen_shipping_methods');
$chosen_payment_method = WC()->session->get('chosen_payment_method');
$display_preferred = false;
// Preferred options are only for Germany customers
if ($this->validate_is_german_customer()) {
if ($check_day_transfer) {
foreach (WC()->cart->get_cart() as $cart_item_key => $values) {
$same_day_transfer = get_post_meta($values['product_id'], '_dhl_no_same_day_transfer', true);
// If one of the products cannot be transferred same day then don't show preferred services
if ($same_day_transfer == 'yes') {
return false;
}
}
}
if (! isset($this->shipping_dhl_settings) || empty($this->shipping_dhl_settings['dhl_shipping_methods'])) {
throw new Exception(esc_html__('No shipping method enabled.', 'dhl-for-woocommerce'));
}
$wc_methods_dhl = $this->shipping_dhl_settings['dhl_shipping_methods'];
if (isset($chosen_shipping_methods)) {
if (is_array($chosen_shipping_methods)) {
foreach ($chosen_shipping_methods as $key => $value) {
$ship_method_slug = $this->get_shipping_method_slug($value);
if (in_array($ship_method_slug, $wc_methods_dhl)) {
$display_preferred = true;
break;
}
}
} else {
$ship_method_slug = $this->get_shipping_method_slug($chosen_shipping_methods);
if (in_array($ship_method_slug, $wc_methods_dhl)) {
$display_preferred = true;
}
}
}
$wc_payment_dhl = $this->shipping_dhl_settings['dhl_payment_gateway'];
if (isset($chosen_payment_method) && ! empty($wc_payment_dhl)) {
if (is_array($chosen_payment_method)) {
foreach ($chosen_payment_method as $key => $value) {
// $ship_method_slug = $this->get_shipping_method_slug( $value );
if (in_array($value, $wc_payment_dhl)) {
throw new Exception(esc_html__('Payment gateway excluded.', 'dhl-for-woocommerce'));
}
}
} else {
// $ship_method_slug = $this->get_shipping_method_slug( $chosen_payment_method );
if (in_array($chosen_payment_method, $wc_payment_dhl)) {
throw new Exception(esc_html__('Payment gateway excluded.', 'dhl-for-woocommerce'));
}
}
}
}
// if reached here and not enabled then it's due to the selected shipping method not being set for DHL services
if (! $display_preferred) {
throw new Exception(esc_html__('Not enabled for selected shipping method.', 'dhl-for-woocommerce'));
}
return $display_preferred;
}
protected function validate_cdp_available()
{
$shipping_country = WC()->customer->get_shipping_country();
$valid_countries = ['SE', 'FI', 'BE', 'AT', 'FR'];
if (in_array($shipping_country, $valid_countries)) {
// Check if COD payment gateway selected
$wc_payment_dhl = $this->shipping_dhl_settings['dhl_payment_gateway'];
$chosen_payment_method = WC()->session->get('chosen_payment_method');
if (isset($chosen_payment_method) && ! empty($wc_payment_dhl)) {
if (is_array($chosen_payment_method)) {
foreach ($chosen_payment_method as $key => $value) {
if (in_array($value, $wc_payment_dhl)) {
return false;
}
}
} elseif (in_array($chosen_payment_method, $wc_payment_dhl)) {
return false;
}
}
return true;
}
return false;
}
public function add_preferred_fields()
{
try {
$display_preferred = $this->validate_extra_services_available(true);
if ($display_preferred == true) {
$template_args = [];
if (isset($_POST['post_data'])) {
parse_str($_POST['post_data'], $post_data);
foreach ($this->preferred_services as $key => $value) {
if (isset($post_data[$key])) {
// array_push($template_args, $post_data[ $key ] );
$template_args[$key.'_selected'] = wc_clean($post_data[$key]);
}
}
}
if (isset($this->shipping_dhl_settings['dhl_preferred_day']) && ($this->shipping_dhl_settings['dhl_preferred_day'] == 'yes')) {
if (isset($_POST['s_postcode'])) {
$shipping_postcode = wc_clean($_POST['s_postcode']);
$template_args['preferred_day_time'] = PR_DHL()->get_dhl_preferred_day_time($shipping_postcode);
// Place preferred day and time in session, as to not call the API after placing an order unnecessarily
WC()->session->set('dhl_preferred_day_time', $template_args['preferred_day_time']);
}
}
wc_get_template('checkout/dhl-preferred-services.php', $template_args, '', PR_DHL_PLUGIN_DIR_PATH.'/templates/');
}
} catch (Exception $e) {
// do nothing
}
}
public function add_cdp_fields()
{
if ($this->validate_cdp_available()) {
wc_get_template('checkout/dhl-closest-drop-point.php', [], '', PR_DHL_PLUGIN_DIR_PATH.'/templates/');
}
}
public function add_cart_fees($cart)
{
if (! $_POST || (is_admin() && ! is_ajax())) {
return;
}
// POST information is either in a query string-like variable called 'post_data'...
if (isset($_POST['post_data'])) {
parse_str($_POST['post_data'], $post_data);
} else {
$post_data = $_POST; // ... else it is in the POST variable itself
}
try {
if (! isset($this->shipping_dhl_settings)) {
return;
}
if (! empty($post_data['pr_dhl_preferred_day'])) {
if (! empty($this->shipping_dhl_settings['dhl_preferred_day_cost'])) {
$cart->add_fee(esc_html__('DHL Delivery Day', 'dhl-for-woocommerce'), wc_format_decimal($this->shipping_dhl_settings['dhl_preferred_day_cost']));
}
}
/*
if( ! empty( $this->shipping_dhl_settings['dhl_cod_fee'] ) && $this->shipping_dhl_settings['dhl_cod_fee'] == 'yes' && isset( $post_data['payment_method'] ) && $post_data['payment_method'] == 'cod' ) {
// Add €2 fee to COD usage (Euro is being assumed as currency)
$cart->add_fee( esc_html__('DHL COD fee', 'dhl-for-woocommerce'), 2 );
}*/
} catch (Exception $e) {
// do nothing
}
}
public function verify_preferred_services_fields()
{
// save the posted preferences to the order so can be used when generating label
$dhl_label_options = [];
if (! isset($_POST)) {
return $dhl_label_options;
}
foreach ($this->preferred_services as $key => $value) {
if (! empty($_POST[$key])) {
$dhl_label_options[$key] = wc_clean($_POST[$key]);
}
}
if (isset($dhl_label_options)) {
if (isset($dhl_label_options['pr_dhl_preferred_location_neighbor'])) {
if (($dhl_label_options['pr_dhl_preferred_location_neighbor'] == 'preferred_location') && (! isset($dhl_label_options['pr_dhl_preferred_location']))) {
throw new Exception(esc_html__('Please enter the preferred location.', 'dhl-for-woocommerce'));
}
if (($dhl_label_options['pr_dhl_preferred_location_neighbor'] == 'preferred_neighbor') && (! isset($dhl_label_options['pr_dhl_preferred_neighbour_name']) || ! isset($dhl_label_options['pr_dhl_preferred_neighbour_address']))) {
throw new Exception(esc_html__('Please enter the preferred neighbor name and address.', 'dhl-for-woocommerce'));
}
}
}
return $dhl_label_options;
}
public function process_dhl_preferred_fields($order_id, $posted)
{
// save the posted preferences to the order so can be used when generating label
$dhl_label_options = $this->verify_preferred_services_fields();
if (! empty($dhl_label_options)) {
PR_DHL()->get_pr_dhl_wc_order()->save_dhl_label_items($order_id, $dhl_label_options);
}
}
public function prepare_cdp_fields()
{
// save the posted preferences to the order so can be used when generating label
$dhl_label_options = [];
if (! isset($_POST)) {
return $dhl_label_options;
}
foreach ($this->cdp_service as $key => $value) {
if (! empty($_POST[$key])) {
$dhl_label_options[$key] = wc_clean($_POST[$key]);
}
}
return $dhl_label_options;
}
public function process_cdp_fields($order_id, $posted)
{
// save the posted preferences to the order so can be used when generating label
$dhl_label_options = $this->prepare_cdp_fields();
if (! empty($dhl_label_options)) {
PR_DHL()->get_pr_dhl_wc_order()->save_dhl_label_items($order_id, $dhl_label_options);
}
}
private function get_shipping_method_slug($ship_method)
{
if (empty($ship_method)) {
return $ship_method;
}
// Assumes format 'name:id'
$new_ship_method = explode(':', $ship_method);
$new_ship_method = isset($new_ship_method[0]) ? $new_ship_method[0] : $ship_method;
return $new_ship_method;
}
public function display_dhl_preferred_free_services_values($total_rows, $order)
{
$order_id = $order->get_id();
$dhl_label_options = PR_DHL()->get_pr_dhl_wc_order()->get_dhl_label_items($order_id);
if (isset(WC()->session)) {
$preferred_day_time = WC()->session->get('dhl_preferred_day_time');
$new_rows = [];
foreach ($this->preferred_services as $key => $value) {
if (! empty($dhl_label_options[$key])) {
// NEED TO PLACE THESE ROWS BEFORE THE PAYMENT METHOD
$new_rows[$key]['label'] = $value.':';
if (isset($this->preferred_location_neighbor[$dhl_label_options[$key]])) {
$new_rows[$key]['value'] = $this->preferred_location_neighbor[$dhl_label_options[$key]];
} else {
$new_rows[$key]['value'] = $dhl_label_options[$key];
}
}
}
if (! empty($new_rows)) {
// Instert before payment method
$insert_before = array_search('payment_method', array_keys($total_rows));
// If no payment method, insert before order total
if (empty($insert_before)) {
$insert_before = array_search('order_total', array_keys($total_rows));
}
if (empty($insert_before)) {
$total_rows += $new_rows;
} else {
$this->array_insert($total_rows, $insert_before, $new_rows);
}
}
}
return $total_rows;
}
private function array_insert(&$array, $position, $insert_array)
{
$first_array = array_splice($array, 0, $position);
$array = array_merge($first_array, $insert_array, $array);
}
public function add_parcel_finder_btn()
{
if (! $this->is_map_enabled()) {
return;
}
$dhl_logo = PR_DHL_PLUGIN_DIR_URL.'/assets/img/dhl-official.png';
echo '<a data-fancybox id="dhl_parcel_finder" class="button" data-src="#dhl_parcel_finder_form" href="javascript:;">'.$this->get_branch_location_text().'<img src="'.esc_url($dhl_logo).'" class="dhl-co-logo"></a>';
}
protected function get_branch_location_text()
{
$button_text = '';
if ($this->is_parcelshop_enabled() || $this->is_post_office_enabled()) {
// $button_text = esc_html__('Search Packstation / Branch', 'dhl-for-woocommerce')
$button_text = esc_html__('Branch', 'dhl-for-woocommerce');
}
if ($this->is_packstation_enabled()) {
if (! empty($button_text)) {
$button_text = esc_html__(' / ', 'dhl-for-woocommerce').$button_text;
}
$button_text = esc_html__('Packstation', 'dhl-for-woocommerce').$button_text;
}
$button_text = esc_html__('Search ', 'dhl-for-woocommerce').$button_text;
return $button_text;
}
public function add_parcel_finder_form()
{
$template_args = [];
$template_args['packstation_img'] = PR_DHL_PLUGIN_DIR_URL.'/assets/img/packstation.png';
$template_args['parcelshop_img'] = PR_DHL_PLUGIN_DIR_URL.'/assets/img/parcelshop.png';
$template_args['post_office_img'] = PR_DHL_PLUGIN_DIR_URL.'/assets/img/post_office.png';
$template_args['packstation_enabled'] = $this->is_packstation_enabled();
$template_args['parcelshop_enabled'] = $this->is_parcelshop_enabled();
$template_args['post_office_enabled'] = $this->is_post_office_enabled();
wc_get_template('checkout/dhl-parcel-finder.php', $template_args, '', PR_DHL_PLUGIN_DIR_PATH.'/templates/');
}
public function call_parcel_finder()
{
check_ajax_referer('dhl_parcelfinder', 'security');
$parcelfinder_country = isset($_POST['parcelfinder_country']) ? wc_clean(wp_unslash($_POST['parcelfinder_country'])) : '';
$parcelfinder_postcode = isset($_POST['parcelfinder_postcode']) ? wc_clean(wp_unslash($_POST['parcelfinder_postcode'])) : '';
$parcelfinder_city = isset($_POST['parcelfinder_city']) ? wc_clean(wp_unslash($_POST['parcelfinder_city'])) : '';
$parcelfinder_address = isset($_POST['parcelfinder_address']) ? wc_clean(wp_unslash($_POST['parcelfinder_address'])) : '';
$packstation_filter = isset($_POST['packstation_filter']) ? wc_clean(wp_unslash($_POST['packstation_filter'])) : '';
$branch_filter = isset($_POST['branch_filter']) ? wc_clean(wp_unslash($_POST['branch_filter'])) : '';
try {
$dhl_obj = PR_DHL()->get_dhl_factory();
$args['dhl_settings']['api_user'] = $this->shipping_dhl_settings['dhl_api_user'];
$args['dhl_settings']['api_pwd'] = $this->shipping_dhl_settings['dhl_api_pwd'];
$args['dhl_settings']['sandbox'] = $this->shipping_dhl_settings['dhl_sandbox'];
$args['shipping_address']['address'] = $parcelfinder_address;
$args['shipping_address']['postcode'] = $parcelfinder_postcode;
$args['shipping_address']['city'] = $parcelfinder_city;
$args['shipping_address']['country'] = $parcelfinder_country;
$args['dhl_parcel_limit'] = $this->shipping_dhl_settings['dhl_parcel_limit'];
$args['dhl_packstation_filter'] = $packstation_filter;
$args['dhl_branch_filter'] = $branch_filter;
$parcel_res = $dhl_obj->get_parcel_location($args);
if (! isset($parcel_res->locations)) {
throw new Exception(esc_html__('No parcel shops found', 'dhl-for-woocommerce'));
}
$res_count = 0;
$parcel_res_filtered = [];
foreach ($parcel_res->locations as $key => $value) {
if (($this->is_packstation_enabled() &&
($packstation_filter == 'true') &&
($value->location->type == 'locker')) ||
($this->is_parcelshop_enabled() &&
($branch_filter == 'true') &&
($value->location->type == 'servicepoint')) ||
($this->is_post_office_enabled() &&
($branch_filter == 'true') &&
($value->location->type == 'postoffice' || $value->location->type == 'postbank'))) {
if ($value->serviceTypes) {
if (is_array($value->serviceTypes)) {
foreach ($value->serviceTypes as $service_type) {
// Only display shops that accept parcels.
// Not needed 'parcelacceptance'
if (in_array($service_type, ['parcel:pick-up', 'parcel:pick-up-unregistered', 'parcel:pick-up-registered'])) {
array_push($parcel_res_filtered, $value);
$res_count++;
break;
}
}
} elseif (in_array($value->serviceTypes, ['parcel:pick-up', 'parcel:pick-up-unregistered', 'parcel:pick-up-registered'])) {
array_push($parcel_res_filtered, $value);
$res_count++;
}
}
}
if ($res_count == $this->shipping_dhl_settings['dhl_parcel_limit']) {
break;
}
}
if (empty($parcel_res_filtered)) {
throw new Exception(esc_html__('No Parcel Shops found. Ensure "Packstation" or Branch" filter is checked ', 'dhl-for-woocommerce'));
}
wp_send_json(
[
'parcel_res' => $parcel_res_filtered,
// 'tracking_note' => $tracking_note
]
);
} catch (Exception $e) {
wp_send_json(['error' => $e->getMessage()]);
}
wp_die();
}
protected function is_parcelfinder_enabled()
{
if ($this->is_packstation_enabled() || $this->is_parcelshop_enabled() || $this->is_post_office_enabled()) {
return true;
} else {
return false;
}
}
/**
* Is Location Finder map enabled?
*
* @return bool
*/
protected function is_map_enabled()
{
if ((isset($this->shipping_dhl_settings['dhl_display_google_maps']) &&
($this->shipping_dhl_settings['dhl_display_google_maps'] == 'yes'))) {
return true;
}
return false;
}
/**
* Get Location Finder map type.
*
* @return string
*/
protected function get_map_type()
{
if ((isset($this->shipping_dhl_settings['dhl_map_type']) &&
($this->shipping_dhl_settings['dhl_map_type'] === 'osm'))) {
return 'osm';
}
return 'gmaps';
}
protected function is_packstation_enabled()
{
if ((isset($this->shipping_dhl_settings['dhl_display_packstation']) &&
($this->shipping_dhl_settings['dhl_display_packstation'] == 'yes'))) {
return true;
} else {
return false;
}
}
protected function is_parcelshop_enabled()
{
if ((isset($this->shipping_dhl_settings['dhl_display_parcelshop']) &&
($this->shipping_dhl_settings['dhl_display_parcelshop'] == 'yes'))) {
return true;
} else {
return false;
}
}
protected function is_post_office_enabled()
{
if ((isset($this->shipping_dhl_settings['dhl_display_post_office']) &&
($this->shipping_dhl_settings['dhl_display_post_office'] == 'yes'))) {
return true;
} else {
return false;
}
}
protected function is_email_notification_enabled()
{
if ((isset($this->shipping_dhl_settings['dhl_email_notification']) &&
($this->shipping_dhl_settings['dhl_email_notification'] == 'yes'))) {
return true;
} else {
return false;
}
}
public function add_postnum_field($checkout_fields)
{
$types = [
'normal' => esc_html__('Regular Address', 'dhl-for-woocommerce'),
];
if ($this->is_packstation_enabled()) {
$types['dhl_packstation'] = esc_html__('DHL Packstation', 'dhl-for-woocommerce');
}
if ($this->is_post_office_enabled()) {
$types['dhl_branch'] = esc_html__('DHL Branch', 'dhl-for-woocommerce');
}
$points = [
'' => esc_html__('Select a drop-off point', 'dhl-for-woocommerce'),
];
$shipping_dhl_address_type = [
'label' => esc_html__('Address Type', 'dhl-for-woocommerce'),
'required' => true,
'type' => 'select',
'class' => ['form-row-first shipping-dhl-address-type'],
'input_class' => ['select2-full-width'],
'clear' => true,
'default' => 'normal',
'options' => $types,
];
$shipping_dhl_postnum_branch = [
'label' => esc_html__('Post Number', 'dhl-for-woocommerce'),
'required' => false,
'type' => 'text',
'class' => ['shipping-dhl-postnum'],
'clear' => true,
];
$shipping_dhl_drop_off = [
'label' => __('Drop off points', 'dhl-for-woocommerce'),
'required' => false,
'type' => 'select',
'class' => ['form-row-last shipping-dhl-drop-off-points'],
'input_class' => ['select2-full-width'],
'clear' => true,
'default' => 'normal',
'options' => $points,
];
$new_shipping_fields = [];
foreach ($checkout_fields['shipping'] as $key => $field) {
if ($key === 'shipping_first_name') {
$new_shipping_fields['shipping_dhl_address_type'] = $shipping_dhl_address_type;
$new_shipping_fields['shipping_dhl_drop_off'] = $shipping_dhl_drop_off;
}
if ($key === 'shipping_address_1') {
$new_shipping_fields['shipping_dhl_postnum'] = $shipping_dhl_postnum_branch;
}
$new_shipping_fields[$key] = $field;
}
if (empty($new_shipping_fields)) {
$new_shipping_fields['shipping_dhl_address_type'] = $shipping_dhl_address_type;
$new_shipping_fields['shipping_dhl_drop_off'] = $shipping_dhl_drop_off;
$new_shipping_fields['shipping_dhl_postnum'] = $shipping_dhl_postnum_branch;
$new_shipping_fields = array_merge($new_shipping_fields, $checkout_fields['shipping']);
}
// Update the checkout fields array
$checkout_fields['shipping'] = $new_shipping_fields;
return $checkout_fields;
}
public function admin_order_add_postnum_field($fields)
{
$shipping_dhl_postnum_branch = [
'label' => esc_html__('Post Number', 'dhl-for-woocommerce'),
'required' => false,
'type' => 'text',
'class' => 'shipping-dhl-postnum',
'clear' => true,
'show' => false,
];
if ($new_shipping_fields = $this->array_insert_before('address_1', $fields, 'dhl_postnum', $shipping_dhl_postnum_branch)) {
$fields = $new_shipping_fields;
}
return $fields;
}
public function add_email_notification_checkbox()
{
if ($this->validate_is_german_customer()) {
woocommerce_form_field(
'pr_dhl_email_notification',
[
'type' => 'checkbox',
'class' => ['pr-dhl-email-notification form-row-wide'],
'label' => esc_html__('Activate Shipment Notification. When activated DHL will inform you via email about the shipment status of your order.', 'dhl-for-woocommerce'),
],
'yes'
);
}
}
public function process_email_notification_fields($order_id, $posted)
{
$dhl_label_items = PR_DHL()->get_pr_dhl_wc_order()->get_dhl_label_items($order_id);
if (isset($_POST['pr_dhl_email_notification'])) {
if (! is_array($dhl_label_items)) {
$dhl_label_items = [];
}
$dhl_label_items['pr_dhl_email_notification'] = $_POST['pr_dhl_email_notification'];
PR_DHL()->get_pr_dhl_wc_order()->save_dhl_label_items($order_id, $dhl_label_items);
}
}
/*
* Inserts a new key/value before the key in the array.
*
* @param $key
* The key to insert before.
* @param $array
* An array to insert in to.
* @param $new_key
* The key to insert.
* @param $new_value
* An value to insert.
*
* @return
* The new array if the key exists, FALSE otherwise.
*
* @see array_insert_after()
*/
private function array_insert_before($key, array &$array, $new_key, $new_value)
{
if (array_key_exists($key, $array)) {
$new = [];
foreach ($array as $k => $value) {
if ($k === $key) {
$new[$new_key] = $new_value;
}
$new[$k] = $value;
}
return $new;
}
return false;
}
public function validate_post_number()
{
// Validate input only if "ship to different address" flag is set
if (! isset($_POST['ship_to_different_address'])) {
return;
}
$shipping_dhl_address_type = wc_clean(wp_unslash($_POST['shipping_dhl_address_type'] ?? ''));
$shipping_address_1 = wc_clean(wp_unslash($_POST['shipping_address_1'] ?? ''));
$shipping_dhl_postnum = wc_clean(wp_unslash($_POST['shipping_dhl_postnum'] ?? ''));
$pos_ps = PR_DHL()->is_packstation($shipping_address_1);
$pos_rs = PR_DHL()->is_parcelshop($shipping_address_1);
$pos_po = PR_DHL()->is_post_office($shipping_address_1);
if (! empty($shipping_dhl_address_type) && $shipping_dhl_address_type != 'normal') {
// check shipping method and payment gateway first
try {
$this->validate_extra_services_available();
} catch (Exception $e) {
wc_add_notice(esc_html__('"DHL Locations" cannot be used - ', 'dhl-for-woocommerce').$e->getMessage(), 'error');
return;
}
}
if ($shipping_dhl_address_type == 'dhl_packstation') {
if (empty($shipping_dhl_postnum)) {
wc_add_notice(esc_html__('Post Number is mandatory for a Packstation location.', 'dhl-for-woocommerce'), 'error');
return;
}
if (! $pos_ps) {
// Translators: %s is the text that must be included in the address (e.g., a specific keyword or phrase).
wc_add_notice(sprintf(esc_html__('The text "%s" must be included in the address.', 'dhl-for-woocommerce'), PR_DHL_PACKSTATION), 'error');
return;
}
} elseif ($shipping_dhl_address_type == 'dhl_branch') {
if (! $pos_rs) {
// Translators: %s is the text that must be included in the address (e.g., a specific keyword or phrase).
wc_add_notice(sprintf(esc_html__('The text "%s" must be included in the address.', 'dhl-for-woocommerce'), PR_DHL_PARCELSHOP), 'error');
return;
}
if (! $pos_po) {
// Translators: %s is the text that must be included in the address (e.g., a specific keyword or phrase).
wc_add_notice(sprintf(esc_html__('The text "%s" must be included in the address.', 'dhl-for-woocommerce'), PR_DHL_POST_OFFICE), 'error');
return;
}
}
// Post Number only applies to Packstation / Postfiliale, not a Regular Address.
if (! empty($shipping_dhl_postnum) && PR_DHL()->is_droppoint_address_type($shipping_dhl_address_type)) {
if (! is_numeric($shipping_dhl_postnum)) {
wc_add_notice(esc_html__('Post Number must be a number.', 'dhl-for-woocommerce'), 'error');
return;
}
$post_num_len = strlen($shipping_dhl_postnum);
if ($post_num_len < 6 || $post_num_len > 12) {
wc_add_notice(esc_html__('The post number you entered is not valid. Please correct the number.', 'dhl-for-woocommerce'), 'error');
return;
}
}
}
/**
* Clear a stale DHL Post Number when a Regular Address is selected.
*
* The Post Number only applies to Packstation / Parcelshop / Postfiliale deliveries.
* If a customer entered one and then switched to a Regular Address, drop the value so
* it is not persisted on the order or sent to the DHL API. Mirrors the Blocks checkout,
* which clears the field client-side on the same switch. The value is kept whenever
* either the selected address type or the shipping address itself is a droppoint, since
* that is how it is consumed downstream.
*
* @param int $order_id Order ID.
* @param array $posted Sanitized posted checkout data.
*/
public function clear_post_number_for_regular_address($order_id, $posted)
{
// An absent or empty address type means Regular Address — e.g. when shipping to the
// billing address, the shipping_* fields are not posted — so still treat it as a clear
// candidate (the droppoint-address check below protects values the label still needs).
$address_type = isset($posted['shipping_dhl_address_type']) ? $posted['shipping_dhl_address_type'] : '';
$order = wc_get_order($order_id);
if (! $order) {
return;
}
// Keep the Post Number for droppoints — by the selected address type or by the shipping
// address itself, which is how it is consumed downstream — so a value the label still
// needs is never dropped, even if the address-type field says otherwise.
if (PR_DHL()->is_droppoint($address_type, $order->get_shipping_address_1())) {
return;
}
if (! empty($order->get_meta('_shipping_dhl_postnum'))) {
$order->delete_meta_data('_shipping_dhl_postnum');
$order->save();
}
}
public function display_post_number($address, $order)
{
if (PR_DHL()->is_droppoint_address($address['address_1']) &&
(! empty($shipping_dhl_postnum = $order->get_meta('_shipping_dhl_postnum')))) {
$address['dhl_postnum'] = $shipping_dhl_postnum;
}
return $address;
}
public function set_format_post_number($formats)
{
$is_store_api = defined('REST_REQUEST') && REST_REQUEST
&& ! empty($_SERVER['REQUEST_URI'])
&& strpos($_SERVER['REQUEST_URI'], '/wc/store/') !== false;
$is_blocks_checkout = function_exists('is_checkout') && is_checkout()
&& method_exists($this, 'is_using_checkout_block')
&& $this->is_using_checkout_block();
if ($is_store_api || $is_blocks_checkout) {
return $formats;
}
foreach ($formats as $key => $value) {
$count = 0;
// use double quotes to find "\n" othewise treated as 2 chars
$format_replaced = str_replace("\n{address_1}", "\n{dhl_postnum}\n{address_1}", $value, $count);
// Only change format if "address_1 found"
if ($count) {
$formats[$key] = $format_replaced;
}
}
return $formats;
}
public function add_format_post_number($address_format, $args)
{
// $address_format['{dhl_postnum}'] must be set, even if empty as to not display on the frontend as '{dhl_postnum}'
if (isset($args['dhl_postnum'])) {
$address_format['{dhl_postnum}'] = $args['dhl_postnum'];
} else {
$address_format['{dhl_postnum}'] = '';
}
return $address_format;
}
}
}