PluginProbe
MakeCommerce for WooCommerce / 4.1.0
MakeCommerce for WooCommerce v4.1.0
4.1.0 4.0.8 trunk 1.0 1.0.1 1.0.2 1.0.3 1.1.0 1.1.1 1.1.2 1.1.3 1.1.4 1.1.5 1.1.6 1.1.7 2.0.0 2.1.0 2.1.1 2.1.2 2.1.3 2.1.4 2.1.5 2.2.0 2.2.1 2.2.2 All 96 releases
makecommerce / shipping / method / parcelmachine / parcelmachine.php

parcelmachine.php in MakeCommerce for WooCommerce 4.1.0, at shipping/method/parcelmachine/parcelmachine.php

510 lines 19.0 KB
No matching file
Up and down to move Enter to open Esc to close
Raw Download Zip
1 <?php
2
3 namespace MakeCommerce\Shipping\Method;
4
5 /**
6 * Smartpost parcelmachine shipping method.
7 * Defines all Smartpost specific options.
8 *
9 * @since 3.0.0
10 */
11
12 use \MakeCommerce\Shipping\Method\ParcelMachine\Map;
13
14 abstract class ParcelMachine extends \MakeCommerce\Shipping\Method {
15
16 use Map;
17
18 public $type = "apt";
19 public $identifier = "parcelmachine";
20 public $identifierString;
21
22 private $mk_lpexpress_template;
23 private $prioritization;
24 private $searchable_parcelmachines;
25 private $short_office_names;
26 private $use_white_apts;
27
28 /**
29 * Required function for all methods, initializes method type
30 *
31 * @since 3.0.0
32 */
33 public function initialize() {
34
35 $this->check_updates();
36
37 //load all hooks/filters for method type
38 $this->set_method_type_hooks();
39
40 //set parcelmachine specific properties
41 if ( isset( $this->settings['prioritization'] ) ) {
42 $this->prioritization = $this->settings['prioritization'];
43 }
44
45 if ( isset( $this->settings['short_office_names'] ) ) {
46 $this->short_office_names = $this->settings['short_office_names'];
47 }
48
49 if ( isset( $this->settings['use_white_apts'] ) ) {
50 $this->use_white_apts = $this->settings['use_white_apts'];
51 }
52
53 if ( isset( $this->settings['searchable_parcelmachines'] ) ) {
54 $this->searchable_parcelmachines = $this->settings['searchable_parcelmachines'];
55 }
56
57 if ( isset( $this->settings['mk_lpexpress_template'] ) ) {
58 $this->mk_lpexpress_template = $this->settings['mk_lpexpress_template'];
59 if ( get_option( 'mk_lpexpress_template' ) === false ) {
60 add_option( 'mk_lpexpress_template', $this->settings['mk_lpexpress_template'] );
61 } else {
62 update_option( 'mk_lpexpress_template', $this->settings['mk_lpexpress_template'] );
63 }
64 }
65
66 //needed for identifier translation
67 $this->identifierString = __( "parcelmachine", 'wc_makecommerce_domain' );
68 }
69
70 /**
71 * Get method title
72 *
73 * @since 3.0.0
74 */
75 public function return_method_title() {
76
77 return $this->carrier_title . " " . __( "parcel machine (MC)", 'wc_makecommerce_domain' );
78 }
79
80 /**
81 * Initialize method type specific checkout fields
82 *
83 * @since 3.0.0
84 */
85 public function initialize_method_type_checkout_fields() {
86
87 $this->form_fields['prioritization'] = array(
88 'title' => __('Prioritize', 'wc_makecommerce_domain'),
89 'type' => 'checkbox',
90 'label' => __('Bigger cities will be on top of list, others sorted alphabetically', 'wc_makecommerce_domain'),
91 'default' => 'yes'
92 );
93
94 $this->form_fields['short_office_names'] = array(
95 'title' => __('Short names', 'wc_makecommerce_domain'),
96 'type' => 'checkbox',
97 'label' => __('Display only parcel machine names, without addresses', 'wc_makecommerce_domain'),
98 'default' => 'no'
99 );
100
101 $this->form_fields['searchable_parcelmachines'] = array(
102 'title' => __('Search', 'wc_makecommerce_domain'),
103 'type' => 'checkbox',
104 'label' => __('Make parcel machine selection searchable', 'wc_makecommerce_domain'),
105 'default' => 'no'
106 );
107 }
108
109 /**
110 * Set method type specific hooks/filters
111 *
112 * @since 3.0.0
113 */
114 public function set_method_type_hooks() {
115
116 $priority = 15;
117
118 //add shipping metadata to order
119 add_action( 'woocommerce_checkout_update_order_meta', array( $this, 'add_parcelmachine_order_meta' ) );
120
121 if ( ! $this->check_filter_hook_initialization( 'woocommerce_review_order_after_shipping', $priority ) ) {
122 //add parcel machines select box to checkout
123 add_filter( 'woocommerce_review_order_after_shipping' , array( $this, 'add_parcelmachine_checkout_fields' ), $priority );
124 }
125 }
126
127 /**
128 * Set parcelmachine specific checkout fields
129 *
130 * @since 3.0.0
131 */
132 public function add_parcelmachine_checkout_fields() {
133 echo self::prepare_parcelmachine_checkout_html( $this->id );
134 }
135
136 /**
137 * Prepare parcelmachine specific checkout fields
138 *
139 * @since 3.5.0
140 */
141 public static function prepare_parcelmachine_checkout_html( $id, $table = true ) {
142
143 $options = get_option( 'woocommerce_' . $id . '_settings', [] );
144 $ext = explode( '_', $id, 2 )[1];
145
146 if ( empty( $options ) ) {
147 return '';
148 }
149
150 $country = WC()->customer->get_shipping_country();
151
152 $aptopts = [ 'use_white_apts' => $options['use_white_apts'] ?? null ];
153 $machines = \MakeCommerce\Shipping::mk_get_machines( $ext, $country, $aptopts );
154
155 //sort machines
156 $machines = self::sort_machines( $machines, $options['prioritization'] ?? 'yes' );
157
158 // Create new class and placeholder for searchable parcel machines
159 $placeholder = __( '-- select parcel machine --', 'wc_makecommerce_domain' );
160 $searchable_class = '';
161 if ( isset( $options['searchable_parcelmachines'] ) && $options['searchable_parcelmachines'] === 'yes' ) {
162 $searchable_class = ' parcel-machine-select-box-searchable';
163 $placeholder = '';
164 }
165
166 $html = '';
167
168 if ($table ) {
169 $html .= '
170 <tr style="display: none;" class="parcel_machine_checkout parcel_machine_checkout_parcelmachine_' . mb_strtolower( $ext ) . '">
171 <td colspan="2">
172 ';
173 }
174
175 $html .= '
176 <p class="form-row" id="' . esc_attr( $id ) . '_field">
177 <select class="select parcel-machine-select-box' . $searchable_class . '" name="' . esc_attr( $id ) . '" id="' . esc_attr( $id ) . '">
178 <option value="">' . $placeholder . '</option>
179 ';
180
181 $html .= self::create_parcelmachine_html( $machines, $options['short_office_names'] ?? 'no' );
182
183 $html .= '
184 </select>
185 </p>';
186
187 if ( $table && self::map_enabled() ) {
188 $html .= '
189 <div class="mc_pmmap_choose_button">
190 <img class="mc_pmmap_pin" src="' . plugin_dir_url(__FILE__) . 'images/pin.svg' . '">
191 <p>' . __( 'Choose machine from map', 'wc_makecommerce_domain' ) . '</p>
192 </div>
193 ';
194 }
195
196 if ($table ) {
197 $html .= '
198 </td>
199 </tr>
200 ';
201 }
202
203 return $html;
204 }
205
206 /**
207 * Creates html for displaying parcel machines
208 *
209 * @since 3.0.15
210 */
211 public static function create_parcelmachine_html( $machines, $short_names = 'no', $selected_machine_id = null ) {
212
213 $output = '';
214
215 //group machines by city and set name
216 $city_machines = array();
217 foreach ( $machines as $machine ) {
218 if ( $short_names !== 'yes' ) {
219 // Original name for map
220 $machine["original_name"] = $machine["name"];
221 $machine["name"] .= ' - ' . $machine['city'] . ', ' . $machine['address'];
222 }
223
224 $city_machines[$machine["city"]][] = $machine;
225 }
226
227 foreach ( $city_machines as $city=>$grouped_machines ) {
228 $output .= '<optgroup label="' . $city . '">';
229
230 foreach ( $grouped_machines as $machine ) {
231 if ( isset($machine['x']) && isset($machine['y'])) {
232 $output .= '<option';
233 if ( isset( $machine["original_name"] ) ) {
234 $output .= ' name="'.esc_attr( $machine['original_name'] ).'"';
235 } else {
236 $output .= ' name="'.esc_attr( $machine['name'] ).'"';
237 }
238 $output .= ' x="'.esc_attr( $machine['x'] ).'"'
239 .' y="'.esc_attr( $machine['y'] ).'"'
240 .' carrier="'.esc_attr( $machine['carrier'] ).'"'
241 .' city="'.esc_attr( $machine['city'] ).'"'
242 .' address="'.esc_attr( $machine['address'] ).'"'
243 .' zip="'.esc_attr( $machine['zip'] ).'"'
244 .' commentet="'.esc_attr( $machine['commentEt'] ).'"'
245 .' commentlv="'.esc_attr( $machine['commentLv'] ).'"'
246 .' commentlt="'.esc_attr( $machine['commentLt'] ).'"'
247 .' commentfi="'.esc_attr( $machine['commentFi'] ).'"'
248 .' availability="'.esc_attr( $machine['availability'] ).'"'
249 .' value="'.esc_attr( $machine['carrier'].'||'.$machine['id'] ).'" '.( $selected_machine_id === $machine['id'] ? ' selected="selected"' : '' ).'>'.$machine["name"].'</option>';
250
251 } else {
252 $output .= '<option value="'.esc_attr( $machine['carrier'].'||'.$machine['id'] ).'" '.( $selected_machine_id === $machine['id'] ? ' selected="selected"' : '' ).'>'.$machine["name"].'</option>';
253 }
254 }
255
256 $output .= '</optgroup>';
257 }
258
259 return $output;
260 }
261
262 /**
263 * Adds metadata to order about shipping
264 *
265 * @since 3.0.0
266 */
267 public function add_parcelmachine_order_meta( $order_id ) {
268
269 $shipping_method = !empty( $_POST['shipping_method'] ) ? $_POST['shipping_method'] : false;
270
271 if ( !empty($shipping_method[0] ) ) {
272 $shipping_method_ext = explode( ':', $shipping_method[0] );
273 }
274
275 if ( $shipping_method_ext[0] === $this->id && !empty( $_POST[$this->id] ) ) {
276
277 \MakeCommerce\Shipping::update_order_parcelmachine_meta( $_POST[$this->id], $order_id );
278 }
279 }
280
281 /**
282 * Convert old methods to shipping zones if current site wc_mc_version is older than one of this module
283 *
284 * @since 3.0.0
285 */
286 private function check_updates() {
287
288 if ( get_site_option('wc_mc_version', 0) < WC_MC_VERSION) {
289
290 update_site_option('wc_mc_version', WC_MC_VERSION);
291
292 error_log("Need to update from [" . get_site_option( 'wc_mc_version', 0 ) . "] to [" . WC_MC_VERSION . "]");
293
294 if ( WC_MC_VERSION === 2.0 ) {
295
296 // Check if omniva / smartpost is enabled and in which countries
297 // Convert to shipping zone
298 foreach ( array(
299 'parcelmachine_omniva' => 'MakeCommerce\Shipping\Method\ParcelMachine\Omniva',
300 'parcelmachine_smartpost' => 'MakeCommerce\Shipping\Method\ParcelMachine\Smartpost',
301 'parcelmachine_dpd' => 'MakeCommerce\Shipping\Method\ParcelMachine\DPD',
302 'parcelmachine_lp_express_lt' => 'MakeCommerce\Shipping\Method\ParcelMachine\LPExpress'
303
304 ) as $method_name => $method_class ) {
305
306 $parcel_machine_method = new $method_class();
307
308 if ( $parcel_machine_method->enable === 'yes' ) {
309
310 $zones = \WC_Shipping_Zones::get_zones();
311
312 //skip if there were no countries selected
313 if ( !empty( $parcel_machine_method->countries ) ) {
314 continue;
315 }
316
317 foreach ( $parcel_machine_method->countries as $ecountry ) {
318
319 $has_ecountry = false;
320
321 foreach ( $zones as $zone ) {
322 foreach ( $zone['zone_locations'] as $location ) {
323
324 if ( $location->code === $ecountry ) {
325
326 $has_ecountry = $zone['zone_id'];
327
328 //skip complete class if a shippingzone with this name has alread been defined
329 foreach ( $zone['shipping_methods'] as $method ) {
330 if ( $method->id === $method_name ) {
331
332 continue 4;
333 }
334 }
335 }
336 }
337 }
338
339 //convert to shipping zones
340 if ( !$has_ecountry ) {
341
342 $zone = new \WC_Shipping_Zone();
343 $zone->set_zone_name( $ecountry );
344 $zone->add_location( $ecountry, 'country' );
345
346 $zone->save();
347 } else {
348 $zone = new \WC_Shipping_Zone( $has_ecountry );
349 }
350
351 $instance_id = $zone->add_shipping_method($method_name);
352 $transport_class = new $method_class($instance_id);
353
354 $price = !empty( $transport_class->settings['price_'.strtolower($ecountry)] ) ? $transport_class->settings['price_'.strtolower($ecountry)] : 0;
355
356 $free_shipping_min_amount = !empty( $transport_class->settings['free_shipping_min_amount_'.strtolower( $ecountry )] ) ? $transport_class->settings['free_shipping_min_amount_'.strtolower($ecountry)] : 0;
357 $transport_class->set_post_data( array( $transport_class->get_field_key( 'price' ) => $price, $transport_class->get_field_key( 'free_shipping_min_amount' ) => $free_shipping_min_amount ) );
358
359 $transport_class->process_admin_options();
360 }
361 }
362 }
363 }
364 }
365 }
366
367 /**
368 * Checks if there is a product that doesn't fit in parcelmachine
369 *
370 * @since 3.0.0
371 */
372 private function fits_parcel_machine( $package ) {
373
374 foreach ( $package['contents'] as $line ) {
375 if ( get_post_meta( $line['product_id'], '_no_parcel_machine', true ) === 'yes' ) {
376 return false;
377 }
378 }
379
380 return true;
381 }
382
383 /**
384 * Checks if shipping method is available.
385 * In addition to parent is_available, also checks if package fits in parcel machine
386 *
387 * @since 3.0.0
388 */
389 public function is_available( $package ) {
390
391 if ( !$this->fits_parcel_machine( $package ) ) {
392 return false;
393 }
394
395 return parent::is_available( $package );
396 }
397
398 /**
399 * Sort machines (biggest cities first)
400 *
401 * @since 3.0.0
402 */
403 private static function sort_machines( $machines, $prioritization ) {
404
405 if ( $prioritization === 'yes' ) {
406
407 usort( $machines, function( $a, $b ) {
408
409 $sortorder = array(
410 'tallinn', 'tartu linn','tartu', 'narva', 'pärnu linn','pärnu', 'viljandi', 'kohtla-järve', 'rakvere', 'maardu', 'sillamäe', 'kuressaare',
411 'helsinki', 'espoo', 'tampere', 'vantaa', 'oulu', 'turku', 'jüväskülä', 'lahti', 'kuopio', 'kouvola',
412 'rīga','riga', 'daugavpils', 'liepāja','liepaja', 'jelgava', 'jūrmala','jurmala', 'ventspils', 'rezekne', 'valmiera', 'jekabpils',
413 'vilnius', 'kaunas', 'klaipeda', 'siauliai', 'panevezys', 'alytus', 'mariampole', 'mazeikiai', 'jonava', 'utena'
414 );
415
416 $acity = mb_strtolower($a['city']);
417 $bcity = mb_strtolower($b['city']);
418
419 if ( !$acity ) {
420 $acity = 'xxxxxxx';
421 }
422
423 if ( !$bcity ) {
424 $bcity = 'xxxxxxx';
425 }
426
427 $aidx = array_search( $acity, $sortorder );
428 $bidx = array_search ($bcity, $sortorder );
429
430 if ( $aidx !== false ) {
431 $acity = str_pad( $aidx, 4, "0", STR_PAD_LEFT ) . '-' . $acity;
432 }
433
434 if ( $bidx !== false ) {
435 $bcity = str_pad( $bidx, 4, "0", STR_PAD_LEFT ) . '-' . $bcity;
436 }
437
438 $acity .= '-' . mb_strtolower($a['name']);
439 $bcity .= '-' . mb_strtolower($b['name']);
440
441 return $acity < $bcity ? -1 : 1;
442 } );
443 }
444
445 return $machines;
446 }
447
448 /**
449 * Generates HTML for checking MakeCommerce shipment mediation availability
450 *
451 * @since 3.0.0
452 */
453 public function generate_verify_feature_swc_html( $key, $data ) {
454
455 $field = $this->get_field_key( $key );
456 $defaults = [
457 'title' => '',
458 'disabled' => false,
459 'class' => '',
460 'css' => '',
461 'placeholder' => '',
462 'type' => 'text',
463 'desc_tip' => false,
464 'description' => '',
465 'custom_attributes' => []
466 ];
467
468 $data = wp_parse_args( $data, $defaults );
469
470 \MakeCommerce::mc_enqueue_script(
471 'MC_TRANSPORT_MEDIATION_VERIFICATION',
472 dirname( __FILE__ ) . '/js/transport_mediation_verification.js',
473 [
474 'site_url' => get_site_url(),
475 'enabled' => __( 'The transport mediation service is already enabled for your shop. You are good to go!', 'wc_makecommerce_domain' ),
476 'not_enabled' => __('The transport mediation service is NOT ENABLED enabled for your shop. Please go to merchant portal to activate it!', 'wc_makecommerce_domain' ),
477 'error' => __( 'There was an error with your request. Please try again.', 'wc_makecommerce_domain' )
478 ],
479 [ 'jquery' ]
480 );
481
482 ob_start();
483 ?>
484 <tr valign="top">
485 <th scope="row" class="titledesc">
486 <label for="<?php echo esc_attr( $field ); ?>"><?php echo wp_kses_post( $data['title'] ); ?></label>
487 <?php echo $this->get_tooltip_html( $data ); ?>
488 </th>
489 <td class="forminp">
490 <fieldset>
491 <legend class="screen-reader-text">
492 <span><?php echo wp_kses_post( $data['title'] ); ?></span>
493 </legend>
494 <input id="verify_feature_swc" class="button <?php echo esc_attr( $data['class'] ); ?>" type="button" name="<?php echo esc_attr( $field ); ?>" id="<?php echo esc_attr( $field ); ?>" style="<?php echo esc_attr( $data['css'] ); ?>" value="<?php echo esc_attr( $data['placeholder'] ); ?>" placeholder="<?php echo esc_attr( $data['placeholder'] ); ?>" <?php disabled( $data['disabled'], true ); ?> <?php echo $this->get_custom_attribute_html( $data ); ?> />
495 </fieldset>
496 </td>
497 </tr>
498 <?php
499
500 return ob_get_clean();
501 }
502
503 /**
504 * Force creating a function for initializing method specific form fields
505 *
506 * @since 3.0.0
507 */
508 abstract public function initialize_method_form_fields();
509 }
510