Files
2026-04-28 15:13:50 +02:00

644 lines
22 KiB
PHP

<?php
use FS\InPost\PickupPoints\PickupPointDetails;
use FS\InPost\PickupPoints\PickupPointsManager;
/**
* Class WPDesk_Paczkomaty_Checkout
*/
class WPDesk_Paczkomaty_Checkout {
const SHIPPING_METOD_SERVICE = 'paczkomaty_usluga';
const FIELD_PACZKOMAT_ID = 'paczkomat_id';
const PRIORITY_FIRST = -10;
/**
* Plugin.
*
* @var WPDesk_Paczkomaty_Plugin
*/
private $plugin;
/**
* @var array
*/
public $machines = [];
/**
* @var array
*/
public $machinesInfo = [];
/**
* @var array
*/
public $allMachines = [];
/**
* @var array
*/
public $adminMachines = [];
/**
* @var PickupPointsManager
*/
private $pickup_points_manager;
/**
* @var bool
*/
private $already_displayed = false;
/**
* @var string
*/
private $already_displayed_for_package_id = '';
/**
* @var string
*/
private $already_displayed_on_action = '';
/**
* WPDesk_Paczkomaty_Checkout constructor.
*
* @param WPDesk_Paczkomaty_Plugin $plugin .
* @param PickupPointsManager $pickup_points_manager .
*/
public function __construct( WPDesk_Paczkomaty_Plugin $plugin, PickupPointsManager $pickup_points_manager ) {
$this->plugin = $plugin;
$this->pickup_points_manager = $pickup_points_manager;
}
/**
*
*/
public function hooks() {
add_action( 'woocommerce_after_checkout_validation', [
$this,
'validate_selected_point_on_paczkomaty_shipping_method',
], self::PRIORITY_FIRST );
add_action( 'woocommerce_checkout_process', [ $this, 'save_paczkomat_id_in_session_on_checkout' ] );
add_action( 'woocommerce_checkout_update_order_review', [
$this,
'woocommerce_checkout_update_order_review',
] );
add_action( 'woocommerce_checkout_init', [
$this,
'init_checkout_hooks'
] );
add_action( 'woocommerce_checkout_update_order_review', [
$this,
'init_checkout_hooks',
] );
add_action( 'woocommerce-paczkomaty-inpost/pickup-point-selection', [ $this, 'display_choose_machine_field' ] );
add_filter( 'paczkomaty_shipping_method_admin_machines', [
$this,
'paczkomaty_shipping_method_admin_machines',
], 10, 2 );
add_filter( 'paczkomaty_paczkomaty_options_admin', [ $this, 'paczkomaty_paczkomaty_options_admin' ] );
add_filter( 'woocommerce_update_order_review_fragments', [ $this, 'reset_checkout' ], self::PRIORITY_FIRST );
add_action( 'wp_enqueue_scripts', [ $this, 'enqueue_scripts' ] );
}
/**
* @internal
*/
public function enqueue_scripts() {
$add_scripts =
/**
* Filter if add inpost scripts.
*
* @param bool $add_scripts If should add inpost scripts to page.
*/
apply_filters( 'woocommerce_paczkomaty_inpost/add_scripts', false );
if ( $add_scripts || is_checkout() ) {
$settings = $this->plugin->get_shipping_method_settings();
if ( ! isset( $settings['select_type'] ) ) {
$settings['select_type'] = 'select2_ajax';
}
wp_register_script(
'paczkomaty_front',
trailingslashit( $this->plugin->get_plugin_assets_url() ) . 'dist/js/checkout.js',
[ 'selectWoo' ],
$this->plugin->scripts_version,
false
);
$localize_data = $this->plugin->get_localization_script_data();
$localize_data['settings']['select_type'] = $settings['select_type'];
wp_localize_script( 'paczkomaty_front', 'paczkomaty', $localize_data );
wp_enqueue_script( 'paczkomaty_front' );
wp_enqueue_style(
'paczkomaty_front',
trailingslashit( $this->plugin->get_plugin_assets_url() ) . 'dist/css/checkout.css',
[ 'select2' ],
$this->plugin->scripts_version
);
wp_enqueue_script(
'paczkomaty_geowidget',
'https://geowidget.easypack24.net/js/sdk-for-javascript.js',
[],
$this->plugin->scripts_version,
false
);
wp_enqueue_style( 'paczkomaty_geowidget', 'https://geowidget.easypack24.net/css/easypack.css', [], $this->plugin->scripts_version );
}
}
/**
* @param array $fragments
*
* @return array
* @internal
*/
public function reset_checkout( $fragments ) {
$this->already_displayed = false;
$this->init_checkout_hooks();
return $fragments;
}
/**
* @return void
*
* @internal
*/
public function init_checkout_hooks() {
if ( $this->get_select_placement() === WC_Paczkomaty_Shipping_Method::OPTION_INSERT_INTO_SECTION ) {
if ( ! has_action( 'woocommerce_after_shipping_rate', [
$this,
'display_choose_machine_field_after_shipping_rate'
] ) ) {
add_action( 'woocommerce_after_shipping_rate', [
$this,
'display_choose_machine_field_after_shipping_rate'
], 10, 2 );
}
} else {
$this->add_actions_for_other_placements();
}
}
/**
* @param array $paczkomaty_options
*
* @return array
*/
public function paczkomaty_paczkomaty_options_admin( $paczkomaty_options ) {
$this->init_machine_list();
$paczkomaty_options = $this->adminMachines;
return $paczkomaty_options;
}
/**
* Validate selected point and how notice on failure.
*
* @throws Exception .
* @throws WPDesk_Paczkomaty_ShipX_Exception .
*/
public function validate_selected_point_on_paczkomaty_shipping_method() {
if ( WC()->cart->needs_shipping() ) {
$shipping_methods = $this->flexible_shipping_methods_selected_in_cart( WPDesk_Paczkomaty_FS::SHIPPING_METHOD_INTEGRATION );
foreach ( $shipping_methods as $shipping_method ) {
if ( isset( $shipping_method[ self::SHIPPING_METOD_SERVICE ] )
&& WC_Paczkomaty_Shipping_Method::USLUGA_PACZKOMATY === $shipping_method[ self::SHIPPING_METOD_SERVICE ]
) {
if ( empty( $_POST[ self::FIELD_PACZKOMAT_ID ] ) ) { // phpcs:ignore
if ( ! wc_has_notice( __( 'Proszę wybrać paczkomat', 'woocommerce-paczkomaty-inpost' ), 'error' ) ) {
wc_add_notice( __( 'Proszę wybrać paczkomat', 'woocommerce-paczkomaty-inpost' ), 'error', array('id' => 'paczkomat_id_field') );
}
} else {
$paczkomat_id = $_POST[ self::FIELD_PACZKOMAT_ID ]; // phpcs:ignore
$this->validate_point_and_add_notice( sanitize_text_field( $paczkomat_id ), $shipping_method );
}
}
}
}
}
/**
* Returns FS methods selected in cart.
*
* @param string $shipping_method_integration .
*
* @return array
*/
private function flexible_shipping_methods_selected_in_cart( $shipping_method_integration ) {
$shipping_methods = [];
$chosen_shipping_methods = $this->get_filtered_chosen_shipping_methods();
if ( is_array( $chosen_shipping_methods ) ) {
$all_shipping_methods = flexible_shipping_get_all_shipping_methods();
$flexible_shipping = $all_shipping_methods['flexible_shipping'];
$flexible_shipping_rates = $flexible_shipping->get_all_rates();
foreach ( $chosen_shipping_methods as $id => $shipping ) {
if ( isset( $flexible_shipping_rates[ $shipping ] ) ) {
$shipping_method = $flexible_shipping_rates[ $shipping ];
if ( $shipping_method['method_integration'] === $shipping_method_integration ) {
$shipping_methods[] = $shipping_method;
}
}
}
}
return $shipping_methods;
}
/**
* Saves paczkomat id in session on checkout process.
*/
public function save_paczkomat_id_in_session_on_checkout() {
if ( isset( $_POST[ self::FIELD_PACZKOMAT_ID ] ) ) { // phpcs:ignore
WC()->session->set( self::FIELD_PACZKOMAT_ID, sanitize_text_field( $_POST[ self::FIELD_PACZKOMAT_ID ] ) ); // phpcs:ignore
}
}
/**
* .
* @param string $parcel_machine_id .
* @param array $shipping_method .
*
* @throws Exception .
* @throws WPDesk_Paczkomaty_ShipX_Exception .
*/
private function validate_point_and_add_notice( $parcel_machine_id, array $shipping_method ) {
try {
$point = $this->pickup_points_manager->get_point_details( $parcel_machine_id );
$this->validate_point_cod_if_enabled_and_add_notice( $point, $shipping_method );
$this->validate_point_end_of_week_collection_if_enabled_and_add_notice( $point, $shipping_method );
} catch ( Exception $e ) {
wc_add_notice( $e->getMessage(), 'error' );
}
}
/**
* Validate point cod if enabled.
*
* @param PickupPointDetails $point .
* @param array $shipping_method .
*/
private function validate_point_cod_if_enabled_and_add_notice( $point, $shipping_method ) {
if ( '1' === $shipping_method[ WPDesk_Paczkomaty_FS::SETTING_COD ] ) {
if ( ! $point->is_payment_available() ) {
wc_add_notice( __( 'Wybrany punkt nie obsługuje płatności.', 'woocommerce-paczkomaty-inpost' ), 'error' );
}
}
}
/**
* Validate end of week collection if enabled.
* End of week collection is available only on parcel machines.
*
* @param PickupPointDetails $point .
* @param array $shipping_method .
*/
private function validate_point_end_of_week_collection_if_enabled_and_add_notice( $point, $shipping_method ) {
if ( isset( $shipping_method[ WPDesk_Paczkomaty_FS::SETTING_END_OF_WEEK_COLLECTION ] )
&& '1' === $shipping_method[ WPDesk_Paczkomaty_FS::SETTING_END_OF_WEEK_COLLECTION ]
) {
if ( ! in_array( 'parcel_locker', $point->get_type(), true ) ) {
wc_add_notice( __( 'Paczka w weekend dostępna jest wyłącznie dla przesyłek do paczkomatów.', 'woocommerce-paczkomaty-inpost' ), 'error' );
}
}
}
/**
* @param $post_data
*/
public function woocommerce_checkout_update_order_review( $post_data ) {
parse_str( $post_data, $data );
if ( isset( $data[ self::FIELD_PACZKOMAT_ID ] ) ) {
WC()->session->set( self::FIELD_PACZKOMAT_ID, $data[ self::FIELD_PACZKOMAT_ID ] );
}
}
/**
* @return array
*/
public function is_paczkomaty_and_cod_and_eowc_in_selected_shipping_methods() {
$paczkomaty = false;
$cod = false;
$end_of_weekend_collection = false;
$shippings = $this->get_filtered_chosen_shipping_methods();
$all_shipping_methods = WC()->shipping()->get_shipping_methods();
if ( empty( $all_shipping_methods ) ) {
$all_shipping_methods = WC()->shipping()->load_shipping_methods();
}
/** @var WPDesk_Flexible_Shipping $flexible_shipping */
$flexible_shipping = $all_shipping_methods['flexible_shipping'];
$flexible_shipping_rates = $flexible_shipping->get_all_rates();
$shipping_methods = [];
foreach ( $shippings as $shipping_method_id ) {
if ( isset( $flexible_shipping_rates[ $shipping_method_id ] ) ) {
$shipping_method = $flexible_shipping_rates[ $shipping_method_id ];
if ( isset( $shipping_method['method_integration'] ) && $shipping_method['method_integration'] == WPDesk_Paczkomaty_FS::SHIPPING_METHOD_INTEGRATION ) {
$shipping_methods[] = $shipping_method;
}
}
}
foreach ( $shipping_methods as $shipping_method ) {
if ( isset( $shipping_method[ self::SHIPPING_METOD_SERVICE ] ) && $shipping_method[ self::SHIPPING_METOD_SERVICE ] == WC_Paczkomaty_Shipping_Method::USLUGA_PACZKOMATY ) {
$paczkomaty = true;
if ( isset( $shipping_method[ WPDesk_Paczkomaty_FS::SETTING_COD ] ) && $shipping_method[ WPDesk_Paczkomaty_FS::SETTING_COD ] == '1' ) {
$cod = true;
}
if ( isset( $shipping_method[ WPDesk_Paczkomaty_FS::SETTING_END_OF_WEEK_COLLECTION ] ) && $shipping_method[ WPDesk_Paczkomaty_FS::SETTING_END_OF_WEEK_COLLECTION ] == '1' ) {
$end_of_weekend_collection = true;
}
}
}
return [
'paczkomaty' => $paczkomaty,
'cod' => $cod,
'end_of_week_collection' => $end_of_weekend_collection,
];
}
/**
* @param WC_Shipping_Rate $method
* @param string $package_id
*
* @return void
*/
public function display_choose_machine_field_after_shipping_rate( $method, $package_id ) {
if ( $method->get_id() != ( $this->get_filtered_chosen_shipping_methods()[ $package_id ] ?? '' ) ) {
return;
}
if ( ! $this->should_display_paczkomaty_field( $method ) ) {
return;
}
if ( $this->already_displayed_for_package_id === $package_id ) {
$this->already_displayed = false;
}
if ( ! $this->already_displayed ) {
echo $this->plugin->load_template( 'pickup-point-selection-after-shipping-rate', '', [] );
$this->already_displayed = true;
$this->already_displayed_for_package_id = $package_id;
}
}
private function add_actions_for_other_placements() {
if ( $this->get_select_placement() === WC_Paczkomaty_Shipping_Method::OPTION_INSERT_BELOW_SECTION ) {
if ( ! has_action( 'woocommerce_review_order_after_shipping', [ $this, 'display_choose_machine_field_after_shipping' ] ) ) {
add_action( 'woocommerce_review_order_after_shipping', [ $this, 'display_choose_machine_field_after_shipping' ] );
}
if ( ! has_action( 'woocommerce_subscriptions_after_recurring_shipping_rates', [ $this, 'display_choose_machine_field_after_shipping' ] ) ) {
add_action( 'woocommerce_subscriptions_after_recurring_shipping_rates', [ $this, 'display_choose_machine_field_after_shipping' ] );
}
}
if ( $this->get_select_placement() === WC_Paczkomaty_Shipping_Method::OPTION_NEW_SECTION ) {
if ( ! has_action( 'woocommerce_review_order_after_order_total', [ $this, 'display_choose_machine_field_after_order_total' ] ) ) {
add_action( 'woocommerce_review_order_after_order_total', [ $this, 'display_choose_machine_field_after_order_total' ] );
}
if ( ! has_action( 'woocommerce_subscriptions_recurring_subscription_totals', [ $this, 'display_choose_machine_field_after_order_total' ] ) ) {
add_action( 'woocommerce_subscriptions_recurring_subscription_totals', [ $this, 'display_choose_machine_field_after_order_total' ], 111 );
}
}
}
/**
* @param WC_Shipping_Rate $method
*
* @return bool
*/
private function should_display_paczkomaty_field( $method ) {
$metadata = $method->get_meta_data();
$fs_method = isset( $metadata['_fs_method'] ) && is_array( $metadata['_fs_method'] ) ? $metadata['_fs_method'] : [];
return ( $metadata['_fs_integration'] ?? '' ) === 'paczkomaty'
&& ( $fs_method['paczkomaty_usluga'] ?? '' ) === 'paczkomaty'
&& in_array( $method->get_id(), $this->get_filtered_chosen_shipping_methods(), true );
}
public function display_choose_machine_field_after_order_total() {
if ( $this->already_displayed && current_action() !== $this->already_displayed_on_action ) {
return;
}
echo $this->plugin->load_template( 'pickup-point-selection-after-order-total', '', [] );
$this->already_displayed = true;
$this->already_displayed_on_action = current_action();
}
public function display_choose_machine_field_after_shipping( $package_id ) {
if ( $this->already_displayed && current_action() !== $this->already_displayed_on_action ) {
return;
}
echo $this->plugin->load_template( 'pickup-point-selection-after-shipping', '', [] );
$this->already_displayed = true;
$this->already_displayed_on_action = current_action();
}
/**
* @return void
* @internal
*/
public function display_choose_machine_field() {
$this->render_choose_machine_field( $this->get_select_method(), $this->get_select_type(), 'pickup-point-selection' );
}
private function get_select_method() {
$settings = $this->plugin->get_shipping_method_settings();
return isset( $settings['select_method'] ) ? $settings['select_method'] : 'select_and_map';
}
private function get_select_type() {
$settings = $this->plugin->get_shipping_method_settings();
return isset( $settings['select_type'] ) ? $settings['select_type'] : 'select2_ajax';
}
private function get_select_placement() {
$settings = $this->plugin->get_shipping_method_settings();
return isset( $settings[ WC_Paczkomaty_Shipping_Method::SELECT_PLACEMENT ] ) ? $settings[ WC_Paczkomaty_Shipping_Method::SELECT_PLACEMENT ] : WC_Paczkomaty_Shipping_Method::OPTION_INSERT_BELOW_SECTION;
}
/**
* @param string $select_method
* @param string $select_type
* @param string $template
*
* @return void
*/
private function render_choose_machine_field( $select_method, $select_type, $template = 'pickup-point-selection' ) {
$args = [];
$paczkomaty_and_cod_and_eowc = $this->is_paczkomaty_and_cod_and_eowc_in_selected_shipping_methods();
if ( $paczkomaty_and_cod_and_eowc['paczkomaty'] ) {
$args['select_type'] = $select_type;
$args['select2'] = apply_filters( 'woocommerce_paczkomaty_inpost_checkout_select2', true );
if ( ! $args['select2'] ) {
$args['select_type'] = 'select';
}
$args['selected_id'] = WC()->session->get( self::FIELD_PACZKOMAT_ID, '' );
if ( $args['select_type'] === 'select2_ajax' ) {
$args['options'] = [ '' => __( 'Wybierz paczkomat...', 'woocommerce-paczkomaty-inpost' ) ];
if ( ! empty( $args['selected_id'] ) ) {
try {
$point = $this->pickup_points_manager->get_point_details( $args['selected_id'] );
$args['options'][ $point->get_point_id() ] = $point->get_name();
$args['selected_name'] = $point->get_name();
} catch ( Exception $e ) {
unset( $args['selected_id'] );
}
}
} else {
$args['options'] = $this->get_parcel_machines( $paczkomaty_and_cod_and_eowc['cod'], $paczkomaty_and_cod_and_eowc['end_of_week_collection'] );
}
$args['cod'] = 'FALSE';
if ( $paczkomaty_and_cod_and_eowc['cod'] ) {
$args['cod'] = 'TRUE';
}
$args['end_of_week_collection'] = 'FALSE';
if ( $paczkomaty_and_cod_and_eowc['end_of_week_collection'] ) {
$args['end_of_week_collection'] = 'TRUE';
}
$args['select_enabled'] = in_array( $select_method, [
WC_Paczkomaty_Shipping_Method::SELECT_METHOD_SELECT,
WC_Paczkomaty_Shipping_Method::SELECT_METHOD_SELECT_AND_MAP
], true );
$args['map_enabled'] = in_array( $select_method, [
WC_Paczkomaty_Shipping_Method::SELECT_METHOD_MAP,
WC_Paczkomaty_Shipping_Method::SELECT_METHOD_SELECT_AND_MAP
], true );;
echo $this->plugin->load_template( $template, '', $args );
$script_url = trailingslashit( $this->plugin->get_plugin_assets_url() ) . 'dist/js/checkout.js?ver=' . $this->plugin->get_scrips_version();
$css_url = trailingslashit( $this->plugin->get_plugin_assets_url() ) . 'dist/css/checkout.css?ver=' . $this->plugin->get_scrips_version();
$select2_script_url = WC()->plugin_url() . '/assets/js/selectWoo/selectWoo.full.min.js?ver=' . $this->plugin->get_scrips_version();
$select2_css_url = WC()->plugin_url() . '/assets/css/select2.css?ver=' . $this->plugin->get_scrips_version();
$inpost_script_url = 'https://geowidget.easypack24.net/js/sdk-for-javascript.js?ver=' . $this->plugin->get_scrips_version();
$inpost_css_url = 'https://geowidget.easypack24.net/css/easypack.css?ver=' . $this->plugin->get_scrips_version();;
$localization_data = $this->plugin->get_localization_script_data();
include __DIR__ . '/views/checkout-script.php';
}
}
/**
* @param bool $cod
*/
public function init_machine_list( $cod = false, $end_of_week_collection = false ) {
$paczkomaty_shipping_method = $this->plugin->paczkomaty->get_shipping_method();
if ( $paczkomaty_shipping_method->get_parcel_lockers_api() === $paczkomaty_shipping_method::API_TYPE_XML ) {
if ( empty( $this->allMachines ) ) {
$machines = inpost_get_machine_list();
$this->machines = [ '' => '-- ' . __( 'wybierz', 'woocommerce-paczkomaty-inpost' ) . ' --' ];
$this->allMachines = [];
foreach ( $machines as $machine ) {
if ( $cod === true && $machine['paymentavailable'] != 1 ) {
continue;
}
$this->machines[ $machine['name'] ] = $machine['town'] . ", " . $machine['street'] . " " . $machine['buildingnumber'];
$this->adminMachines[ $machine['name'] ] = "[" . $machine['name'] . "] " . $machine['town'] . ", " . $machine['street'] . " " . $machine['buildingnumber'];
$this->allMachines[ $machine['name'] ] = $machine['town'] . ", " . $machine['street'] . " " . $machine['buildingnumber'];
$this->machinesInfo[ $machine['name'] ] = $machine;
}
}
} else {
$points_type = WPDesk_Paczkomaty_ShipX_Cache::PARCEL_LOCKER_AND_POP;
if ( $cod || $end_of_week_collection ) {
$points_type = WPDesk_Paczkomaty_ShipX_Cache::PARCEL_LOCKER_ONLY;
}
$this->machines = $this->pickup_points_manager->get_points( $points_type );
$this->allMachines = $this->machines;
$this->adminMachines = $this->machines;
}
}
/**
* @param bool $cod
* @param bool $end_of_week_collection
*
* @return string[]
*/
private function get_parcel_machines( bool $cod = false, bool $end_of_week_collection = false ) {
$points_type = WPDesk_Paczkomaty_ShipX_Cache::PARCEL_LOCKER_AND_POP;
if ( $cod || $end_of_week_collection ) {
$points_type = WPDesk_Paczkomaty_ShipX_Cache::PARCEL_LOCKER_ONLY;
}
return $this->pickup_points_manager->get_points( $points_type );
}
/**
* Returns list of parcel lockers.
*
* @param array $admin_machines List of saved options (keys are values).
* @param bool $show_all_options Whether to return all options or only selected.
*
* @return array Updated list of options.
*/
public function paczkomaty_shipping_method_admin_machines( $admin_machines, $show_all_options = true ) {
$default_values = [ '' => __( '-- wybierz --', 'woocommerce-paczkomaty-inpost' ) ];
$selected_values = $admin_machines;
try {
$this->init_machine_list();
if ( count( $this->adminMachines ) ) {
foreach ( $admin_machines as $id => $name ) {
if ( ! isset( $this->adminMachines[ $id ] ) ) {
$this->adminMachines[ $id ] = $name;
} else {
$selected_values[ $id ] = $this->adminMachines[ $id ];
}
}
if ( $show_all_options ) {
return $default_values + $this->adminMachines;
} else {
return $default_values + $selected_values;
}
} else {
return $default_values + $admin_machines;
}
} catch ( Exception $e ) {
return $default_values + $admin_machines;
}
}
/**
* @return string[]
*/
private function get_filtered_chosen_shipping_methods(): array {
return $this->get_chosen_shipping_methods();
}
/**
* @return string[]
*/
private function get_chosen_shipping_methods(): array {
return array_filter( wp_parse_list( WC()->session->get( 'chosen_shipping_methods', [] ) ) );
}
}