| 1 |
<?php |
| 2 |
|
| 3 |
use MyParcelNL\Sdk\src\Adapter\DeliveryOptions\AbstractDeliveryOptionsAdapter as DeliveryOptions; |
| 4 |
use MyParcelNL\Sdk\src\Factory\DeliveryOptionsAdapterFactory; |
| 5 |
use MyParcelNL\Sdk\src\Model\Consignment\AbstractConsignment; |
| 6 |
use WPO\WC\PostNL\Compatibility\Order as WCX_Order; |
| 7 |
use WPO\WC\PostNL\Compatibility\Product as WCX_Product; |
| 8 |
use WPO\WC\PostNL\Compatibility\WC_Core as WCX; |
| 9 |
use WPO\WC\PostNL\Entity\SettingsFieldArguments; |
| 10 |
|
| 11 |
if (! defined('ABSPATH')) { |
| 12 |
exit; |
| 13 |
} // Exit if accessed directly |
| 14 |
|
| 15 |
if (class_exists('WCPOST_Admin')) { |
| 16 |
return new WCPOST_Admin(); |
| 17 |
} |
| 18 |
|
| 19 |
/** |
| 20 |
* Admin options, buttons & data |
| 21 |
*/ |
| 22 |
class WCPOST_Admin |
| 23 |
{ |
| 24 |
public const META_CONSIGNMENTS = "_postnl_consignments"; |
| 25 |
public const META_CONSIGNMENT_ID = "_postnl_consignment_id"; |
| 26 |
public const META_DELIVERY_OPTIONS = "_postnl_delivery_options"; |
| 27 |
public const META_HIGHEST_SHIPPING_CLASS = "_postnl_highest_shipping_class"; |
| 28 |
public const META_LAST_SHIPMENT_IDS = "_postnl_last_shipment_ids"; |
| 29 |
public const META_RETURN_SHIPMENT_IDS = "_postnl_return_shipment_ids"; |
| 30 |
public const META_ORDER_VERSION = "_postnl_order_version"; |
| 31 |
public const META_PGADDRESS = "_postnl_pgaddress"; |
| 32 |
public const META_SHIPMENTS = "_postnl_shipments"; |
| 33 |
public const META_SHIPMENT_OPTIONS_EXTRA = "_postnl_shipment_options_extra"; |
| 34 |
public const META_TRACK_TRACE = "_postnl_tracktrace"; |
| 35 |
public const META_HS_CODE = "_postnl_hs_code"; |
| 36 |
public const META_HS_CODE_VARIATION = "_postnl_hs_code_variation"; |
| 37 |
public const META_COUNTRY_OF_ORIGIN = "_postnl_country_of_origin"; |
| 38 |
public const META_AGE_CHECK = "_postnl_age_check"; |
| 39 |
|
| 40 |
/** |
| 41 |
* @deprecated use weight property in META_SHIPMENT_OPTIONS_EXTRA. |
| 42 |
*/ |
| 43 |
public const META_ORDER_WEIGHT = "_postnl_order_weight"; |
| 44 |
|
| 45 |
/** |
| 46 |
* Legacy meta keys. |
| 47 |
*/ |
| 48 |
public const META_SHIPMENT_OPTIONS_LT_4_0_0 = "_postnl_shipment_options"; |
| 49 |
|
| 50 |
// Ids referring to shipment statuses. |
| 51 |
public const ORDER_STATUS_DELIVERED_AT_RECIPIENT = 7; |
| 52 |
public const ORDER_STATUS_DELIVERED_READY_FOR_PICKUP = 8; |
| 53 |
public const ORDER_STATUS_DELIVERED_PACKAGE_PICKED_UP = 9; |
| 54 |
public const ORDER_STATUS_PRINTED_LETTER = 12; |
| 55 |
public const ORDER_STATUS_PRINTED_DIGITAL_STAMP = 14; |
| 56 |
|
| 57 |
public const SHIPMENT_OPTIONS_FORM_NAME = "postnl_options"; |
| 58 |
|
| 59 |
public const BULK_ACTION_EXPORT = "wcpn_export"; |
| 60 |
public const BULK_ACTION_PRINT = "wcpn_print"; |
| 61 |
public const BULK_ACTION_EXPORT_PRINT = "wcpn_export_print"; |
| 62 |
|
| 63 |
public const PRODUCT_OPTIONS_ENABLED = "yes"; |
| 64 |
public const PRODUCT_OPTIONS_DISABLED = "no"; |
| 65 |
|
| 66 |
public function __construct() |
| 67 |
{ |
| 68 |
if (is_wp_version_compatible("4.7.0")) { |
| 69 |
add_action("bulk_actions-edit-shop_order", [$this, "addBulkActions"], 100); |
| 70 |
} else { |
| 71 |
add_action("admin_footer", [$this, "bulk_actions"]); |
| 72 |
} |
| 73 |
|
| 74 |
add_action("admin_footer", [$this, "renderOffsetDialog"]); |
| 75 |
add_action("admin_footer", [$this, "renderShipmentOptionsForm"]); |
| 76 |
|
| 77 |
/** |
| 78 |
* Orders page |
| 79 |
* -- |
| 80 |
* showPostNLSettings is on the woocommerce_admin_order_actions_end hook because there is no hook to put it |
| 81 |
* in the shipping address column... It is put in the right place after loading using JavaScript. |
| 82 |
* |
| 83 |
* @see wcpn-admin.js -> runTriggers() |
| 84 |
*/ |
| 85 |
add_action("woocommerce_admin_order_actions_end", [$this, "showPostNLSettings"], 9999); |
| 86 |
add_action("woocommerce_admin_order_actions_end", [$this, "showOrderActions"], 20); |
| 87 |
|
| 88 |
/* |
| 89 |
* Single order page |
| 90 |
*/ |
| 91 |
add_action("add_meta_boxes_shop_order", [$this, "add_order_meta_box"]); |
| 92 |
add_action("woocommerce_admin_order_data_after_shipping_address", [$this, "single_order_shipment_options"]); |
| 93 |
|
| 94 |
add_action("wp_ajax_wcpn_save_shipment_options", [$this, "save_shipment_options_ajax"]); |
| 95 |
add_action("wp_ajax_wcpn_get_shipment_summary_status", [$this, "order_list_ajax_get_shipment_summary"]); |
| 96 |
add_action("wp_ajax_wcpn_get_shipment_options", [$this, "ajaxGetShipmentOptions"]); |
| 97 |
|
| 98 |
// Add barcode in order grid |
| 99 |
add_filter("manage_edit-shop_order_columns", [$this, "barcode_add_new_order_admin_list_column"], 10, 1); |
| 100 |
add_action("manage_shop_order_posts_custom_column", [$this, "addBarcodeToOrderColumn"], 10, 2); |
| 101 |
|
| 102 |
add_action('woocommerce_payment_complete', [$this, 'automaticExportOrder'], 1000); |
| 103 |
|
| 104 |
add_action("init", [$this, "registerDeliveredPostStatus"], 10, 1); |
| 105 |
add_filter("wc_order_statuses", [$this, "displayDeliveredPostStatus"], 10, 2); |
| 106 |
|
| 107 |
add_action('woocommerce_product_after_variable_attributes', [$this, 'variation_hs_code_field'], 10, 3); |
| 108 |
add_action('woocommerce_save_product_variation', [$this, 'save_variation_hs_code_field'], 10, 2); |
| 109 |
add_filter('woocommerce_available_variation', [$this, 'load_variation_hs_code_field'], 10, 1); |
| 110 |
|
| 111 |
add_action("woocommerce_product_options_shipping", [$this, "productOptionsFields"]); |
| 112 |
add_action("woocommerce_process_product_meta", [$this, "productOptionsFieldSave"]); |
| 113 |
} |
| 114 |
|
| 115 |
/** |
| 116 |
* @param \MyParcelNL\Sdk\src\Adapter\DeliveryOptions\AbstractDeliveryOptionsAdapter $deliveryOptions |
| 117 |
*/ |
| 118 |
public static function renderPickupLocation(DeliveryOptions $deliveryOptions): void |
| 119 |
{ |
| 120 |
$pickup = $deliveryOptions->getPickupLocation(); |
| 121 |
|
| 122 |
if (! $pickup || ! $deliveryOptions->isPickup()) { |
| 123 |
return; |
| 124 |
} |
| 125 |
|
| 126 |
printf( |
| 127 |
"<div class=\"pickup-location\"><strong>%s:</strong><br /> %s<br />%s %s<br />%s %s</div>", |
| 128 |
__("Pickup location", "woocommerce-postnl"), |
| 129 |
$pickup->getLocationName(), |
| 130 |
$pickup->getStreet(), |
| 131 |
$pickup->getNumber(), |
| 132 |
$pickup->getPostalCode(), |
| 133 |
$pickup->getCity() |
| 134 |
); |
| 135 |
|
| 136 |
echo "<hr>"; |
| 137 |
} |
| 138 |
|
| 139 |
/** |
| 140 |
* @param $loop |
| 141 |
* @param $variationData |
| 142 |
* @param $variation |
| 143 |
*/ |
| 144 |
public function variation_hs_code_field($loop, $variationData, $variation) |
| 145 |
{ |
| 146 |
woocommerce_wp_text_input( |
| 147 |
[ |
| 148 |
'id' => self::META_HS_CODE_VARIATION . "[{$loop}]", |
| 149 |
'name' => self::META_HS_CODE_VARIATION . "[{$loop}]", |
| 150 |
'value' => get_post_meta($variation->ID, self::META_HS_CODE_VARIATION, true), |
| 151 |
'label' => __('HS Code', 'woocommerce'), |
| 152 |
'desc_tip' => true, |
| 153 |
'description' => __('This HS Code overwrites the parents HS Code.', 'woocommerce'), |
| 154 |
'wrapper_class' => 'form-row form-row-full', |
| 155 |
] |
| 156 |
); |
| 157 |
} |
| 158 |
|
| 159 |
/** |
| 160 |
* @param $variationId |
| 161 |
* @param $loop |
| 162 |
*/ |
| 163 |
public function save_variation_hs_code_field($variationId, $loop) |
| 164 |
{ |
| 165 |
$hsCodeValue = $_POST[self::META_HS_CODE_VARIATION][$loop]; |
| 166 |
|
| 167 |
if (! empty($hsCodeValue)) { |
| 168 |
update_post_meta($variationId, self::META_HS_CODE_VARIATION, esc_attr($hsCodeValue)); |
| 169 |
} |
| 170 |
} |
| 171 |
|
| 172 |
/** |
| 173 |
* @param $variation |
| 174 |
* |
| 175 |
* @return mixed |
| 176 |
*/ |
| 177 |
public function load_variation_hs_code_field($variation) |
| 178 |
{ |
| 179 |
$variation[self::META_HS_CODE_VARIATION] = get_post_meta($variation['variation_id'], self::META_HS_CODE_VARIATION, true); |
| 180 |
|
| 181 |
return $variation; |
| 182 |
} |
| 183 |
|
| 184 |
/** |
| 185 |
* Add delivered post type to order statuses list |
| 186 |
*/ |
| 187 |
public function registerDeliveredPostStatus(): void |
| 188 |
{ |
| 189 |
register_post_status('wc-custom-delivered', |
| 190 |
[ |
| 191 |
'label' => 'Delivered', |
| 192 |
'public' => true, |
| 193 |
'exclude_from_search' => false, |
| 194 |
'show_in_admin_all_list' => true, |
| 195 |
'show_in_admin_status_list' => true, |
| 196 |
'label_count' => _n_noop('Delivered (%s)', 'Delivered (%s)'), |
| 197 |
] |
| 198 |
); |
| 199 |
} |
| 200 |
|
| 201 |
/** |
| 202 |
* @param array $order_statuses |
| 203 |
* |
| 204 |
* @return array |
| 205 |
*/ |
| 206 |
public function displayDeliveredPostStatus(array $order_statuses): array |
| 207 |
{ |
| 208 |
$new_order_statuses = []; |
| 209 |
|
| 210 |
foreach ($order_statuses as $key => $status) { |
| 211 |
$new_order_statuses[$key] = $status; |
| 212 |
|
| 213 |
// if ('wc-processing' === $key) { |
| 214 |
// $new_order_statuses['wc-custom-delivered'] = 'Delivered'; |
| 215 |
// } |
| 216 |
} |
| 217 |
|
| 218 |
return $new_order_statuses; |
| 219 |
} |
| 220 |
|
| 221 |
/** |
| 222 |
* @param $orderId |
| 223 |
* |
| 224 |
* @throws ErrorException |
| 225 |
* @throws \MyParcelNL\Sdk\src\Exception\ApiException |
| 226 |
* @throws \MyParcelNL\Sdk\src\Exception\MissingFieldException |
| 227 |
*/ |
| 228 |
public function automaticExportOrder($orderId): void |
| 229 |
{ |
| 230 |
(new WCPN_Export())->exportByOrderId($orderId); |
| 231 |
} |
| 232 |
|
| 233 |
/** |
| 234 |
* @param WC_Order $order |
| 235 |
* |
| 236 |
* @throws Exception |
| 237 |
*/ |
| 238 |
public function showPostNLSettings(WC_Order $order): void |
| 239 |
{ |
| 240 |
$orderSettings = new OrderSettings($order); |
| 241 |
$isAllowedDestination = WCPN_Country_Codes::isAllowedDestination($orderSettings->getShippingCountry()); |
| 242 |
|
| 243 |
if (! $isAllowedDestination) { |
| 244 |
return; |
| 245 |
} |
| 246 |
|
| 247 |
echo '<div class="wcpn__shipment-settings-wrapper" style="display: none;">'; |
| 248 |
$this->printDeliveryDate($orderSettings->getDeliveryOptions()); |
| 249 |
|
| 250 |
$consignments = self::get_order_shipments($order); |
| 251 |
// if we have shipments, then we show status & link to Track & Trace, settings under i |
| 252 |
if (! empty($consignments)) : |
| 253 |
// only use last shipment |
| 254 |
$lastShipment = array_pop($consignments); |
| 255 |
$lastShipmentId = $lastShipment['shipment_id']; |
| 256 |
|
| 257 |
?> |
| 258 |
<a class="wcpn__shipment-summary__show"> |
| 259 |
<span class="wcpn__encircle wcpn__shipment-summary__show">i</span> |
| 260 |
</a> |
| 261 |
<div |
| 262 |
class="wcpn__box wcpn__shipment-summary__list" |
| 263 |
data-loaded="" |
| 264 |
data-shipment_id="<?php echo $lastShipmentId; ?>" |
| 265 |
data-order_id="<?php echo $order->get_id(); ?>" |
| 266 |
style="display: none;"> |
| 267 |
<?php self::renderSpinner(); ?> |
| 268 |
</div> |
| 269 |
<?php endif; |
| 270 |
|
| 271 |
printf( |
| 272 |
'<a href="#" class="wcpn__shipment-options__show" data-order-id="%d">%s ▾</a>', |
| 273 |
$order->get_id(), |
| 274 |
WCPN_Data::getPackageTypeHuman( |
| 275 |
$orderSettings->getPackageType() ?? AbstractConsignment::DEFAULT_PACKAGE_TYPE_NAME |
| 276 |
) |
| 277 |
); |
| 278 |
|
| 279 |
echo "</div>"; |
| 280 |
} |
| 281 |
|
| 282 |
/** |
| 283 |
* Get shipment status + Track & Trace link via AJAX |
| 284 |
* |
| 285 |
* @throws Exception |
| 286 |
*/ |
| 287 |
public function order_list_ajax_get_shipment_summary(): void |
| 288 |
{ |
| 289 |
check_ajax_referer(WCPOST::NONCE_ACTION, 'security'); |
| 290 |
|
| 291 |
include('views/html-order-shipment-summary.php'); |
| 292 |
die(); |
| 293 |
} |
| 294 |
|
| 295 |
/** |
| 296 |
* Add export option to bulk action drop down menu. |
| 297 |
* |
| 298 |
* @param array $actions |
| 299 |
* |
| 300 |
* @return array |
| 301 |
* @since WordPress 4.7.0 |
| 302 |
*/ |
| 303 |
public function addBulkActions(array $actions): array |
| 304 |
{ |
| 305 |
$actions = array_merge( |
| 306 |
$actions, |
| 307 |
[ |
| 308 |
self::BULK_ACTION_EXPORT => __("bulk_action_export", "woocommerce-postnl"), |
| 309 |
self::BULK_ACTION_PRINT => __("bulk_action_print", "woocommerce-postnl"), |
| 310 |
self::BULK_ACTION_EXPORT_PRINT => __("bulk_action_export_print", "woocommerce-postnl"), |
| 311 |
] |
| 312 |
); |
| 313 |
|
| 314 |
self::renderSpinner('bulkAction'); |
| 315 |
|
| 316 |
return $actions; |
| 317 |
} |
| 318 |
|
| 319 |
/** |
| 320 |
* Add export option to bulk action drop down menu |
| 321 |
* Using Javascript until WordPress core fixes: http://core.trac.wordpress.org/ticket/16031 |
| 322 |
* |
| 323 |
* Used pre WordPress 4.7.0 |
| 324 |
* |
| 325 |
* @access public |
| 326 |
* @return void |
| 327 |
*/ |
| 328 |
public function bulk_actions() |
| 329 |
{ |
| 330 |
global $post_type; |
| 331 |
$bulk_actions = [ |
| 332 |
self::BULK_ACTION_EXPORT => __("PostNL: Export", "woocommerce-postnl"), |
| 333 |
self::BULK_ACTION_PRINT => __("PostNL: Print", "woocommerce-postnl"), |
| 334 |
self::BULK_ACTION_EXPORT_PRINT => __("PostNL: Export & Print", "woocommerce-postnl"), |
| 335 |
]; |
| 336 |
|
| 337 |
if ('shop_order' == $post_type) { |
| 338 |
?> |
| 339 |
<script type="text/javascript"> |
| 340 |
jQuery(document).ready(function () { |
| 341 |
<?php foreach ($bulk_actions as $action => $title) { ?> |
| 342 |
jQuery('<option>') |
| 343 |
.val('<?php echo $action; ?>') |
| 344 |
.html('<?php echo esc_attr($title); ?>') |
| 345 |
.appendTo('select[name=\'action\'], select[name=\'action2\']'); |
| 346 |
<?php } ?> |
| 347 |
}); |
| 348 |
</script> |
| 349 |
<?php |
| 350 |
self::renderSpinner(); |
| 351 |
} |
| 352 |
} |
| 353 |
|
| 354 |
/** |
| 355 |
* Show dialog to choose print position (offset) |
| 356 |
* |
| 357 |
* @access public |
| 358 |
* @return void |
| 359 |
*/ |
| 360 |
public function renderOffsetDialog(): void |
| 361 |
{ |
| 362 |
if (! WCPOST()->setting_collection->isEnabled(WCPOST_Settings::SETTING_ASK_FOR_PRINT_POSITION)) { |
| 363 |
return; |
| 364 |
} |
| 365 |
|
| 366 |
$field = [ |
| 367 |
"name" => "offset", |
| 368 |
"class" => ["wcpn__d--inline-block"], |
| 369 |
"input_class" => ["wcpn__offset-dialog__offset"], |
| 370 |
"type" => "number", |
| 371 |
"custom_attributes" => [ |
| 372 |
"step" => "1", |
| 373 |
"min" => "0", |
| 374 |
"max" => "4", |
| 375 |
"size" => "2", |
| 376 |
], |
| 377 |
]; |
| 378 |
|
| 379 |
$class = new SettingsFieldArguments($field, false); |
| 380 |
?> |
| 381 |
|
| 382 |
<div |
| 383 |
class="wcpn wcpn__box wcpn__offset-dialog wcpn__ws--nowrap" |
| 384 |
style="display: none;"> |
| 385 |
<div class="wcpn__offset-dialog__inner wcpn__d--flex"> |
| 386 |
<div> |
| 387 |
<div class="wcpn__pb--2"> |
| 388 |
<?php printf( |
| 389 |
'<label for="%s">%s</label>', |
| 390 |
$class->getId(), |
| 391 |
__("Labels to skip", "woocommerce-postnl") |
| 392 |
); ?> |
| 393 |
</div> |
| 394 |
<div class="wcpn__d--flex wcpn__pb--2"> |
| 395 |
<?php woocommerce_form_field($field["name"], $class->getArguments(false), ""); ?> |
| 396 |
<img |
| 397 |
src="<?php echo WCPOST()->plugin_url() . "/assets/img/offset.svg"; ?>" |
| 398 |
alt="<?php implode(", ", WCPN_Export::DEFAULT_POSITIONS) ?>" |
| 399 |
class="wcpn__offset-dialog__icon wcpn__pl--1"/> |
| 400 |
</div> |
| 401 |
<div> |
| 402 |
<a |
| 403 |
href="#" |
| 404 |
class="wcpn__offset-dialog__button button" |
| 405 |
style="display: none;" |
| 406 |
target="_blank"> |
| 407 |
<?php _e("Print", "woocommerce-postnl"); ?> |
| 408 |
<?php self::renderSpinner(); ?> |
| 409 |
</a> |
| 410 |
</div> |
| 411 |
</div> |
| 412 |
<div class="wcpn__close-button dashicons dashicons-no-alt wcpn__offset-dialog__close wcpn__pl--2"></div> |
| 413 |
</div> |
| 414 |
</div> |
| 415 |
<?php |
| 416 |
} |
| 417 |
|
| 418 |
/** |
| 419 |
* Hide an empty shipment options form in the footer. |
| 420 |
*/ |
| 421 |
public function renderShipmentOptionsForm(): void |
| 422 |
{ |
| 423 |
echo '<div class="wcpn__box wcpn__shipment-options-dialog" style="display: none; position: absolute;"></div>'; |
| 424 |
} |
| 425 |
|
| 426 |
/** |
| 427 |
* Get the new html content for the shipment options form based on the passed order id. |
| 428 |
*/ |
| 429 |
public function ajaxGetShipmentOptions(): void |
| 430 |
{ |
| 431 |
// Order is used in views/html-order-shipment-options.php |
| 432 |
$order = wc_get_order((int) $_POST['orderId']); |
| 433 |
|
| 434 |
include('views/html-order-shipment-options.php'); |
| 435 |
|
| 436 |
die(); |
| 437 |
} |
| 438 |
|
| 439 |
/** |
| 440 |
* Add print actions to the orders listing |
| 441 |
* |
| 442 |
* @param $order |
| 443 |
* |
| 444 |
* @throws Exception |
| 445 |
*/ |
| 446 |
public function showOrderActions($order): void |
| 447 |
{ |
| 448 |
if (empty($order)) { |
| 449 |
return; |
| 450 |
} |
| 451 |
|
| 452 |
$shipping_country = WCX_Order::get_prop($order, 'shipping_country'); |
| 453 |
|
| 454 |
if (! WCPN_Country_Codes::isAllowedDestination($shipping_country)) { |
| 455 |
return; |
| 456 |
} |
| 457 |
|
| 458 |
$order_id = WCX_Order::get_id($order); |
| 459 |
|
| 460 |
$baseUrl = "admin-ajax.php?action=" . WCPN_Export::EXPORT; |
| 461 |
$addShipments = WCPN_Export::ADD_SHIPMENTS; |
| 462 |
$getLabels = WCPN_Export::GET_LABELS; |
| 463 |
$addReturn = WCPN_Export::ADD_RETURN; |
| 464 |
|
| 465 |
$returnShipmentId = $order->get_meta(self::META_RETURN_SHIPMENT_IDS); |
| 466 |
|
| 467 |
$listing_actions = [ |
| 468 |
$addShipments => [ |
| 469 |
"url" => admin_url("$baseUrl&request=$addShipments&order_ids=$order_id"), |
| 470 |
"img" => WCPOST()->plugin_url() . "/assets/img/postnl-export.png", |
| 471 |
"alt" => __("Export to PostNL", "woocommerce-postnl"), |
| 472 |
], |
| 473 |
$getLabels => [ |
| 474 |
"url" => admin_url("$baseUrl&request=$getLabels&order_ids=$order_id"), |
| 475 |
"img" => WCPOST()->plugin_url() . "/assets/img/postnl-print.png", |
| 476 |
"alt" => __("Print PostNL label", "woocommerce-postnl"), |
| 477 |
], |
| 478 |
// $addReturn => [ |
| 479 |
// "url" => admin_url("$baseUrl&request=$addReturn&order_ids=$order_id"), |
| 480 |
// "img" => WCPOST()->plugin_url() . "/assets/img/postnl-return.svg", |
| 481 |
// "alt" => __("Email return label", "woocommerce-postnl"), |
| 482 |
// ], |
| 483 |
]; |
| 484 |
|
| 485 |
$consignments = self::get_order_shipments($order); |
| 486 |
|
| 487 |
if (empty($consignments)) { |
| 488 |
unset($listing_actions[$getLabels]); |
| 489 |
} |
| 490 |
|
| 491 |
$processed_shipments = self::get_order_shipments($order); |
| 492 |
if (empty($processed_shipments) || $shipping_country !== 'NL') { |
| 493 |
unset($listing_actions[$addReturn]); |
| 494 |
} |
| 495 |
|
| 496 |
$display = WCPOST()->setting_collection->getByName(WCPOST_Settings::SETTING_DOWNLOAD_DISPLAY) === 'display'; |
| 497 |
$attributes = []; |
| 498 |
|
| 499 |
if ($display) { |
| 500 |
$attributes["target"] = "_blank"; |
| 501 |
} |
| 502 |
|
| 503 |
foreach ($listing_actions as $request => $data) { |
| 504 |
self::renderAction( |
| 505 |
$data['url'], |
| 506 |
$data['alt'], |
| 507 |
$data["img"], |
| 508 |
$attributes |
| 509 |
); |
| 510 |
} |
| 511 |
} |
| 512 |
|
| 513 |
/** |
| 514 |
* @param WC_Order $order |
| 515 |
* @param bool $exclude_concepts |
| 516 |
* |
| 517 |
* @return array |
| 518 |
*/ |
| 519 |
public static function get_order_shipments(WC_Order $order, bool $exclude_concepts = false): array |
| 520 |
{ |
| 521 |
$consignments = WCX_Order::get_meta($order, self::META_SHIPMENTS); |
| 522 |
|
| 523 |
// fallback to legacy consignment data (v1.X) |
| 524 |
if (empty($consignments)) { |
| 525 |
if ($consignment_id = WCX_Order::get_meta($order, self::META_CONSIGNMENT_ID)) { |
| 526 |
$consignments = [ |
| 527 |
[ |
| 528 |
"shipment_id" => $consignment_id, |
| 529 |
"track_trace" => WCX_Order::get_meta($order, self::META_TRACK_TRACE), |
| 530 |
], |
| 531 |
]; |
| 532 |
} elseif ($legacy_consignments = WCX_Order::get_meta($order, self::META_CONSIGNMENTS)) { |
| 533 |
$consignments = []; |
| 534 |
foreach ($legacy_consignments as $consignment) { |
| 535 |
if (isset($consignment["consignment_id"])) { |
| 536 |
$consignments[] = [ |
| 537 |
"shipment_id" => $consignment["consignment_id"], |
| 538 |
"track_trace" => $consignment["track_trace"], |
| 539 |
]; |
| 540 |
} |
| 541 |
} |
| 542 |
} |
| 543 |
} |
| 544 |
|
| 545 |
if (empty($consignments) || ! is_array($consignments)) { |
| 546 |
return []; |
| 547 |
} |
| 548 |
|
| 549 |
/** |
| 550 |
* Filter out concepts. |
| 551 |
*/ |
| 552 |
if ($exclude_concepts) { |
| 553 |
$consignments = array_filter($consignments, |
| 554 |
function($consignment) { |
| 555 |
return isset($consignment["track_trace"]); |
| 556 |
} |
| 557 |
); |
| 558 |
} |
| 559 |
|
| 560 |
return $consignments; |
| 561 |
} |
| 562 |
|
| 563 |
/** |
| 564 |
* On saving shipment options from the bulk options form. |
| 565 |
* |
| 566 |
* @throws Exception |
| 567 |
* @see admin/views/html-order-shipment-options.php |
| 568 |
*/ |
| 569 |
public function save_shipment_options_ajax(): void |
| 570 |
{ |
| 571 |
parse_str($_POST["form_data"], $form_data); |
| 572 |
|
| 573 |
foreach ($form_data[self::SHIPMENT_OPTIONS_FORM_NAME] as $order_id => $data) { |
| 574 |
$order = WCX::get_order($order_id); |
| 575 |
$data = self::removeDisallowedDeliveryOptions($data, $order->get_shipping_country()); |
| 576 |
$orderSettings = new OrderSettings($order, $data); |
| 577 |
|
| 578 |
WCX_Order::update_meta_data( |
| 579 |
$order, |
| 580 |
self::META_DELIVERY_OPTIONS, |
| 581 |
$orderSettings->getDeliveryOptions()->toArray() |
| 582 |
); |
| 583 |
|
| 584 |
// Save extra options |
| 585 |
WCX_Order::update_meta_data( |
| 586 |
$order, |
| 587 |
self::META_SHIPMENT_OPTIONS_EXTRA, |
| 588 |
array_merge( |
| 589 |
$orderSettings->getExtraOptions(), |
| 590 |
$data["extra_options"] |
| 591 |
) |
| 592 |
); |
| 593 |
} |
| 594 |
|
| 595 |
die(); |
| 596 |
} |
| 597 |
|
| 598 |
/** |
| 599 |
* Add the meta box on the single order page |
| 600 |
*/ |
| 601 |
public function add_order_meta_box(): void |
| 602 |
{ |
| 603 |
add_meta_box( |
| 604 |
"postnl", |
| 605 |
__("PostNL", "woocommerce-postnl"), |
| 606 |
[$this, "createMetaBox"], |
| 607 |
"shop_order", |
| 608 |
"side", |
| 609 |
"default" |
| 610 |
); |
| 611 |
} |
| 612 |
|
| 613 |
/** |
| 614 |
* Callback: Create the meta box content on the single order page |
| 615 |
* |
| 616 |
* @throws Exception |
| 617 |
*/ |
| 618 |
public function createMetaBox(): void |
| 619 |
{ |
| 620 |
global $post_id; |
| 621 |
// get order |
| 622 |
$order = WCX::get_order($post_id); |
| 623 |
|
| 624 |
if (! $order) { |
| 625 |
return; |
| 626 |
} |
| 627 |
|
| 628 |
$order_id = WCX_Order::get_id($order); |
| 629 |
|
| 630 |
$shipping_country = WCX_Order::get_prop($order, 'shipping_country'); |
| 631 |
if (! WCPN_Country_Codes::isAllowedDestination($shipping_country)) { |
| 632 |
return; |
| 633 |
} |
| 634 |
|
| 635 |
$class = version_compare(WOOCOMMERCE_VERSION, '3.3.0', '>=') ? "single_wc_actions" : "single_order_actions"; |
| 636 |
// show buttons and check if WooCommerce > 3.3.0 is used and select the correct function and class |
| 637 |
echo "<div class=\"$class\">"; |
| 638 |
$this->showOrderActions($order); |
| 639 |
echo '</div>'; |
| 640 |
|
| 641 |
$downloadDisplay = WCPOST()->setting_collection->getByName(WCPOST_Settings::SETTING_DOWNLOAD_DISPLAY) === 'display'; |
| 642 |
$consignments = self::get_order_shipments($order); |
| 643 |
|
| 644 |
// show shipments if available |
| 645 |
if (empty($consignments)) { |
| 646 |
return; |
| 647 |
} |
| 648 |
|
| 649 |
include('views/html-order-track-trace-table.php'); |
| 650 |
} |
| 651 |
|
| 652 |
/** |
| 653 |
* @param $order |
| 654 |
* |
| 655 |
* @throws Exception |
| 656 |
*/ |
| 657 |
public function single_order_shipment_options(WC_Order $order) |
| 658 |
{ |
| 659 |
$shipping_country = WCX_Order::get_prop($order, "shipping_country"); |
| 660 |
|
| 661 |
if (! WCPN_Country_Codes::isAllowedDestination($shipping_country)) { |
| 662 |
return; |
| 663 |
} |
| 664 |
|
| 665 |
$this->showPostNLSettings($order); |
| 666 |
} |
| 667 |
|
| 668 |
/** |
| 669 |
* @param WC_Order $order |
| 670 |
* |
| 671 |
* @throws Exception |
| 672 |
*/ |
| 673 |
public function showDeliveryDateForOrder(WC_Order $order): void |
| 674 |
{ |
| 675 |
$deliveryOptions = self::getDeliveryOptionsFromOrder($order); |
| 676 |
$this->printDeliveryDate($deliveryOptions); |
| 677 |
} |
| 678 |
|
| 679 |
/** |
| 680 |
* @param \WC_Order $order |
| 681 |
* @param bool $isEmail |
| 682 |
* |
| 683 |
* @throws \Exception |
| 684 |
*/ |
| 685 |
public function showShipmentConfirmation(WC_Order $order, bool $isEmail): void |
| 686 |
{ |
| 687 |
$deliveryOptions = self::getDeliveryOptionsFromOrder($order); |
| 688 |
$confirmationData = $this->getConfirmationData($deliveryOptions); |
| 689 |
$isEmail |
| 690 |
? $this->printEmailConfirmation($confirmationData) |
| 691 |
: $this->printThankYouConfirmation($confirmationData); |
| 692 |
} |
| 693 |
|
| 694 |
/** |
| 695 |
* Go through all getProductOptions and show them on the screen |
| 696 |
*/ |
| 697 |
public function productOptionsFields(): void |
| 698 |
{ |
| 699 |
echo '<div class="options_group">'; |
| 700 |
foreach ($this->getProductOptions() as $productOption) { |
| 701 |
$type = $productOption['type']; |
| 702 |
if ('text' === $type) { |
| 703 |
woocommerce_wp_text_input( |
| 704 |
[ |
| 705 |
'id' => $productOption['id'], |
| 706 |
'label' => $productOption['label'], |
| 707 |
'description' => $productOption['description'], |
| 708 |
] |
| 709 |
); |
| 710 |
} elseif ('select' === $type) { |
| 711 |
woocommerce_wp_select( |
| 712 |
[ |
| 713 |
'id' => $productOption['id'], |
| 714 |
'label' => $productOption['label'], |
| 715 |
'options' => $productOption['options'], |
| 716 |
'description' => $productOption['description'], |
| 717 |
] |
| 718 |
); |
| 719 |
} |
| 720 |
} |
| 721 |
echo '</div>'; |
| 722 |
} |
| 723 |
|
| 724 |
/** |
| 725 |
* @param int $postId |
| 726 |
*/ |
| 727 |
public function productOptionsFieldSave(int $postId): void |
| 728 |
{ |
| 729 |
foreach ($this->getProductOptions() as $productOption) { |
| 730 |
// check if hs code is passed and not an array (=variation hs code) |
| 731 |
if (isset($_POST[$productOption['id']]) && ! is_array($_POST[$productOption['id']])) { |
| 732 |
$product = wc_get_product($postId); |
| 733 |
$productId = $_POST[$productOption['id']]; |
| 734 |
|
| 735 |
if (! empty($productId)) { |
| 736 |
WCX_Product::update_meta_data($product, $productOption['id'], esc_attr($productId)); |
| 737 |
} else { |
| 738 |
if (isset($_POST[$productOption['id']]) && empty($productId)) { |
| 739 |
WCX_Product::delete_meta_data($product, $productOption['id']); |
| 740 |
} |
| 741 |
} |
| 742 |
} |
| 743 |
} |
| 744 |
} |
| 745 |
|
| 746 |
/** |
| 747 |
* @param $order_id |
| 748 |
* @param $track_trace |
| 749 |
* |
| 750 |
* @return string|void |
| 751 |
* @throws Exception |
| 752 |
*/ |
| 753 |
public static function getTrackTraceUrl($order_id, $track_trace) |
| 754 |
{ |
| 755 |
if (empty($order_id)) { |
| 756 |
return; |
| 757 |
} |
| 758 |
|
| 759 |
$order = WCX::get_order($order_id); |
| 760 |
$country = WCX_Order::get_prop($order, 'shipping_country'); |
| 761 |
$postcode = preg_replace('/\s+/', '', WCX_Order::get_prop($order, 'shipping_postcode')); |
| 762 |
|
| 763 |
// set url for NL or foreign orders |
| 764 |
if ($country === 'NL') { |
| 765 |
$deliveryOptions = self::getDeliveryOptionsFromOrder($order); |
| 766 |
|
| 767 |
// use billing postcode for pickup/pakjegemak |
| 768 |
if ($deliveryOptions->isPickup()) { |
| 769 |
$postcode = preg_replace('/\s+/', '', WCX_Order::get_prop($order, 'billing_postcode')); |
| 770 |
} |
| 771 |
|
| 772 |
$trackTraceUrl = sprintf( |
| 773 |
'https://jouw.postnl.nl/track-and-trace/%s/%s/%s', |
| 774 |
$track_trace, |
| 775 |
$country, |
| 776 |
$postcode |
| 777 |
); |
| 778 |
} else { |
| 779 |
$trackTraceUrl = sprintf( |
| 780 |
'https://www.internationalparceltracking.com/Main.aspx#/track/%s/%s/%s', |
| 781 |
$track_trace, |
| 782 |
$country, |
| 783 |
$postcode |
| 784 |
); |
| 785 |
} |
| 786 |
|
| 787 |
return $trackTraceUrl; |
| 788 |
} |
| 789 |
|
| 790 |
/** |
| 791 |
* @return array |
| 792 |
*/ |
| 793 |
public function getProductOptions(): array |
| 794 |
{ |
| 795 |
return [ |
| 796 |
'HS-Code' => [ |
| 797 |
'id' => self::META_HS_CODE, |
| 798 |
'label' => __('HS Code', 'woocommerce-postnl'), |
| 799 |
'type' => 'text', |
| 800 |
'description' => wc_help_tip( |
| 801 |
sprintf( |
| 802 |
__( |
| 803 |
'HS Codes are used for PostNL world shipments, you can find the appropriate code on the %ssite of the Dutch Customs%s', |
| 804 |
'woocommerce-postnl' |
| 805 |
), |
| 806 |
'<a href="https://tarief.douane.nl/arctictariff-public-web/#!/home" target="_blank">', |
| 807 |
'</a>' |
| 808 |
) |
| 809 |
), |
| 810 |
], |
| 811 |
'Country-of-origin' => [ |
| 812 |
'id' => self::META_COUNTRY_OF_ORIGIN, |
| 813 |
'label' => __('product_options_country_of_origin', 'woocommerce-postnl'), |
| 814 |
'type' => 'select', |
| 815 |
'options' => array_merge( |
| 816 |
[ |
| 817 |
null => __('Default', 'woocommerce-postnl'), |
| 818 |
], |
| 819 |
(new WC_Countries())->get_countries() |
| 820 |
), |
| 821 |
'description' => wc_help_tip( |
| 822 |
__('setting_country_of_origin_help_text', 'woocommerce-postnl') |
| 823 |
), |
| 824 |
], |
| 825 |
'Age-check' => [ |
| 826 |
'id' => self::META_AGE_CHECK, |
| 827 |
'label' => __('shipment_options_age_check', 'woocommerce-postnl'), |
| 828 |
'type' => 'select', |
| 829 |
'options' => [ |
| 830 |
null => __('Default', 'woocommerce-postnl'), |
| 831 |
self::PRODUCT_OPTIONS_DISABLED => __('Disabled', 'woocommerce-postnl'), |
| 832 |
self::PRODUCT_OPTIONS_ENABLED => __('Enabled', 'woocommerce-postnl'), |
| 833 |
], |
| 834 |
'description' => wc_help_tip(__('shipment_options_age_check_help_text', 'woocommerce-postnl')), |
| 835 |
], |
| 836 |
]; |
| 837 |
} |
| 838 |
|
| 839 |
/** |
| 840 |
* @snippet Add Column to Orders Table (e.g. Barcode) - WooCommerce |
| 841 |
* |
| 842 |
* @param $columns |
| 843 |
* |
| 844 |
* @return mixed |
| 845 |
*/ |
| 846 |
public function barcode_add_new_order_admin_list_column($columns) |
| 847 |
{ |
| 848 |
// I want to display Barcode column just after the date column |
| 849 |
return array_slice($columns, 0, 6, true) + ['barcode' => 'Barcode'] + array_slice($columns, 6, null, true); |
| 850 |
} |
| 851 |
|
| 852 |
/** |
| 853 |
* @param $column |
| 854 |
* |
| 855 |
* @throws Exception |
| 856 |
*/ |
| 857 |
public function addBarcodeToOrderColumn($column) |
| 858 |
{ |
| 859 |
global $post; |
| 860 |
|
| 861 |
if ("barcode" === $column) { |
| 862 |
$this->renderBarcodes(WCX::get_order($post->ID)); |
| 863 |
} |
| 864 |
} |
| 865 |
|
| 866 |
/** |
| 867 |
* @param WC_Order $order |
| 868 |
* |
| 869 |
* @return void |
| 870 |
* @throws Exception |
| 871 |
*/ |
| 872 |
public function renderBarcodes(WC_Order $order): void |
| 873 |
{ |
| 874 |
$shipments = self::get_order_shipments($order, true); |
| 875 |
|
| 876 |
if (empty($shipments)) { |
| 877 |
echo __("No label has been created yet.", "woocommerce-postnl"); |
| 878 |
|
| 879 |
return; |
| 880 |
} |
| 881 |
|
| 882 |
echo '<div class="wcpn__barcodes">'; |
| 883 |
foreach ($shipments as $shipment_id => $shipment) { |
| 884 |
$shipmentStatusId = $shipment['shipment']['status']; |
| 885 |
$printedStatuses = [WCPOST_Admin::ORDER_STATUS_PRINTED_DIGITAL_STAMP, WCPOST_Admin::ORDER_STATUS_PRINTED_LETTER]; |
| 886 |
|
| 887 |
if (in_array($shipmentStatusId, $printedStatuses)) { |
| 888 |
echo __("The label has been printed.", "woocommerce-postnl"); |
| 889 |
continue; |
| 890 |
} |
| 891 |
|
| 892 |
if (empty($shipment["track_trace"])) { |
| 893 |
echo __("Concept created but not printed.", "woocommerce-postnl"); |
| 894 |
continue; |
| 895 |
} |
| 896 |
|
| 897 |
printf( |
| 898 |
'<a target="_blank" class="wcpn__barcode-link" title="%2$s" href="%1$s">%2$s</a><br>', |
| 899 |
self::getTrackTraceUrl($order, $shipment["track_trace"]), |
| 900 |
$shipment["track_trace"] |
| 901 |
); |
| 902 |
} |
| 903 |
echo "</div>"; |
| 904 |
} |
| 905 |
|
| 906 |
/** |
| 907 |
* Get DeliveryOptions object from the given order's meta data. Uses legacy delivery options if found, if that |
| 908 |
* data is invalid it falls back to defaults. |
| 909 |
* |
| 910 |
* @param WC_Order $order |
| 911 |
* @param array $inputData |
| 912 |
* |
| 913 |
* @return DeliveryOptions |
| 914 |
* @throws \Exception |
| 915 |
* @see \WCPN_Checkout::save_delivery_options |
| 916 |
*/ |
| 917 |
public static function getDeliveryOptionsFromOrder(WC_Order $order, array $inputData = []): DeliveryOptions |
| 918 |
{ |
| 919 |
$meta = WCX_Order::get_meta($order, self::META_DELIVERY_OPTIONS) ?: null; |
| 920 |
|
| 921 |
// $meta is a json string, create an instance |
| 922 |
if (! empty($meta) && ! $meta instanceof DeliveryOptions) { |
| 923 |
if (is_string($meta)) { |
| 924 |
$meta = json_decode(stripslashes($meta), true); |
| 925 |
} |
| 926 |
|
| 927 |
$meta["carrier"] = WCPN_Data::DEFAULT_CARRIER; |
| 928 |
|
| 929 |
try { |
| 930 |
// create new instance from known json |
| 931 |
$meta = DeliveryOptionsAdapterFactory::create((array) $meta); |
| 932 |
} catch (BadMethodCallException $e) { |
| 933 |
// create new instance from unknown json data |
| 934 |
$meta = new WCPN_DeliveryOptionsFromOrderAdapter(null, (array) $meta); |
| 935 |
} |
| 936 |
} |
| 937 |
|
| 938 |
// Create or update immutable adapter from order with a instanceof DeliveryOptionsAdapter |
| 939 |
if (empty($meta) || ! empty($inputData)) { |
| 940 |
$meta = new WCPN_DeliveryOptionsFromOrderAdapter($meta, $inputData); |
| 941 |
} |
| 942 |
|
| 943 |
return $meta; |
| 944 |
} |
| 945 |
|
| 946 |
/** |
| 947 |
* Output the delivery date if there is a date and the show delivery day setting is enabled. |
| 948 |
* |
| 949 |
* @param DeliveryOptions $deliveryOptions |
| 950 |
* |
| 951 |
* @throws Exception |
| 952 |
*/ |
| 953 |
private function printDeliveryDate(DeliveryOptions $deliveryOptions): void |
| 954 |
{ |
| 955 |
$showDeliveryDay = WCPOST()->setting_collection->isEnabled(WCPOST_Settings::SETTING_SHOW_DELIVERY_DAY); |
| 956 |
|
| 957 |
if ($showDeliveryDay && $deliveryOptions->getDate()) { |
| 958 |
printf( |
| 959 |
'<div class="delivery-date"><strong>%s</strong><br />%s, %s</div>', |
| 960 |
__("PostNL shipment:", "woocommerce-postnl"), |
| 961 |
WCPN_Data::getDeliveryTypesHuman()[$deliveryOptions->getDeliveryType()], |
| 962 |
wc_format_datetime(new WC_DateTime($deliveryOptions->getDate()), 'D d-m') |
| 963 |
); |
| 964 |
} |
| 965 |
} |
| 966 |
|
| 967 |
/** |
| 968 |
* Output the chosen delivery options or the chosen pickup options. |
| 969 |
* |
| 970 |
* @param DeliveryOptions $deliveryOptions |
| 971 |
* |
| 972 |
* @return array[]|null |
| 973 |
* @throws \Exception |
| 974 |
*/ |
| 975 |
private function getConfirmationData(DeliveryOptions $deliveryOptions): ?array |
| 976 |
{ |
| 977 |
$deliveryOptionsEnabled = WCPOST()->setting_collection->isEnabled( |
| 978 |
WCPOST_Settings::SETTING_DELIVERY_OPTIONS_ENABLED |
| 979 |
); |
| 980 |
|
| 981 |
if (! $deliveryOptionsEnabled || ! $deliveryOptions->getCarrier()) { |
| 982 |
return null; |
| 983 |
} |
| 984 |
|
| 985 |
$signatureTitle = WCPN_Checkout::getDeliveryOptionsTitle(WCPOST_Settings::SETTING_SIGNATURE_TITLE); |
| 986 |
$onlyRecipientTitle = WCPN_Checkout::getDeliveryOptionsTitle(WCPOST_Settings::SETTING_ONLY_RECIPIENT_TITLE); |
| 987 |
$hasSignature = $deliveryOptions->getShipmentOptions()->hasSignature(); |
| 988 |
$hasOnlyRecipient = $deliveryOptions->getShipmentOptions()->hasOnlyRecipient(); |
| 989 |
|
| 990 |
if (AbstractConsignment::DELIVERY_TYPE_PICKUP_NAME === $deliveryOptions->getDeliveryType()) { |
| 991 |
$pickupLocation = $deliveryOptions->getPickupLocation(); |
| 992 |
return [ |
| 993 |
__("delivery_type", "woocommerce-postnl") => WCPN_Data::getDeliveryTypesHuman()[$deliveryOptions->getDeliveryType()], |
| 994 |
__("pickup_location", "woocommerce-postnl") => |
| 995 |
sprintf("%s<br>%s %s<br>%s %s", |
| 996 |
$pickupLocation->getLocationName(), |
| 997 |
$pickupLocation->getStreet(), |
| 998 |
$pickupLocation->getNumber(), |
| 999 |
$pickupLocation->getPostalCode(), |
| 1000 |
$pickupLocation->getCity() |
| 1001 |
) |
| 1002 |
]; |
| 1003 |
} |
| 1004 |
|
| 1005 |
$confirmationData = [ |
| 1006 |
__("delivery_type", "woocommerce-postnl") => WCPN_Data::getDeliveryTypesHuman()[$deliveryOptions->getDeliveryType()], |
| 1007 |
]; |
| 1008 |
|
| 1009 |
if (WCPOST()->setting_collection->isEnabled(WCPOST_Settings::SETTING_SHOW_DELIVERY_DAY)) { |
| 1010 |
$confirmationData[__("Date:", 'woocommerce')] = wc_format_datetime(new WC_DateTime($deliveryOptions->getDate()));; |
| 1011 |
} |
| 1012 |
|
| 1013 |
if ($hasSignature || $hasOnlyRecipient) { |
| 1014 |
$confirmationData[__("extra_options", "woocommerce-postnl")] = |
| 1015 |
sprintf("%s<br>%s", |
| 1016 |
$hasSignature ? $signatureTitle : null, |
| 1017 |
$hasOnlyRecipient ? $onlyRecipientTitle : null); |
| 1018 |
} |
| 1019 |
|
| 1020 |
return $confirmationData; |
| 1021 |
} |
| 1022 |
|
| 1023 |
/** |
| 1024 |
* Print a table with the chosen delivery options on the confirmation page. |
| 1025 |
* |
| 1026 |
* @param array[]|null $selectedDeliveryOptions |
| 1027 |
*/ |
| 1028 |
public function printThankYouConfirmation(?array $selectedDeliveryOptions): void |
| 1029 |
{ |
| 1030 |
printf($this->generateThankYouConfirmation($selectedDeliveryOptions)); |
| 1031 |
} |
| 1032 |
|
| 1033 |
/** |
| 1034 |
* Print a table with the chosen delivery options in the confirmation email. |
| 1035 |
* |
| 1036 |
* @param array[]|null $selectedDeliveryOptions |
| 1037 |
*/ |
| 1038 |
public function printEmailConfirmation(?array $selectedDeliveryOptions): void |
| 1039 |
{ |
| 1040 |
printf($this->generateEmailConfirmation($selectedDeliveryOptions)); |
| 1041 |
} |
| 1042 |
|
| 1043 |
/** |
| 1044 |
* @param array[]|null $options |
| 1045 |
* |
| 1046 |
* @return string|null |
| 1047 |
*/ |
| 1048 |
public function generateThankYouConfirmation(?array $options): ?string |
| 1049 |
{ |
| 1050 |
if ($options) { |
| 1051 |
$htmlHeader = "<h2 class='woocommerce-column__title'> " . __("Delivery information:", "woocommerce-postnl") . "</h2><table>"; |
| 1052 |
|
| 1053 |
foreach ($options as $key => $option) { |
| 1054 |
if ($option) { |
| 1055 |
$htmlHeader .= "<tr><td>$key</td><td>" . __($option, "woocommerce-postnl") . "</td></tr>"; |
| 1056 |
} |
| 1057 |
} |
| 1058 |
|
| 1059 |
return $htmlHeader . "</table>"; |
| 1060 |
} |
| 1061 |
|
| 1062 |
return null; |
| 1063 |
} |
| 1064 |
|
| 1065 |
/** |
| 1066 |
* @param array[]|null $options |
| 1067 |
* |
| 1068 |
* @return string|null |
| 1069 |
*/ |
| 1070 |
public function generateEmailConfirmation(?array $options): ?string |
| 1071 |
{ |
| 1072 |
if ($options) { |
| 1073 |
$htmlHeader = "<h2 class='woocommerce-column__title'> " . __("Delivery information:", "woocommerce-postnl") . "</h2>"; |
| 1074 |
$htmlHeader .= "<table cellspacing='0' style='border: 1px solid #e5e5e5; margin-bottom: 20px;>"; |
| 1075 |
|
| 1076 |
foreach ($options as $key => $option) { |
| 1077 |
if ($option) { |
| 1078 |
$htmlHeader .= "<tr style='border: 1px solid #d5d5d5;'> |
| 1079 |
<td style='border: 1px solid #e5e5e5;'>$key</td> |
| 1080 |
<td style='border: 1px solid #e5e5e5;'>" . __($option, "woocommerce-postnl") . "</td> |
| 1081 |
</tr>"; |
| 1082 |
} |
| 1083 |
} |
| 1084 |
|
| 1085 |
return $htmlHeader . "</table>"; |
| 1086 |
} |
| 1087 |
|
| 1088 |
return null; |
| 1089 |
} |
| 1090 |
|
| 1091 |
/** |
| 1092 |
* Output a spinner. |
| 1093 |
* |
| 1094 |
* @param string $state |
| 1095 |
* @param array $args |
| 1096 |
*/ |
| 1097 |
public static function renderSpinner(string $state = "", array $args = []): void |
| 1098 |
{ |
| 1099 |
$spinners = [ |
| 1100 |
"loading" => get_site_url() . "/wp-admin/images/spinner.gif", |
| 1101 |
"success" => get_site_url() . "/wp-admin/images/yes.png", |
| 1102 |
"failed" => get_site_url() . "/wp-admin/images/no.png", |
| 1103 |
]; |
| 1104 |
|
| 1105 |
$arguments = []; |
| 1106 |
|
| 1107 |
$args["class"][] = "wcpn__spinner"; |
| 1108 |
|
| 1109 |
if ($state) { |
| 1110 |
$args["class"][] = "wcpn__spinner--$state"; |
| 1111 |
} |
| 1112 |
|
| 1113 |
foreach ($args as $arg => $value) { |
| 1114 |
if (is_array($value)) { |
| 1115 |
$value = implode(" ", $value); |
| 1116 |
} |
| 1117 |
$arguments[] = "$arg=\"$value\""; |
| 1118 |
} |
| 1119 |
|
| 1120 |
$attributes = implode(" ", $arguments); |
| 1121 |
|
| 1122 |
echo "<span $attributes>"; |
| 1123 |
foreach ($spinners as $spinnerState => $icon) { |
| 1124 |
printf( |
| 1125 |
'<img class="wcpn__spinner__%1$s" alt="%1$s" src="%2$s" style="display: %3$s;" />', |
| 1126 |
$spinnerState, |
| 1127 |
$icon, |
| 1128 |
$state === $spinnerState ? "block" : "none" |
| 1129 |
); |
| 1130 |
} |
| 1131 |
echo '</span>'; |
| 1132 |
} |
| 1133 |
|
| 1134 |
/** |
| 1135 |
* @param string $url |
| 1136 |
* @param string $alt |
| 1137 |
* @param string $icon |
| 1138 |
* @param array $rawAttributes |
| 1139 |
*/ |
| 1140 |
public static function renderAction(string $url, string $alt, string $icon, array $rawAttributes = []): void |
| 1141 |
{ |
| 1142 |
printf( |
| 1143 |
'<a href="%1$s" |
| 1144 |
class="button tips wcpn__action" |
| 1145 |
data-tip="%2$s" |
| 1146 |
%4$s> |
| 1147 |
<img class="wcpn__action__img wcpn__m--auto" src="%3$s" alt="%2$s" />', |
| 1148 |
wp_nonce_url($url, WCPOST::NONCE_ACTION), |
| 1149 |
$alt, |
| 1150 |
$icon, |
| 1151 |
wc_implode_html_attributes($rawAttributes) |
| 1152 |
); |
| 1153 |
|
| 1154 |
self::renderSpinner(); |
| 1155 |
echo "</a>"; |
| 1156 |
} |
| 1157 |
|
| 1158 |
/** |
| 1159 |
* @param array $shipment |
| 1160 |
* @param int $order_id |
| 1161 |
* |
| 1162 |
* @throws Exception |
| 1163 |
*/ |
| 1164 |
public static function renderTrackTraceLink(array $shipment, int $order_id): void |
| 1165 |
{ |
| 1166 |
$track_trace = $shipment["track_trace"] ?? null; |
| 1167 |
|
| 1168 |
if ($track_trace) { |
| 1169 |
$track_trace_url = self::getTrackTraceUrl($order_id, $track_trace); |
| 1170 |
$track_trace_link = sprintf( |
| 1171 |
'<a href="%s" target="_blank">%s</a>', |
| 1172 |
$track_trace_url, |
| 1173 |
$track_trace |
| 1174 |
); |
| 1175 |
} elseif (isset($shipment["shipment"]) && isset($shipment["shipment"]["options"])) { |
| 1176 |
$package_type = WCPN_Export::getPackageTypeHuman($shipment["shipment"]["options"]["package_type"]); |
| 1177 |
$track_trace_link = "($package_type)"; |
| 1178 |
} else { |
| 1179 |
$track_trace_link = __("(Unknown)", "woocommerce-postnl"); |
| 1180 |
} |
| 1181 |
|
| 1182 |
echo $track_trace_link; |
| 1183 |
} |
| 1184 |
|
| 1185 |
/** |
| 1186 |
* @param array $shipment |
| 1187 |
* @param int $order_id |
| 1188 |
*/ |
| 1189 |
public static function renderStatus(array $shipment, int $order_id): void |
| 1190 |
{ |
| 1191 |
echo $shipment["status"] ?? "–"; |
| 1192 |
|
| 1193 |
if (self::shipmentIsStatus($shipment, self::ORDER_STATUS_DELIVERED_AT_RECIPIENT) |
| 1194 |
|| self::shipmentIsStatus($shipment, self::ORDER_STATUS_DELIVERED_READY_FOR_PICKUP) |
| 1195 |
|| self::shipmentIsStatus($shipment, self::ORDER_STATUS_DELIVERED_PACKAGE_PICKED_UP) |
| 1196 |
) { |
| 1197 |
$order = WCX::get_order($order_id); |
| 1198 |
// This will be addressed in MY-24881 |
| 1199 |
// $order->update_status('wc-custom-delivered'); |
| 1200 |
} |
| 1201 |
} |
| 1202 |
|
| 1203 |
/** |
| 1204 |
* @param array $shipment |
| 1205 |
* @param int $status |
| 1206 |
* |
| 1207 |
* @return bool |
| 1208 |
*/ |
| 1209 |
public static function shipmentIsStatus(array $shipment, int $status): bool |
| 1210 |
{ |
| 1211 |
return strstr($shipment['status'], (new WCPN_Export())->getShipmentStatusName($status)); |
| 1212 |
} |
| 1213 |
|
| 1214 |
/** |
| 1215 |
* Remove options that aren't allowed and return the edited array. |
| 1216 |
* |
| 1217 |
* @param array $data |
| 1218 |
* @param string $country |
| 1219 |
* |
| 1220 |
* @return mixed |
| 1221 |
*/ |
| 1222 |
public static function removeDisallowedDeliveryOptions(array $data, string $country): array |
| 1223 |
{ |
| 1224 |
$data['package_type'] = $data['package_type'] ?? AbstractConsignment::DEFAULT_PACKAGE_TYPE_NAME; |
| 1225 |
$isHomeCountry = WCPN_Data::isHomeCountry($country); |
| 1226 |
$isEuCountry = WCPN_Country_Codes::isEuCountry($country); |
| 1227 |
$isBelgium = AbstractConsignment::CC_BE === $country; |
| 1228 |
$isPackage = AbstractConsignment::PACKAGE_TYPE_PACKAGE_NAME === $data['package_type']; |
| 1229 |
$isDigitalStamp = AbstractConsignment::PACKAGE_TYPE_DIGITAL_STAMP_NAME === $data['package_type']; |
| 1230 |
|
| 1231 |
if (! $isHomeCountry || ! $isPackage) { |
| 1232 |
$data['shipment_options']['age_check'] = false; |
| 1233 |
$data['shipment_options']['return_shipment'] = false; |
| 1234 |
|
| 1235 |
if (! $isBelgium || ! $isPackage) { |
| 1236 |
$data['shipment_options']['insured'] = false; |
| 1237 |
$data['shipment_options']['insured_amount'] = 0; |
| 1238 |
} |
| 1239 |
} |
| 1240 |
|
| 1241 |
if (! $isPackage || (! $isHomeCountry && ! $isEuCountry)) { |
| 1242 |
$data['shipment_options']['large_format'] = false; |
| 1243 |
} |
| 1244 |
|
| 1245 |
if (! $isDigitalStamp) { |
| 1246 |
unset($data['extra_options']['weight']); |
| 1247 |
} |
| 1248 |
|
| 1249 |
return $data; |
| 1250 |
} |
| 1251 |
} |
| 1252 |
|
| 1253 |
return new WCPOST_Admin(); |
| 1254 |
|