Version Description
Download this release
Release Info
Developer | aftership |
Plugin | AfterShip – WooCommerce Tracking |
Version | 1.7.7 |
Comparing to | |
See all releases |
Code changes from version 1.7.6 to 1.7.7
- aftership.php +1 -1
- assets/js/couriers.js +16 -10
- readme.txt +1 -1
- trunk/aftership-backward-compatibility.php +21 -0
- trunk/aftership-fields.php +86 -0
- trunk/aftership-functions.php +15 -0
- trunk/aftership.php +608 -0
- trunk/api/class-aftership-api-authentication.php +129 -0
- trunk/api/class-aftership-api-json-handler.php +77 -0
- trunk/api/class-aftership-api-orders.php +505 -0
- trunk/api/class-aftership-api-resource.php +416 -0
- trunk/api/class-aftership-api-server.php +758 -0
- trunk/api/interface-aftership-api-handler.php +46 -0
- trunk/assets/css/admin.css +15 -0
- trunk/assets/js/admin.js +123 -0
- trunk/assets/js/couriers.js +2494 -0
- trunk/assets/js/footer.js +1 -0
- trunk/assets/js/setting.js +72 -0
- trunk/assets/js/util.js +18 -0
- trunk/assets/plugin/chosen/chosen-sprite.png +0 -0
- trunk/assets/plugin/chosen/chosen-sprite@2x.png +0 -0
- trunk/assets/plugin/chosen/chosen.jquery.min.js +2 -0
- trunk/assets/plugin/chosen/chosen.min.css +3 -0
- trunk/assets/plugin/chosen/chosen.proto.min.js +2 -0
- trunk/class-aftership-api.php +182 -0
- trunk/class-aftership-dependencies.php +35 -0
- trunk/class-aftership-settings.php +295 -0
- trunk/readme.txt +205 -0
aftership.php
CHANGED
@@ -3,7 +3,7 @@
|
|
3 |
Plugin Name: AfterShip - WooCommerce Tracking
|
4 |
Plugin URI: http://aftership.com/
|
5 |
Description: Add tracking number and carrier name to WooCommerce, display tracking info at order history page, auto import tracking numbers to AfterShip.
|
6 |
-
Version: 1.7.
|
7 |
Author: AfterShip
|
8 |
Author URI: http://aftership.com
|
9 |
|
3 |
Plugin Name: AfterShip - WooCommerce Tracking
|
4 |
Plugin URI: http://aftership.com/
|
5 |
Description: Add tracking number and carrier name to WooCommerce, display tracking info at order history page, auto import tracking numbers to AfterShip.
|
6 |
+
Version: 1.7.7
|
7 |
Author: AfterShip
|
8 |
Author URI: http://aftership.com
|
9 |
|
assets/js/couriers.js
CHANGED
@@ -1,11 +1,11 @@
|
|
1 |
function get_couriers() {
|
2 |
var data = [
|
3 |
-
|
4 |
-
|
5 |
-
|
6 |
-
|
7 |
-
|
8 |
-
|
9 |
{
|
10 |
"slug": "17postservice",
|
11 |
"name": "17 Post Service",
|
@@ -2146,10 +2146,10 @@ function get_couriers() {
|
|
2146 |
"required_fields": []
|
2147 |
},
|
2148 |
{
|
2149 |
-
|
2150 |
-
|
2151 |
-
|
2152 |
-
|
2153 |
},
|
2154 |
{
|
2155 |
"slug": "tgx",
|
@@ -2482,6 +2482,12 @@ function get_couriers() {
|
|
2482 |
"name": "Zyllem",
|
2483 |
"other_name": "RocketUncle",
|
2484 |
"required_fields": []
|
|
|
|
|
|
|
|
|
|
|
|
|
2485 |
}
|
2486 |
];
|
2487 |
return data;
|
1 |
function get_couriers() {
|
2 |
var data = [
|
3 |
+
{
|
4 |
+
"slug": "alliedexpress",
|
5 |
+
"name": "Allied Express",
|
6 |
+
"other_name": "",
|
7 |
+
"required_fields": []
|
8 |
+
},
|
9 |
{
|
10 |
"slug": "17postservice",
|
11 |
"name": "17 Post Service",
|
2146 |
"required_fields": []
|
2147 |
},
|
2148 |
{
|
2149 |
+
"slug": "tcs",
|
2150 |
+
"name": "TCS",
|
2151 |
+
"other_name": "TCS",
|
2152 |
+
"required_fields": []
|
2153 |
},
|
2154 |
{
|
2155 |
"slug": "tgx",
|
2482 |
"name": "Zyllem",
|
2483 |
"other_name": "RocketUncle",
|
2484 |
"required_fields": []
|
2485 |
+
},
|
2486 |
+
{
|
2487 |
+
"slug": "tipsa",
|
2488 |
+
"name": "TIPSA",
|
2489 |
+
"other_name": "",
|
2490 |
+
"required_fields": []
|
2491 |
}
|
2492 |
];
|
2493 |
return data;
|
readme.txt
CHANGED
@@ -4,7 +4,7 @@ Donate link: https://www.aftership.com/
|
|
4 |
Tags: shipping, tracking, ups, usps, fedex, dhl, tnt, dpd, post, shipment, woocommerce, tracking number, aftership, package tracking, fulfilment, tracking link, carrier, courier, woo commerce, woocommerce shipment tracking, shipping details plugin, widget, shipstation, track, package
|
5 |
Requires at least: 2.9
|
6 |
Tested up to: 4.2.2
|
7 |
-
Stable tag: 1.7.
|
8 |
License: GPLv2 or later
|
9 |
License URI: http://www.gnu.org/licenses/gpl-2.0.html
|
10 |
|
4 |
Tags: shipping, tracking, ups, usps, fedex, dhl, tnt, dpd, post, shipment, woocommerce, tracking number, aftership, package tracking, fulfilment, tracking link, carrier, courier, woo commerce, woocommerce shipment tracking, shipping details plugin, widget, shipstation, track, package
|
5 |
Requires at least: 2.9
|
6 |
Tested up to: 4.2.2
|
7 |
+
Stable tag: 1.7.7
|
8 |
License: GPLv2 or later
|
9 |
License URI: http://www.gnu.org/licenses/gpl-2.0.html
|
10 |
|
trunk/aftership-backward-compatibility.php
ADDED
@@ -0,0 +1,21 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
<?php
|
2 |
+
/**
|
3 |
+
* Get woo order ID
|
4 |
+
*/
|
5 |
+
if ( ! function_exists( 'get_order_id' ) ) {
|
6 |
+
function get_order_id($order) {
|
7 |
+
return (method_exists($order, 'get_id'))? $order->get_id() : $order->id;
|
8 |
+
}
|
9 |
+
}
|
10 |
+
|
11 |
+
/**
|
12 |
+
* @see https://docs.woocommerce.com/wc-apidocs/source-class-WC_Abstract_Legacy_Order.html#406
|
13 |
+
* Get attribute from WC_Order
|
14 |
+
*
|
15 |
+
*/
|
16 |
+
if ( ! function_exists( 'order_post_meta_getter' ) ) {
|
17 |
+
function order_post_meta_getter($order, $attr) {
|
18 |
+
$meta = get_post_meta(get_order_id($order), '_'. $attr, true);
|
19 |
+
return $meta;
|
20 |
+
}
|
21 |
+
}
|
trunk/aftership-fields.php
ADDED
@@ -0,0 +1,86 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
<?php
|
2 |
+
/**
|
3 |
+
* Created by PhpStorm.
|
4 |
+
* User: Sunny Chow
|
5 |
+
* Date: 4/2/15
|
6 |
+
* Time: 6:08 PM
|
7 |
+
*/
|
8 |
+
|
9 |
+
$aftership_fields = array(
|
10 |
+
'aftership_tracking_provider_name' => array(
|
11 |
+
'id' => 'aftership_tracking_provider_name',
|
12 |
+
'type' => 'text',
|
13 |
+
'label' => '',
|
14 |
+
'placeholder' => '',
|
15 |
+
'description' => '',
|
16 |
+
'class' => 'hidden'
|
17 |
+
),
|
18 |
+
|
19 |
+
'aftership_tracking_required_fields' => array(
|
20 |
+
'id' => 'aftership_tracking_required_fields',
|
21 |
+
'type' => 'text',
|
22 |
+
'label' => '',
|
23 |
+
'placeholder' => '',
|
24 |
+
'description' => '',
|
25 |
+
'class' => 'hidden'
|
26 |
+
),
|
27 |
+
|
28 |
+
'aftership_tracking_number' => array(
|
29 |
+
'id' => 'aftership_tracking_number',
|
30 |
+
'type' => 'text',
|
31 |
+
'label' => 'Tracking number',
|
32 |
+
'placeholder' => '',
|
33 |
+
'description' => '',
|
34 |
+
'class' => ''
|
35 |
+
),
|
36 |
+
|
37 |
+
'aftership_tracking_shipdate' => array(
|
38 |
+
'key' => 'tracking_ship_date',
|
39 |
+
'id' => 'aftership_tracking_shipdate',
|
40 |
+
'type' => 'date',
|
41 |
+
'label' => 'Date shipped',
|
42 |
+
'placeholder' => 'YYYY-MM-DD',
|
43 |
+
'description' => '',
|
44 |
+
'class' => 'date-picker-field hidden-field'
|
45 |
+
),
|
46 |
+
|
47 |
+
'aftership_tracking_postal' => array(
|
48 |
+
'key' => 'tracking_postal_code',
|
49 |
+
'id' => 'aftership_tracking_postal',
|
50 |
+
'type' => 'text',
|
51 |
+
'label' => 'Postal Code',
|
52 |
+
'placeholder' => '',
|
53 |
+
'description' => '',
|
54 |
+
'class' => 'hidden-field'
|
55 |
+
),
|
56 |
+
|
57 |
+
'aftership_tracking_account' => array(
|
58 |
+
'key' => 'tracking_account_number',
|
59 |
+
'id' => 'aftership_tracking_account',
|
60 |
+
'type' => 'text',
|
61 |
+
'label' => 'Account name',
|
62 |
+
'placeholder' => '',
|
63 |
+
'description' => '',
|
64 |
+
'class' => 'hidden-field'
|
65 |
+
),
|
66 |
+
|
67 |
+
'aftership_tracking_key' => array(
|
68 |
+
'key' => 'tracking_key',
|
69 |
+
'id' => 'aftership_tracking_key',
|
70 |
+
'type' => 'text',
|
71 |
+
'label' => 'Tracking key',
|
72 |
+
'placeholder' => '',
|
73 |
+
'description' => '',
|
74 |
+
'class' => 'hidden-field'
|
75 |
+
),
|
76 |
+
|
77 |
+
'aftership_tracking_destination_country' => array(
|
78 |
+
'key' => 'tracking_destination_country',
|
79 |
+
'id' => 'aftership_tracking_destination_country',
|
80 |
+
'type' => 'text',
|
81 |
+
'label' => 'Destination Country',
|
82 |
+
'placeholder' => '',
|
83 |
+
'description' => '',
|
84 |
+
'class' => 'hidden-field'
|
85 |
+
)
|
86 |
+
);
|
trunk/aftership-functions.php
ADDED
@@ -0,0 +1,15 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
<?php
|
2 |
+
/**
|
3 |
+
* Functions used by plugins
|
4 |
+
*/
|
5 |
+
if ( ! class_exists( 'AfterShip_Dependencies' ) )
|
6 |
+
require_once 'class-aftership-dependencies.php';
|
7 |
+
|
8 |
+
/**
|
9 |
+
* WC Detection
|
10 |
+
*/
|
11 |
+
if ( ! function_exists( 'is_woocommerce_active' ) ) {
|
12 |
+
function is_woocommerce_active() {
|
13 |
+
return AfterShip_Dependencies::woocommerce_active_check();
|
14 |
+
}
|
15 |
+
}
|
trunk/aftership.php
ADDED
@@ -0,0 +1,608 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
<?php
|
2 |
+
/*
|
3 |
+
Plugin Name: AfterShip - WooCommerce Tracking
|
4 |
+
Plugin URI: http://aftership.com/
|
5 |
+
Description: Add tracking number and carrier name to WooCommerce, display tracking info at order history page, auto import tracking numbers to AfterShip.
|
6 |
+
Version: 1.7.7
|
7 |
+
Author: AfterShip
|
8 |
+
Author URI: http://aftership.com
|
9 |
+
|
10 |
+
Copyright: © AfterShip
|
11 |
+
*/
|
12 |
+
|
13 |
+
/**
|
14 |
+
* Security Note
|
15 |
+
*/
|
16 |
+
defined('ABSPATH') or die("No script kiddies please!");
|
17 |
+
|
18 |
+
/**
|
19 |
+
* Required functions
|
20 |
+
*/
|
21 |
+
if (!function_exists('is_woocommerce_active'))
|
22 |
+
require_once('aftership-functions.php');
|
23 |
+
require_once('aftership-backward-compatibility.php');
|
24 |
+
|
25 |
+
/**
|
26 |
+
* Plugin updates
|
27 |
+
*/
|
28 |
+
|
29 |
+
if (is_woocommerce_active()) {
|
30 |
+
|
31 |
+
/**
|
32 |
+
* AfterShip class
|
33 |
+
*/
|
34 |
+
if (!class_exists('AfterShip')) {
|
35 |
+
|
36 |
+
final class AfterShip
|
37 |
+
{
|
38 |
+
|
39 |
+
protected static $_instance = null;
|
40 |
+
|
41 |
+
public static function instance()
|
42 |
+
{
|
43 |
+
if (is_null(self::$_instance)) {
|
44 |
+
self::$_instance = new self();
|
45 |
+
}
|
46 |
+
return self::$_instance;
|
47 |
+
}
|
48 |
+
|
49 |
+
|
50 |
+
/**
|
51 |
+
* Constructor
|
52 |
+
*/
|
53 |
+
public function __construct()
|
54 |
+
{
|
55 |
+
$this->includes();
|
56 |
+
|
57 |
+
$this->api = new AfterShip_API();
|
58 |
+
|
59 |
+
$options = get_option('aftership_option_name');
|
60 |
+
if ($options) {
|
61 |
+
|
62 |
+
if (isset($options['plugin'])) {
|
63 |
+
$plugin = $options['plugin'];
|
64 |
+
if ($plugin == 'aftership') {
|
65 |
+
add_action('admin_print_scripts', array(&$this, 'library_scripts'));
|
66 |
+
add_action('in_admin_footer', array(&$this, 'include_footer_script'));
|
67 |
+
add_action('admin_print_styles', array(&$this, 'admin_styles'));
|
68 |
+
add_action('add_meta_boxes', array(&$this, 'add_meta_box'));
|
69 |
+
add_action('woocommerce_process_shop_order_meta', array(&$this, 'save_meta_box'), 0, 2);
|
70 |
+
add_action('plugins_loaded', array($this, 'load_plugin_textdomain'));
|
71 |
+
|
72 |
+
$this->couriers = $options['couriers'];
|
73 |
+
}
|
74 |
+
|
75 |
+
// View Order Page
|
76 |
+
$this->plugin = $plugin;
|
77 |
+
} else {
|
78 |
+
$this->plugin = '';
|
79 |
+
}
|
80 |
+
|
81 |
+
if (isset($options['use_track_button'])) {
|
82 |
+
$this->use_track_button = $options['use_track_button'];
|
83 |
+
} else {
|
84 |
+
$this->use_track_button = false;
|
85 |
+
}
|
86 |
+
|
87 |
+
if (isset($options['custom_domain'])) {
|
88 |
+
$this->custom_domain = $options['custom_domain'];
|
89 |
+
} else {
|
90 |
+
$this->custom_domain = '';
|
91 |
+
}
|
92 |
+
|
93 |
+
add_action('woocommerce_view_order', array(&$this, 'display_tracking_info'));
|
94 |
+
add_action('woocommerce_email_before_order_table', array(&$this, 'email_display'));
|
95 |
+
|
96 |
+
}
|
97 |
+
|
98 |
+
// user profile api key
|
99 |
+
add_action('show_user_profile', array($this, 'add_api_key_field'));
|
100 |
+
add_action('edit_user_profile', array($this, 'add_api_key_field'));
|
101 |
+
add_action('personal_options_update', array($this, 'generate_api_key'));
|
102 |
+
add_action('edit_user_profile_update', array($this, 'generate_api_key'));
|
103 |
+
|
104 |
+
register_activation_hook(__FILE__, array($this, 'install'));
|
105 |
+
}
|
106 |
+
|
107 |
+
public function install()
|
108 |
+
{
|
109 |
+
global $wp_roles;
|
110 |
+
|
111 |
+
if (class_exists('WP_Roles')) {
|
112 |
+
if (!isset($wp_roles)) {
|
113 |
+
$wp_roles = new WP_Roles();
|
114 |
+
}
|
115 |
+
}
|
116 |
+
|
117 |
+
if (is_object($wp_roles)) {
|
118 |
+
$wp_roles->add_cap('administrator', 'manage_aftership');
|
119 |
+
}
|
120 |
+
}
|
121 |
+
|
122 |
+
private function includes()
|
123 |
+
{
|
124 |
+
include_once('aftership-fields.php');
|
125 |
+
$this->aftership_fields = $aftership_fields;
|
126 |
+
|
127 |
+
include_once('class-aftership-api.php');
|
128 |
+
include_once('class-aftership-settings.php');
|
129 |
+
}
|
130 |
+
|
131 |
+
/**
|
132 |
+
* Localisation
|
133 |
+
*/
|
134 |
+
public function load_plugin_textdomain()
|
135 |
+
{
|
136 |
+
load_plugin_textdomain('aftership', false, dirname(plugin_basename(__FILE__)) . '/languages/');
|
137 |
+
}
|
138 |
+
|
139 |
+
public function admin_styles()
|
140 |
+
{
|
141 |
+
wp_enqueue_style('aftership_styles_chosen', plugins_url(basename(dirname(__FILE__))) . '/assets/plugin/chosen/chosen.min.css');
|
142 |
+
wp_enqueue_style('aftership_styles', plugins_url(basename(dirname(__FILE__))) . '/assets/css/admin.css');
|
143 |
+
}
|
144 |
+
|
145 |
+
public function library_scripts()
|
146 |
+
{
|
147 |
+
wp_enqueue_script('aftership_styles_chosen_jquery', plugins_url(basename(dirname(__FILE__))) . '/assets/plugin/chosen/chosen.jquery.min.js');
|
148 |
+
wp_enqueue_script('aftership_styles_chosen_proto', plugins_url(basename(dirname(__FILE__))) . '/assets/plugin/chosen/chosen.proto.min.js');
|
149 |
+
wp_enqueue_script('aftership_script_util', plugins_url(basename(dirname(__FILE__))) . '/assets/js/util.js');
|
150 |
+
wp_enqueue_script('aftership_script_couriers', plugins_url(basename(dirname(__FILE__))) . '/assets/js/couriers.js');
|
151 |
+
wp_enqueue_script('aftership_script_admin', plugins_url(basename(dirname(__FILE__))) . '/assets/js/admin.js');
|
152 |
+
}
|
153 |
+
public function include_footer_script()
|
154 |
+
{
|
155 |
+
wp_enqueue_script('aftership_script_footer', plugins_url(basename(dirname(__FILE__))) . '/assets/js/footer.js', true);
|
156 |
+
}
|
157 |
+
|
158 |
+
/**
|
159 |
+
* Add the meta box for shipment info on the order page
|
160 |
+
*
|
161 |
+
* @access public
|
162 |
+
*/
|
163 |
+
public function add_meta_box()
|
164 |
+
{
|
165 |
+
add_meta_box('woocommerce-aftership', __('AfterShip', 'wc_aftership'), array(&$this, 'meta_box'), 'shop_order', 'side', 'high');
|
166 |
+
}
|
167 |
+
|
168 |
+
/**
|
169 |
+
* Show the meta box for shipment info on the order page
|
170 |
+
*
|
171 |
+
* @access public
|
172 |
+
*/
|
173 |
+
public function meta_box()
|
174 |
+
{
|
175 |
+
|
176 |
+
// just draw the layout, no data
|
177 |
+
global $post;
|
178 |
+
|
179 |
+
$selected_provider = get_post_meta($post->ID, '_aftership_tracking_provider', true);
|
180 |
+
|
181 |
+
echo '<div id="aftership_wrapper">';
|
182 |
+
|
183 |
+
echo '<p class="form-field"><label for="aftership_tracking_provider">' . __('Carrier:', 'wc_aftership') . '</label><br/><select id="aftership_tracking_provider" name="aftership_tracking_provider" class="chosen_select" style="width:100%">';
|
184 |
+
if ($selected_provider == '') {
|
185 |
+
$selected_text = 'selected="selected"';
|
186 |
+
} else {
|
187 |
+
$selected_text = '';
|
188 |
+
}
|
189 |
+
echo '<option disabled ' . $selected_text . ' value="">Please Select</option>';
|
190 |
+
echo '</select>';
|
191 |
+
echo '<br><a href="options-general.php?page=aftership-setting-admin">Update carrier list</a>';
|
192 |
+
echo '<input type="hidden" id="aftership_tracking_provider_hidden" value="' . $selected_provider . '"/>';
|
193 |
+
echo '<input type="hidden" id="aftership_couriers_selected" value="' . $this->couriers . '"/>';
|
194 |
+
|
195 |
+
foreach ($this->aftership_fields as $field) {
|
196 |
+
if ($field['type'] == 'date') {
|
197 |
+
woocommerce_wp_text_input(array(
|
198 |
+
'id' => $field['id'],
|
199 |
+
'label' => __($field['label'], 'wc_aftership'),
|
200 |
+
'placeholder' => $field['placeholder'],
|
201 |
+
'description' => $field['description'],
|
202 |
+
'class' => $field['class'],
|
203 |
+
'value' => ($date = get_post_meta($post->ID, '_' . $field['id'], true)) ? date('Y-m-d', $date) : ''
|
204 |
+
));
|
205 |
+
} else {
|
206 |
+
woocommerce_wp_text_input(array(
|
207 |
+
'id' => $field['id'],
|
208 |
+
'label' => __($field['label'], 'wc_aftership'),
|
209 |
+
'placeholder' => $field['placeholder'],
|
210 |
+
'description' => $field['description'],
|
211 |
+
'class' => $field['class'],
|
212 |
+
'value' => get_post_meta($post->ID, '_' . $field['id'], true),
|
213 |
+
));
|
214 |
+
}
|
215 |
+
}
|
216 |
+
|
217 |
+
//
|
218 |
+
// woocommerce_wp_text_input(array(
|
219 |
+
// 'id' => 'aftership_tracking_provider_name',
|
220 |
+
// 'label' => __('', 'wc_aftership'),
|
221 |
+
// 'placeholder' => '',
|
222 |
+
// 'description' => '',
|
223 |
+
// 'class' => 'hidden',
|
224 |
+
// 'value' => get_post_meta($post->ID, '_aftership_tracking_provider_name', true),
|
225 |
+
// ));
|
226 |
+
//
|
227 |
+
// woocommerce_wp_text_input(array(
|
228 |
+
// 'id' => 'aftership_tracking_required_fields',
|
229 |
+
// 'label' => __('', 'wc_aftership'),
|
230 |
+
// 'placeholder' => '',
|
231 |
+
// 'description' => '',
|
232 |
+
// 'class' => 'hidden',
|
233 |
+
// 'value' => get_post_meta($post->ID, '_aftership_tracking_required_fields', true),
|
234 |
+
// ));
|
235 |
+
//
|
236 |
+
// woocommerce_wp_text_input(array(
|
237 |
+
// 'id' => 'aftership_tracking_number',
|
238 |
+
// 'label' => __('Tracking number:', 'wc_aftership'),
|
239 |
+
// 'placeholder' => '',
|
240 |
+
// 'description' => '',
|
241 |
+
// 'value' => get_post_meta($post->ID, '_aftership_tracking_number', true),
|
242 |
+
// ));
|
243 |
+
//
|
244 |
+
// woocommerce_wp_text_input(array(
|
245 |
+
// 'id' => 'aftership_tracking_shipdate',
|
246 |
+
// 'label' => __('Date shipped:', 'wc_aftership'),
|
247 |
+
// 'placeholder' => 'YYYY-MM-DD',
|
248 |
+
// 'description' => '',
|
249 |
+
// 'class' => 'date-picker-field hidden-field',
|
250 |
+
// 'value' => ($date = get_post_meta($post->ID, '_aftership_tracking_shipdate', true)) ? date('Y-m-d', $date) : ''
|
251 |
+
// ));
|
252 |
+
//
|
253 |
+
// woocommerce_wp_text_input(array(
|
254 |
+
// 'id' => 'aftership_tracking_postal',
|
255 |
+
// 'label' => __('Postal Code:', 'wc_aftership'),
|
256 |
+
// 'placeholder' => '',
|
257 |
+
// 'description' => '',
|
258 |
+
// 'class' => 'hidden-field',
|
259 |
+
// 'value' => get_post_meta($post->ID, '_aftership_tracking_postal', true),
|
260 |
+
// ));
|
261 |
+
//
|
262 |
+
// woocommerce_wp_text_input(array(
|
263 |
+
// 'id' => 'aftership_tracking_account',
|
264 |
+
// 'label' => __('Account name:', 'wc_aftership'),
|
265 |
+
// 'placeholder' => '',
|
266 |
+
// 'description' => '',
|
267 |
+
// 'class' => 'hidden-field',
|
268 |
+
// 'value' => get_post_meta($post->ID, '_aftership_tracking_account', true),
|
269 |
+
// ));
|
270 |
+
//
|
271 |
+
// woocommerce_wp_text_input(array(
|
272 |
+
// 'id' => 'aftership_tracking_key',
|
273 |
+
// 'label' => __('Tracking key:', 'wc_aftership'),
|
274 |
+
// 'placeholder' => '',
|
275 |
+
// 'description' => '',
|
276 |
+
// 'class' => 'hidden-field',
|
277 |
+
// 'value' => get_post_meta($post->ID, '_aftership_tracking_key', true),
|
278 |
+
// ));
|
279 |
+
//
|
280 |
+
// woocommerce_wp_text_input(array(
|
281 |
+
// 'id' => 'aftership_tracking_destination_country',
|
282 |
+
// 'label' => __('Destination Country:', 'wc_aftership'),
|
283 |
+
// 'placeholder' => '',
|
284 |
+
// 'description' => '',
|
285 |
+
// 'class' => 'hidden-field',
|
286 |
+
// 'value' => get_post_meta($post->ID, '_aftership_tracking_destination_country', true),
|
287 |
+
// ));
|
288 |
+
echo '</div>';
|
289 |
+
}
|
290 |
+
|
291 |
+
/**
|
292 |
+
* Order Downloads Save
|
293 |
+
*
|
294 |
+
* Function for processing and storing all order downloads.
|
295 |
+
*/
|
296 |
+
public function save_meta_box($post_id, $post)
|
297 |
+
{
|
298 |
+
if (isset($_POST['aftership_tracking_number'])) {
|
299 |
+
//
|
300 |
+
// // Download data
|
301 |
+
$tracking_provider = wc_clean($_POST['aftership_tracking_provider']);
|
302 |
+
// $tracking_number = wc_clean($_POST['aftership_tracking_number']);
|
303 |
+
// $tracking_provider_name = wc_clean($_POST['aftership_tracking_provider_name']);
|
304 |
+
// $tracking_required_fields = wc_clean($_POST['aftership_tracking_required_fields']);
|
305 |
+
// $shipdate = wc_clean(strtotime($_POST['aftership_tracking_shipdate']));
|
306 |
+
// $postal = wc_clean($_POST['aftership_tracking_postal']);
|
307 |
+
// $account = wc_clean($_POST['aftership_tracking_account']);
|
308 |
+
// $tracking_key = wc_clean($_POST['aftership_tracking_key']);
|
309 |
+
// $tracking_destination_country = wc_clean($_POST['aftership_tracking_destination_country']);
|
310 |
+
//
|
311 |
+
// // Update order data
|
312 |
+
update_post_meta($post_id, '_aftership_tracking_provider', $tracking_provider);
|
313 |
+
// update_post_meta($post_id, '_aftership_tracking_number', $tracking_number);
|
314 |
+
// update_post_meta($post_id, '_aftership_tracking_provider_name', $tracking_provider_name);
|
315 |
+
// update_post_meta($post_id, '_aftership_tracking_required_fields', $tracking_required_fields);
|
316 |
+
// update_post_meta($post_id, '_aftership_tracking_shipdate', $shipdate);
|
317 |
+
// update_post_meta($post_id, '_aftership_tracking_postal', $postal);
|
318 |
+
// update_post_meta($post_id, '_aftership_tracking_account', $account);
|
319 |
+
// update_post_meta($post_id, '_aftership_tracking_key', $tracking_key);
|
320 |
+
// update_post_meta($post_id, '_aftership_tracking_destination_country', $tracking_destination_country);
|
321 |
+
|
322 |
+
|
323 |
+
foreach ($this->aftership_fields as $field) {
|
324 |
+
if ($field['type'] == 'date') {
|
325 |
+
update_post_meta($post_id, '_' . $field['id'], wc_clean(strtotime($_POST[$field['id']])));
|
326 |
+
} else {
|
327 |
+
update_post_meta($post_id, '_' . $field['id'], wc_clean($_POST[$field['id']]));
|
328 |
+
}
|
329 |
+
}
|
330 |
+
}
|
331 |
+
}
|
332 |
+
|
333 |
+
/**
|
334 |
+
* Display the API key info for a user
|
335 |
+
*
|
336 |
+
* @since 2.1
|
337 |
+
* @param WP_User $user
|
338 |
+
*/
|
339 |
+
public function add_api_key_field($user)
|
340 |
+
{
|
341 |
+
|
342 |
+
if (!current_user_can('manage_aftership'))
|
343 |
+
return;
|
344 |
+
|
345 |
+
if (current_user_can('edit_user', $user->ID)) {
|
346 |
+
?>
|
347 |
+
<h3>AfterShip</h3>
|
348 |
+
<table class="form-table">
|
349 |
+
<tbody>
|
350 |
+
<tr>
|
351 |
+
<th><label
|
352 |
+
for="aftership_wp_api_key"><?php _e('AfterShip\'s WordPress API Key', 'aftership'); ?></label>
|
353 |
+
</th>
|
354 |
+
<td>
|
355 |
+
<?php if (empty($user->aftership_wp_api_key)) : ?>
|
356 |
+
<input name="aftership_wp_generate_api_key" type="checkbox"
|
357 |
+
id="aftership_wp_generate_api_key" value="0"/>
|
358 |
+
<span class="description"><?php _e('Generate API Key', 'aftership'); ?></span>
|
359 |
+
<?php else : ?>
|
360 |
+
<code id="aftership_wp_api_key"><?php echo $user->aftership_wp_api_key ?></code>
|
361 |
+
<br/>
|
362 |
+
<input name="aftership_wp_generate_api_key" type="checkbox"
|
363 |
+
id="aftership_wp_generate_api_key" value="0"/>
|
364 |
+
<span class="description"><?php _e('Revoke API Key', 'aftership'); ?></span>
|
365 |
+
<?php endif; ?>
|
366 |
+
</td>
|
367 |
+
</tr>
|
368 |
+
</tbody>
|
369 |
+
</table>
|
370 |
+
<?php
|
371 |
+
}
|
372 |
+
}
|
373 |
+
|
374 |
+
/**
|
375 |
+
* Generate and save (or delete) the API keys for a user
|
376 |
+
*
|
377 |
+
* @since 2.1
|
378 |
+
* @param int $user_id
|
379 |
+
*/
|
380 |
+
public function generate_api_key($user_id)
|
381 |
+
{
|
382 |
+
|
383 |
+
if (current_user_can('edit_user', $user_id)) {
|
384 |
+
|
385 |
+
$user = get_userdata($user_id);
|
386 |
+
|
387 |
+
// creating/deleting key
|
388 |
+
if (isset($_POST['aftership_wp_generate_api_key'])) {
|
389 |
+
|
390 |
+
// consumer key
|
391 |
+
if (empty($user->aftership_wp_api_key)) {
|
392 |
+
|
393 |
+
$api_key = 'ck_' . hash('md5', $user->user_login . date('U') . mt_rand());
|
394 |
+
|
395 |
+
update_user_meta($user_id, 'aftership_wp_api_key', $api_key);
|
396 |
+
|
397 |
+
} else {
|
398 |
+
|
399 |
+
delete_user_meta($user_id, 'aftership_wp_api_key');
|
400 |
+
}
|
401 |
+
|
402 |
+
}
|
403 |
+
}
|
404 |
+
}
|
405 |
+
|
406 |
+
/**
|
407 |
+
* Display Shipment info in the frontend (order view/tracking page).
|
408 |
+
*
|
409 |
+
* @access public
|
410 |
+
*/
|
411 |
+
function display_tracking_info($order_id, $for_email = false)
|
412 |
+
{
|
413 |
+
if ($this->plugin == 'aftership') {
|
414 |
+
$this->display_order_aftership($order_id, $for_email);
|
415 |
+
} else if ($this->plugin == 'wc-shipment-tracking') { //$49
|
416 |
+
$this->display_order_wc_shipment_tracking($order_id, $for_email);
|
417 |
+
}
|
418 |
+
}
|
419 |
+
|
420 |
+
private function display_order_aftership($order_id, $for_email)
|
421 |
+
{
|
422 |
+
|
423 |
+
// print_r($this->aftership_fields);
|
424 |
+
$values = array();
|
425 |
+
foreach ($this->aftership_fields as $field) {
|
426 |
+
$values[$field['id']] = get_post_meta($order_id, '_' . $field['id'], true);
|
427 |
+
if ($field['type'] == 'date' && $values[$field['id']]) {
|
428 |
+
$values[$field['id']] = date_i18n(__('l jS F Y', 'wc_shipment_tracking'), $values[$field['id']]);
|
429 |
+
}
|
430 |
+
}
|
431 |
+
$values['aftership_tracking_provider'] = get_post_meta($order_id, '_aftership_tracking_provider', true);
|
432 |
+
|
433 |
+
if (!$values['aftership_tracking_provider'])
|
434 |
+
return;
|
435 |
+
|
436 |
+
if (!$values['aftership_tracking_number'])
|
437 |
+
return;
|
438 |
+
|
439 |
+
|
440 |
+
$options = get_option('aftership_option_name');
|
441 |
+
if (array_key_exists('track_message_1', $options) && array_key_exists('track_message_2', $options)) {
|
442 |
+
$track_message_1 = $options['track_message_1'];
|
443 |
+
$track_message_2 = $options['track_message_2'];
|
444 |
+
} else {
|
445 |
+
$track_message_1 = 'Your order was shipped via ';
|
446 |
+
$track_message_2 = 'Tracking number is ';
|
447 |
+
}
|
448 |
+
|
449 |
+
$required_fields_values = array();
|
450 |
+
$provider_required_fields = explode(",", $values['aftership_tracking_required_fields']);
|
451 |
+
|
452 |
+
for ($i = 0 ; $i < count($provider_required_fields); $i++) {
|
453 |
+
$field = $provider_required_fields[$i];
|
454 |
+
foreach ($this->aftership_fields as $aftership_field) {
|
455 |
+
if (array_key_exists('key', $aftership_field) && $field == $aftership_field['key']) {
|
456 |
+
array_unshift($required_fields_values, $values[$aftership_field['id']]);
|
457 |
+
}
|
458 |
+
}
|
459 |
+
}
|
460 |
+
|
461 |
+
if (count($required_fields_values)) {
|
462 |
+
$required_fields_msg = ' (' . join(', ', $required_fields_values) . ')';
|
463 |
+
} else {
|
464 |
+
$required_fields_msg = '';
|
465 |
+
}
|
466 |
+
|
467 |
+
|
468 |
+
echo $track_message_1 . $values['aftership_tracking_provider_name'] . '<br/>' . $track_message_2 . $values['aftership_tracking_number'] . $required_fields_msg;
|
469 |
+
|
470 |
+
if (!$for_email && $this->use_track_button) {
|
471 |
+
$this->display_track_button($values['aftership_tracking_provider'], $values['aftership_tracking_number'], $required_fields_values);
|
472 |
+
}
|
473 |
+
|
474 |
+
//-------------------------------------------------------------------------------------
|
475 |
+
/*
|
476 |
+
$tracking_provider = get_post_meta($order_id, '_aftership_tracking_provider', true);
|
477 |
+
$tracking_number = get_post_meta($order_id, '_aftership_tracking_number', true);
|
478 |
+
$tracking_provider_name = get_post_meta($order_id, '_aftership_tracking_provider_name', true);
|
479 |
+
$tracking_required_fields = get_post_meta($order_id, '_aftership_tracking_required_fields', true);
|
480 |
+
$date_shipped = get_post_meta($order_id, '_aftership_tracking_shipdate', true);
|
481 |
+
$postcode = get_post_meta($order_id, '_aftership_tracking_postal', true);
|
482 |
+
$account = get_post_meta($order_id, '_aftership_tracking_account', true);
|
483 |
+
|
484 |
+
if (!$tracking_provider)
|
485 |
+
return;
|
486 |
+
|
487 |
+
if (!$tracking_number)
|
488 |
+
return;
|
489 |
+
|
490 |
+
$provider_name = $tracking_provider_name;
|
491 |
+
$provider_required_fields = explode(",", $tracking_required_fields);
|
492 |
+
|
493 |
+
$date_shipped_str = '';
|
494 |
+
$postcode_str = '';
|
495 |
+
$account_str = '';
|
496 |
+
|
497 |
+
foreach ($provider_required_fields as $field) {
|
498 |
+
if ($field == 'tracking_ship_date') {
|
499 |
+
if ($date_shipped) {
|
500 |
+
$date_shipped_str = ' ' . sprintf(__('on %s', 'wc_shipment_tracking'), date_i18n(__('l jS F Y', 'wc_shipment_tracking'), $date_shipped));
|
501 |
+
}
|
502 |
+
} else if ($field == 'tracking_postal_code') {
|
503 |
+
if ($postcode) {
|
504 |
+
$postcode_str = ' ' . sprintf('The postal code is %s.', $postcode);
|
505 |
+
}
|
506 |
+
} else if ($field == 'tracking_account_number') {
|
507 |
+
if ($account) {
|
508 |
+
$account_str = ' ' . sprintf('The account is %s.', $account);
|
509 |
+
}
|
510 |
+
}
|
511 |
+
}
|
512 |
+
|
513 |
+
$provider_name = ' ' . __('via', 'wc_shipment_tracking') . ' <strong>' . $provider_name . '</strong>';
|
514 |
+
|
515 |
+
echo wpautop(sprintf(__('Your order was shipped%s%s. Tracking number is %s.%s%s', 'wc_shipment_tracking'), $date_shipped_str, $provider_name, $tracking_number, $postcode_str, $account_str));
|
516 |
+
|
517 |
+
if (!$for_email && $this->use_track_button) {
|
518 |
+
$this->display_track_button($tracking_provider, $tracking_number);
|
519 |
+
}
|
520 |
+
*/
|
521 |
+
|
522 |
+
}
|
523 |
+
|
524 |
+
private function display_order_wc_shipment_tracking($order_id, $for_email)
|
525 |
+
{
|
526 |
+
if ($for_email || !$this->use_track_button) {
|
527 |
+
return;
|
528 |
+
}
|
529 |
+
|
530 |
+
$tracking = get_post_meta($order_id, '_tracking_number', true);
|
531 |
+
$sharp = strpos($tracking, '#');
|
532 |
+
$colon = strpos($tracking, ':');
|
533 |
+
$required_fields = array();
|
534 |
+
if ($sharp && $colon && $sharp >= $colon) {
|
535 |
+
return;
|
536 |
+
} else if (!$sharp && $colon) {
|
537 |
+
return;
|
538 |
+
} else if ($sharp) {
|
539 |
+
$tracking_provider = substr($tracking, 0, $sharp);
|
540 |
+
if ($colon) {
|
541 |
+
$tracking_number = substr($tracking, $sharp + 1, $colon - $sharp - 1);
|
542 |
+
$temp = substr($tracking, $sharp + 1, strlen($tracking));
|
543 |
+
$required_fields = explode(':', $temp);
|
544 |
+
} else {
|
545 |
+
$tracking_number = substr($tracking, $sharp + 1, strlen($tracking));
|
546 |
+
}
|
547 |
+
} else {
|
548 |
+
$tracking_provider = '';
|
549 |
+
$tracking_number = $tracking;
|
550 |
+
}
|
551 |
+
if ($tracking_number) {
|
552 |
+
$this->display_track_button($tracking_provider, $tracking_number, $required_fields);
|
553 |
+
}
|
554 |
+
}
|
555 |
+
|
556 |
+
/**
|
557 |
+
* Display shipment info in customer emails.
|
558 |
+
*
|
559 |
+
* @access public
|
560 |
+
* @return void
|
561 |
+
*/
|
562 |
+
function email_display($order)
|
563 |
+
{
|
564 |
+
$this->display_tracking_info(get_order_id($order), true);
|
565 |
+
}
|
566 |
+
|
567 |
+
private function display_track_button($tracking_provider, $tracking_number, $required_fields_values)
|
568 |
+
{
|
569 |
+
|
570 |
+
$js = '(function(e,t,n){var r,i=e.getElementsByTagName(t)[0];if(e.getElementById(n))return;r=e.createElement(t);r.id=n;r.src="//apps.aftership.com/all.js";i.parentNode.insertBefore(r,i)})(document,"script","aftership-jssdk")';
|
571 |
+
if (function_exists('wc_enqueue_js')) {
|
572 |
+
wc_enqueue_js($js);
|
573 |
+
} else {
|
574 |
+
global $woocommerce;
|
575 |
+
$woocommerce->add_inline_js($js);
|
576 |
+
}
|
577 |
+
|
578 |
+
if (count($required_fields_values)) {
|
579 |
+
$tracking_number = $tracking_number . ':' . join(':', $required_fields_values);
|
580 |
+
}
|
581 |
+
|
582 |
+
$temp_url = '';
|
583 |
+
$temp_slug = ' data-slug="' . $tracking_provider . '"';
|
584 |
+
if($this->custom_domain != '') {
|
585 |
+
$temp_url = '" data-domain="' . $this->custom_domain;
|
586 |
+
$temp_slug = '';
|
587 |
+
}
|
588 |
+
|
589 |
+
$track_button = '<div id="as-root"></div><div class="as-track-button"' . $temp_slug . ' data-tracking-number="' . $tracking_number . $temp_url .'" data-support="true" data-width="400" data-size="normal" data-hide-tracking-number="true"></div>';
|
590 |
+
echo wpautop(sprintf('%s', $track_button));
|
591 |
+
echo "<br><br>";
|
592 |
+
}
|
593 |
+
}
|
594 |
+
|
595 |
+
if (!function_exists('getAfterShipInstance')) {
|
596 |
+
function getAfterShipInstance()
|
597 |
+
{
|
598 |
+
return AfterShip::Instance();
|
599 |
+
}
|
600 |
+
}
|
601 |
+
}
|
602 |
+
|
603 |
+
/**
|
604 |
+
* Register this class globally
|
605 |
+
*/
|
606 |
+
$GLOBALS['aftership'] = getAfterShipInstance();
|
607 |
+
|
608 |
+
}
|
trunk/api/class-aftership-api-authentication.php
ADDED
@@ -0,0 +1,129 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
<?php
|
2 |
+
/**
|
3 |
+
* AfterShip API Authentication Class
|
4 |
+
*
|
5 |
+
* @author AfterShip
|
6 |
+
* @category API
|
7 |
+
* @package AfterShip/API
|
8 |
+
* @since 1
|
9 |
+
*/
|
10 |
+
|
11 |
+
if (!defined('ABSPATH')) exit; // Exit if accessed directly
|
12 |
+
|
13 |
+
|
14 |
+
if (!function_exists('getallheaders')) {
|
15 |
+
function getallheaders()
|
16 |
+
{
|
17 |
+
$headers = '';
|
18 |
+
foreach ($_SERVER as $name => $value) {
|
19 |
+
if (substr($name, 0, 5) == 'HTTP_') {
|
20 |
+
$headers[str_replace(' ', '-', ucwords(strtolower(str_replace('_', ' ', substr($name, 5)))))] = $value;
|
21 |
+
}
|
22 |
+
}
|
23 |
+
return $headers;
|
24 |
+
}
|
25 |
+
}
|
26 |
+
|
27 |
+
class AfterShip_API_Authentication
|
28 |
+
{
|
29 |
+
|
30 |
+
/**
|
31 |
+
* Setup class
|
32 |
+
*
|
33 |
+
* @since 2.1
|
34 |
+
* @return WC_API_Authentication
|
35 |
+
*/
|
36 |
+
public function __construct()
|
37 |
+
{
|
38 |
+
|
39 |
+
// to disable authentication, hook into this filter at a later priority and return a valid WP_User
|
40 |
+
add_filter('aftership_api_check_authentication', array($this, 'authenticate'), 0);
|
41 |
+
}
|
42 |
+
|
43 |
+
/**
|
44 |
+
* Authenticate the request. The authentication method varies based on whether the request was made over SSL or not.
|
45 |
+
*
|
46 |
+
* @since 2.1
|
47 |
+
* @param WP_User $user
|
48 |
+
* @return null|WP_Error|WP_User
|
49 |
+
*/
|
50 |
+
public function authenticate($user)
|
51 |
+
{
|
52 |
+
|
53 |
+
// allow access to the index by default
|
54 |
+
if ('/' === getAfterShipInstance()->api->server->path)
|
55 |
+
return new WP_User(0);
|
56 |
+
|
57 |
+
try {
|
58 |
+
$user = $this->perform_authentication();
|
59 |
+
|
60 |
+
} catch (Exception $e) {
|
61 |
+
|
62 |
+
$user = new WP_Error('aftership_api_authentication_error', $e->getMessage(), array('status' => $e->getCode()));
|
63 |
+
}
|
64 |
+
|
65 |
+
return $user;
|
66 |
+
}
|
67 |
+
|
68 |
+
private function perform_authentication()
|
69 |
+
{
|
70 |
+
//$params = getAfterShipInstance()->api->server->params['GET'];
|
71 |
+
|
72 |
+
$headers = getallheaders();
|
73 |
+
$headers = json_decode(json_encode($headers), true);
|
74 |
+
|
75 |
+
// it dues to different kind of server configuration
|
76 |
+
$key = 'AFTERSHIP_WP_KEY';
|
77 |
+
$key1 = str_replace(' ', '-', ucwords(strtolower(str_replace('_', ' ', $key))));
|
78 |
+
$key2 = 'AFTERSHIP-WP-KEY';
|
79 |
+
$qskey = $_GET['key'];
|
80 |
+
|
81 |
+
// get aftership wp key
|
82 |
+
if (!empty($headers[$key])) {
|
83 |
+
$api_key = $headers[$key];
|
84 |
+
} else if (!empty($headers[$key1])){
|
85 |
+
$api_key = $headers[$key1];
|
86 |
+
} else if (!empty($headers[$key2])){
|
87 |
+
$api_key = $headers[$key2];
|
88 |
+
} else if (!empty($qskey)) {
|
89 |
+
$api_key = $qskey;
|
90 |
+
} else {
|
91 |
+
throw new Exception(__('AfterShip\'s WordPress Key is missing', 'aftership'), 404);
|
92 |
+
}
|
93 |
+
|
94 |
+
$user = $this->get_user_by_api_key($api_key);
|
95 |
+
|
96 |
+
return $user;
|
97 |
+
|
98 |
+
}
|
99 |
+
|
100 |
+
/**
|
101 |
+
* Return the user for the given consumer key
|
102 |
+
*
|
103 |
+
* @since 2.1
|
104 |
+
* @param string $consumer_key
|
105 |
+
* @return WP_User
|
106 |
+
* @throws Exception
|
107 |
+
*/
|
108 |
+
private function get_user_by_api_key($api_key)
|
109 |
+
{
|
110 |
+
|
111 |
+
$user_query = new WP_User_Query(
|
112 |
+
array(
|
113 |
+
//'meta_key' => 'woocommerce_api_consumer_key',
|
114 |
+
'meta_key' => 'aftership_wp_api_key',
|
115 |
+
'meta_value' => $api_key,
|
116 |
+
)
|
117 |
+
);
|
118 |
+
|
119 |
+
$users = $user_query->get_results();
|
120 |
+
|
121 |
+
if (empty($users[0]))
|
122 |
+
throw new Exception(__('AfterShip\'s WordPress API Key is invalid', 'aftership'), 401);
|
123 |
+
|
124 |
+
return $users[0];
|
125 |
+
|
126 |
+
|
127 |
+
}
|
128 |
+
|
129 |
+
}
|
trunk/api/class-aftership-api-json-handler.php
ADDED
@@ -0,0 +1,77 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
<?php
|
2 |
+
/**
|
3 |
+
* AfterShip API
|
4 |
+
*
|
5 |
+
* Handles parsing JSON request bodies and generating JSON responses
|
6 |
+
*
|
7 |
+
* @author AfterShip
|
8 |
+
* @category API
|
9 |
+
* @package AfterShip/API
|
10 |
+
* @since 1.0
|
11 |
+
*/
|
12 |
+
|
13 |
+
if (!defined('ABSPATH')) exit; // Exit if accessed directly
|
14 |
+
|
15 |
+
class AfterShip_API_JSON_Handler implements AfterShip_API_Handler
|
16 |
+
{
|
17 |
+
|
18 |
+
/**
|
19 |
+
* Get the content type for the response
|
20 |
+
*
|
21 |
+
* @since 2.1
|
22 |
+
* @return string
|
23 |
+
*/
|
24 |
+
public function get_content_type()
|
25 |
+
{
|
26 |
+
|
27 |
+
return 'application/json; charset=' . get_option('blog_charset');
|
28 |
+
}
|
29 |
+
|
30 |
+
/**
|
31 |
+
* Parse the raw request body entity
|
32 |
+
*
|
33 |
+
* @since 2.1
|
34 |
+
* @param string $body the raw request body
|
35 |
+
* @return array|mixed
|
36 |
+
*/
|
37 |
+
public function parse_body($body)
|
38 |
+
{
|
39 |
+
|
40 |
+
return json_decode($body, true);
|
41 |
+
}
|
42 |
+
|
43 |
+
/**
|
44 |
+
* Generate a JSON response given an array of data
|
45 |
+
*
|
46 |
+
* @since 2.1
|
47 |
+
* @param array $data the response data
|
48 |
+
* @return string
|
49 |
+
*/
|
50 |
+
public function generate_response($data)
|
51 |
+
{
|
52 |
+
|
53 |
+
if (isset($_GET['_jsonp'])) {
|
54 |
+
|
55 |
+
// JSONP enabled by default
|
56 |
+
if (!apply_filters('aftership_api_jsonp_enabled', true)) {
|
57 |
+
|
58 |
+
WC()->api->server->send_status(400);
|
59 |
+
|
60 |
+
$data = array(array('code' => 'aftership_api_jsonp_disabled', 'message' => __('JSONP support is disabled on this site', 'aftership')));
|
61 |
+
}
|
62 |
+
|
63 |
+
// Check for invalid characters (only alphanumeric allowed)
|
64 |
+
if (preg_match('/\W/', $_GET['_jsonp'])) {
|
65 |
+
|
66 |
+
WC()->api->server->send_status(400);
|
67 |
+
|
68 |
+
$data = array(array('code' => 'aftership_api_jsonp_callback_invalid', __('The JSONP callback function is invalid', 'aftership')));
|
69 |
+
}
|
70 |
+
|
71 |
+
return $_GET['_jsonp'] . '(' . json_encode($data) . ')';
|
72 |
+
}
|
73 |
+
|
74 |
+
return json_encode($data);
|
75 |
+
}
|
76 |
+
|
77 |
+
}
|
trunk/api/class-aftership-api-orders.php
ADDED
@@ -0,0 +1,505 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
<?php
|
2 |
+
/**
|
3 |
+
* AfterShip API Orders Class
|
4 |
+
*
|
5 |
+
* Handles requests to the /orders endpoint
|
6 |
+
*
|
7 |
+
* @author AfterShip
|
8 |
+
* @category API
|
9 |
+
* @package AfterShip/API
|
10 |
+
* @since 1.0
|
11 |
+
*/
|
12 |
+
|
13 |
+
if (!defined('ABSPATH')) exit; // Exit if accessed directly
|
14 |
+
|
15 |
+
class AfterShip_API_Orders extends AfterShip_API_Resource
|
16 |
+
{
|
17 |
+
|
18 |
+
/** @var string $base the route base */
|
19 |
+
protected $base = '/orders';
|
20 |
+
|
21 |
+
/**
|
22 |
+
* Register the routes for this class
|
23 |
+
*
|
24 |
+
* GET /orders
|
25 |
+
* GET /orders/count
|
26 |
+
* GET|PUT /orders/<id>
|
27 |
+
* GET /orders/<id>/notes
|
28 |
+
*
|
29 |
+
* @since 2.1
|
30 |
+
* @param array $routes
|
31 |
+
* @return array
|
32 |
+
*/
|
33 |
+
public function register_routes($routes)
|
34 |
+
{
|
35 |
+
|
36 |
+
# GET /orders
|
37 |
+
$routes[$this->base] = array(
|
38 |
+
array(array($this, 'get_orders'), AfterShip_API_Server::READABLE),
|
39 |
+
);
|
40 |
+
|
41 |
+
# GET /orders/count
|
42 |
+
$routes[$this->base . '/count'] = array(
|
43 |
+
array(array($this, 'get_orders_count'), AfterShip_API_Server::READABLE),
|
44 |
+
);
|
45 |
+
|
46 |
+
# GET|PUT /orders/<id>
|
47 |
+
$routes[$this->base . '/(?P<id>\d+)'] = array(
|
48 |
+
array(array($this, 'get_order'), AfterShip_API_Server::READABLE),
|
49 |
+
array(array($this, 'edit_order'), AfterShip_API_Server::EDITABLE | AfterShip_API_Server::ACCEPT_DATA),
|
50 |
+
);
|
51 |
+
|
52 |
+
# GET /orders/<id>/notes
|
53 |
+
$routes[$this->base . '/(?P<id>\d+)/notes'] = array(
|
54 |
+
array(array($this, 'get_order_notes'), AfterShip_API_Server::READABLE),
|
55 |
+
);
|
56 |
+
|
57 |
+
# GET /orders/ping
|
58 |
+
$routes[$this->base . '/ping'] = array(
|
59 |
+
array(array($this, 'ping'), AfterShip_API_Server::READABLE),
|
60 |
+
);
|
61 |
+
|
62 |
+
return $routes;
|
63 |
+
}
|
64 |
+
|
65 |
+
/**
|
66 |
+
* Get all orders
|
67 |
+
*
|
68 |
+
* @since 2.1
|
69 |
+
* @param string $fields
|
70 |
+
* @param array $filter
|
71 |
+
* @param string $status
|
72 |
+
* @param int $page
|
73 |
+
* @return array
|
74 |
+
*/
|
75 |
+
public function get_orders($fields = null, $filter = array(), $status = null, $page = 1)
|
76 |
+
{
|
77 |
+
|
78 |
+
if (!empty($status))
|
79 |
+
$filter['status'] = $status;
|
80 |
+
|
81 |
+
$filter['page'] = $page;
|
82 |
+
|
83 |
+
$query = $this->query_orders($filter);
|
84 |
+
|
85 |
+
$orders = array();
|
86 |
+
|
87 |
+
foreach ($query->posts as $order_id) {
|
88 |
+
|
89 |
+
if (!$this->is_readable($order_id))
|
90 |
+
continue;
|
91 |
+
|
92 |
+
$orders[] = current($this->get_order($order_id, $fields));
|
93 |
+
}
|
94 |
+
|
95 |
+
$this->server->add_pagination_headers($query);
|
96 |
+
|
97 |
+
return array('orders' => $orders);
|
98 |
+
}
|
99 |
+
|
100 |
+
|
101 |
+
/**
|
102 |
+
* Get the order for the given ID
|
103 |
+
*
|
104 |
+
* @since 2.1
|
105 |
+
* @param int $id the order ID
|
106 |
+
* @param array $fields
|
107 |
+
* @return array
|
108 |
+
*/
|
109 |
+
public function get_order($id, $fields = null)
|
110 |
+
{
|
111 |
+
|
112 |
+
// ensure order ID is valid & user has permission to read
|
113 |
+
$id = $this->validate_request($id, 'shop_order', 'read');
|
114 |
+
|
115 |
+
if (is_wp_error($id))
|
116 |
+
return $id;
|
117 |
+
|
118 |
+
$order = new WC_Order($id);
|
119 |
+
|
120 |
+
$order_post = get_post($id);
|
121 |
+
|
122 |
+
$order_data = array(
|
123 |
+
'id' => get_order_id($order),
|
124 |
+
'order_number' => $order->get_order_number(),
|
125 |
+
'created_at' => $this->server->format_datetime($order_post->post_date_gmt),
|
126 |
+
'updated_at' => $this->server->format_datetime($order_post->post_modified_gmt),
|
127 |
+
// 'completed_at' => $this->server->format_datetime($order->completed_date, true),
|
128 |
+
// 'status' => $order->status,
|
129 |
+
// 'currency' => $order->order_currency,
|
130 |
+
// 'total' => wc_format_decimal($order->get_total(), 2),
|
131 |
+
// 'subtotal' => wc_format_decimal($this->get_order_subtotal($order), 2),
|
132 |
+
// 'total_line_items_quantity' => $order->get_item_count(),
|
133 |
+
// 'total_tax' => wc_format_decimal($order->get_total_tax(), 2),
|
134 |
+
// 'total_shipping' => wc_format_decimal($order->get_total_shipping(), 2),
|
135 |
+
// 'cart_tax' => wc_format_decimal($order->get_cart_tax(), 2),
|
136 |
+
// 'shipping_tax' => wc_format_decimal($order->get_shipping_tax(), 2),
|
137 |
+
// 'total_discount' => wc_format_decimal($order->get_total_discount(), 2),
|
138 |
+
// 'cart_discount' => wc_format_decimal($order->get_cart_discount(), 2),
|
139 |
+
// 'order_discount' => wc_format_decimal($order->get_order_discount(), 2),
|
140 |
+
// 'shipping_methods' => $order->get_shipping_method(),
|
141 |
+
// 'payment_details' => array(
|
142 |
+
// 'method_id' => $order->payment_method,
|
143 |
+
// 'method_title' => $order->payment_method_title,
|
144 |
+
// 'paid' => isset($order->paid_date),
|
145 |
+
// ),
|
146 |
+
'billing_address' => array(
|
147 |
+
'first_name' => order_post_meta_getter($order, 'billing_first_name'),
|
148 |
+
'last_name' => order_post_meta_getter($order, 'billing_last_name'),
|
149 |
+
'company' => order_post_meta_getter($order, 'billing_company'),
|
150 |
+
'address_1' => order_post_meta_getter($order, 'billing_address_1'),
|
151 |
+
'address_2' => order_post_meta_getter($order, 'billing_address_2'),
|
152 |
+
'city' => order_post_meta_getter($order, 'billing_city'),
|
153 |
+
'state' => order_post_meta_getter($order, 'billing_state'),
|
154 |
+
'postcode' => order_post_meta_getter($order, 'billing_postcode'),
|
155 |
+
'country' => order_post_meta_getter($order,'billing_country'),
|
156 |
+
'email' => order_post_meta_getter($order,'billing_email'),
|
157 |
+
'phone' => order_post_meta_getter($order,'billing_phone'),
|
158 |
+
),
|
159 |
+
'shipping_address' => array(
|
160 |
+
'first_name' => order_post_meta_getter($order,'shipping_first_name'),
|
161 |
+
'last_name' => order_post_meta_getter($order,'shipping_last_name'),
|
162 |
+
'company' => order_post_meta_getter($order,'shipping_company'),
|
163 |
+
'address_1' => order_post_meta_getter($order,'shipping_address_1'),
|
164 |
+
'address_2' => order_post_meta_getter($order,'shipping_address_2'),
|
165 |
+
'city' => order_post_meta_getter($order,'shipping_city'),
|
166 |
+
'state' => order_post_meta_getter($order,'shipping_state'),
|
167 |
+
'postcode' => order_post_meta_getter($order,'shipping_postcode'),
|
168 |
+
'country' => order_post_meta_getter($order,'shipping_country'),
|
169 |
+
),
|
170 |
+
'note' => (method_exists($order, 'get_customer_note'))? $order->get_customer_note() : $order->customer_note,
|
171 |
+
// 'customer_ip' => $order->customer_ip_address,
|
172 |
+
// 'customer_user_agent' => $order->customer_user_agent,
|
173 |
+
// 'customer_id' => $order->customer_user,
|
174 |
+
// 'view_order_url' => $order->get_view_order_url(),
|
175 |
+
'line_items' => array(),
|
176 |
+
// 'shipping_lines' => array(),
|
177 |
+
// 'tax_lines' => array(),
|
178 |
+
// 'fee_lines' => array(),
|
179 |
+
// 'coupon_lines' => array(),
|
180 |
+
);
|
181 |
+
|
182 |
+
// add line items
|
183 |
+
foreach ($order->get_items() as $item_id => $item) {
|
184 |
+
|
185 |
+
// $product = $order->get_product_from_item($item);
|
186 |
+
|
187 |
+
$order_data['line_items'][] = array(
|
188 |
+
'id' => $item_id,
|
189 |
+
// 'subtotal' => wc_format_decimal($order->get_line_subtotal($item), 2),
|
190 |
+
// 'total' => wc_format_decimal($order->get_line_total($item), 2),
|
191 |
+
// 'total_tax' => wc_format_decimal($order->get_line_tax($item), 2),
|
192 |
+
// 'price' => wc_format_decimal($order->get_item_total($item), 2),
|
193 |
+
'quantity' => (int)$item['qty'],
|
194 |
+
// 'tax_class' => (!empty($item['tax_class'])) ? $item['tax_class'] : null,
|
195 |
+
'name' => $item['name'],
|
196 |
+
// 'product_id' => (isset($product->variation_id)) ? $product->variation_id : (method_exists($product, 'get_id'))? $product->get_id() : $product->id,
|
197 |
+
// 'sku' => is_object($product) ? $product->get_sku() : null,
|
198 |
+
);
|
199 |
+
}
|
200 |
+
|
201 |
+
/*
|
202 |
+
// add shipping
|
203 |
+
foreach ($order->get_shipping_methods() as $shipping_item_id => $shipping_item) {
|
204 |
+
|
205 |
+
$order_data['shipping_lines'][] = array(
|
206 |
+
'id' => $shipping_item_id,
|
207 |
+
'method_id' => $shipping_item['method_id'],
|
208 |
+
'method_title' => $shipping_item['name'],
|
209 |
+
'total' => wc_format_decimal($shipping_item['cost'], 2),
|
210 |
+
);
|
211 |
+
}
|
212 |
+
|
213 |
+
// add taxes
|
214 |
+
foreach ($order->get_tax_totals() as $tax_code => $tax) {
|
215 |
+
|
216 |
+
$order_data['tax_lines'][] = array(
|
217 |
+
'code' => $tax_code,
|
218 |
+
'title' => $tax->label,
|
219 |
+
'total' => wc_format_decimal($tax->amount, 2),
|
220 |
+
'compound' => (bool)$tax->is_compound,
|
221 |
+
);
|
222 |
+
}
|
223 |
+
|
224 |
+
// add fees
|
225 |
+
foreach ($order->get_fees() as $fee_item_id => $fee_item) {
|
226 |
+
|
227 |
+
$order_data['fee_lines'][] = array(
|
228 |
+
'id' => $fee_item_id,
|
229 |
+
'title' => $fee_item['name'],
|
230 |
+
'tax_class' => (!empty($fee_item['tax_class'])) ? $fee_item['tax_class'] : null,
|
231 |
+
'total' => wc_format_decimal($order->get_line_total($fee_item), 2),
|
232 |
+
'total_tax' => wc_format_decimal($order->get_line_tax($fee_item), 2),
|
233 |
+
);
|
234 |
+
}
|
235 |
+
|
236 |
+
// add coupons
|
237 |
+
foreach ($order->get_items('coupon') as $coupon_item_id => $coupon_item) {
|
238 |
+
|
239 |
+
$order_data['coupon_lines'][] = array(
|
240 |
+
'id' => $coupon_item_id,
|
241 |
+
'code' => $coupon_item['name'],
|
242 |
+
'amount' => wc_format_decimal($coupon_item['discount_amount'], 2),
|
243 |
+
);
|
244 |
+
}
|
245 |
+
*/
|
246 |
+
|
247 |
+
// aftership add
|
248 |
+
$options = get_option('aftership_option_name');
|
249 |
+
$plugin = $options['plugin'];
|
250 |
+
if ($plugin == 'aftership') {
|
251 |
+
|
252 |
+
// $result = array();
|
253 |
+
// foreach($this->aftership_fields as $field){
|
254 |
+
// $id = $field['id'];
|
255 |
+
// $result[substr($id,10)] = get_post_meta((method_exists($order, 'get_id'))? $order->get_id() : $order->id, '_' . $field['id'], true);
|
256 |
+
// }
|
257 |
+
// $order_data['aftership']['woocommerce']['trackings'][] = $result;
|
258 |
+
|
259 |
+
$order_data['aftership']['woocommerce']['trackings'][] = array(
|
260 |
+
'tracking_provider' => order_post_meta_getter($order, 'aftership_tracking_provider'),
|
261 |
+
'tracking_number' => order_post_meta_getter($order, 'aftership_tracking_number'),
|
262 |
+
'tracking_ship_date' => order_post_meta_getter($order, 'aftership_tracking_shipdate'),
|
263 |
+
'tracking_postal_code' => order_post_meta_getter($order, 'aftership_tracking_postal'),
|
264 |
+
'tracking_account_number' => order_post_meta_getter($order, 'aftership_tracking_account'),
|
265 |
+
'tracking_key' => order_post_meta_getter($order, 'aftership_tracking_key'),
|
266 |
+
'tracking_destination_country' => order_post_meta_getter($order, 'aftership_tracking_destination_country'),
|
267 |
+
);
|
268 |
+
}
|
269 |
+
if ($tn == NULL) {
|
270 |
+
// Handle old Shipping Tracking plugin
|
271 |
+
$tn = order_post_meta_getter($order, 'tracking_number');
|
272 |
+
if ($tn == NULL) {
|
273 |
+
// Handle new Shipping Tracking plugin version higher than 1.6.4
|
274 |
+
$tracking_items = order_post_meta_getter($order, 'wc_shipment_tracking_items')[0];
|
275 |
+
|
276 |
+
$order_data['aftership']['woocommerce']['trackings'][] = array(
|
277 |
+
'tracking_number' => $tracking_items['tracking_number'],
|
278 |
+
'tracking_provider' => $tracking_items['custom_tracking_provider']
|
279 |
+
);
|
280 |
+
} else {
|
281 |
+
$order_data['aftership']['woocommerce']['trackings'][] = array(
|
282 |
+
'tracking_number' => $tn,
|
283 |
+
);
|
284 |
+
}
|
285 |
+
}
|
286 |
+
// aftership add finish
|
287 |
+
|
288 |
+
return array('order' => apply_filters('aftership_api_order_response', $order_data, $order, $fields, $this->server));
|
289 |
+
}
|
290 |
+
|
291 |
+
/**
|
292 |
+
* Get the total number of orders
|
293 |
+
*
|
294 |
+
* @since 2.1
|
295 |
+
* @param string $status
|
296 |
+
* @param array $filter
|
297 |
+
* @return array
|
298 |
+
*/
|
299 |
+
public function get_orders_count($status = null, $filter = array())
|
300 |
+
{
|
301 |
+
|
302 |
+
if (!empty($status))
|
303 |
+
$filter['status'] = $status;
|
304 |
+
|
305 |
+
$query = $this->query_orders($filter);
|
306 |
+
|
307 |
+
if (!current_user_can('read_private_shop_orders'))
|
308 |
+
return new WP_Error('aftership_api_user_cannot_read_orders_count', __('You do not have permission to read the orders count', 'aftership'), array('status' => 401));
|
309 |
+
|
310 |
+
return array('count' => (int)$query->found_posts);
|
311 |
+
}
|
312 |
+
|
313 |
+
/**
|
314 |
+
* Edit an order
|
315 |
+
*
|
316 |
+
* API v1 only allows updating the status of an order
|
317 |
+
*
|
318 |
+
* @since 2.1
|
319 |
+
* @param int $id the order ID
|
320 |
+
* @param array $data
|
321 |
+
* @return array
|
322 |
+
*/
|
323 |
+
public function edit_order($id, $data)
|
324 |
+
{
|
325 |
+
|
326 |
+
$id = $this->validate_request($id, 'shop_order', 'edit');
|
327 |
+
|
328 |
+
if (is_wp_error($id))
|
329 |
+
return $id;
|
330 |
+
|
331 |
+
$order = new WC_Order($id);
|
332 |
+
|
333 |
+
if (!empty($data['status'])) {
|
334 |
+
|
335 |
+
$order->update_status($data['status'], isset($data['note']) ? $data['note'] : '');
|
336 |
+
}
|
337 |
+
|
338 |
+
return $this->get_order($id);
|
339 |
+
}
|
340 |
+
|
341 |
+
/**
|
342 |
+
* Delete an order
|
343 |
+
*
|
344 |
+
* @TODO enable along with POST in 2.2
|
345 |
+
* @param int $id the order ID
|
346 |
+
* @param bool $force true to permanently delete order, false to move to trash
|
347 |
+
* @return array
|
348 |
+
*/
|
349 |
+
public function delete_order($id, $force = false)
|
350 |
+
{
|
351 |
+
|
352 |
+
$id = $this->validate_request($id, 'shop_order', 'delete');
|
353 |
+
|
354 |
+
return $this->delete($id, 'order', ('true' === $force));
|
355 |
+
}
|
356 |
+
|
357 |
+
/**
|
358 |
+
* Get the admin order notes for an order
|
359 |
+
*
|
360 |
+
* @since 2.1
|
361 |
+
* @param int $id the order ID
|
362 |
+
* @param string $fields fields to include in response
|
363 |
+
* @return array
|
364 |
+
*/
|
365 |
+
public function get_order_notes($id, $fields = null)
|
366 |
+
{
|
367 |
+
|
368 |
+
// ensure ID is valid order ID
|
369 |
+
$id = $this->validate_request($id, 'shop_order', 'read');
|
370 |
+
|
371 |
+
if (is_wp_error($id))
|
372 |
+
return $id;
|
373 |
+
|
374 |
+
$args = array(
|
375 |
+
'post_id' => $id,
|
376 |
+
'approve' => 'approve',
|
377 |
+
'type' => 'order_note'
|
378 |
+
);
|
379 |
+
|
380 |
+
remove_filter('comments_clauses', array('WC_Comments', 'exclude_order_comments'), 10, 1);
|
381 |
+
|
382 |
+
$notes = get_comments($args);
|
383 |
+
|
384 |
+
add_filter('comments_clauses', array('WC_Comments', 'exclude_order_comments'), 10, 1);
|
385 |
+
|
386 |
+
$order_notes = array();
|
387 |
+
|
388 |
+
foreach ($notes as $note) {
|
389 |
+
|
390 |
+
$order_notes[] = array(
|
391 |
+
'id' => $note->comment_ID,
|
392 |
+
'created_at' => $this->server->format_datetime($note->comment_date_gmt),
|
393 |
+
'note' => $note->comment_content,
|
394 |
+
'customer_note' => get_comment_meta($note->comment_ID, 'is_customer_note', true) ? true : false,
|
395 |
+
);
|
396 |
+
}
|
397 |
+
|
398 |
+
return array('order_notes' => apply_filters('aftership_api_order_notes_response', $order_notes, $id, $fields, $notes, $this->server));
|
399 |
+
}
|
400 |
+
|
401 |
+
/**
|
402 |
+
* Helper method to get order post objects
|
403 |
+
*
|
404 |
+
* @since 2.1
|
405 |
+
* @param array $args request arguments for filtering query
|
406 |
+
* @return WP_Query
|
407 |
+
*/
|
408 |
+
private function query_orders($args)
|
409 |
+
{
|
410 |
+
|
411 |
+
function aftership_wpbo_get_woo_version_number()
|
412 |
+
{
|
413 |
+
// If get_plugins() isn't available, require it
|
414 |
+
if (!function_exists('get_plugins'))
|
415 |
+
require_once(ABSPATH . 'wp-admin/includes/plugin.php');
|
416 |
+
|
417 |
+
// Create the plugins folder and file variables
|
418 |
+
$plugin_folder = get_plugins('/' . 'woocommerce');
|
419 |
+
$plugin_file = 'woocommerce.php';
|
420 |
+
|
421 |
+
// If the plugin version number is set, return it
|
422 |
+
if (isset($plugin_folder[$plugin_file]['Version'])) {
|
423 |
+
return $plugin_folder[$plugin_file]['Version'];
|
424 |
+
|
425 |
+
} else {
|
426 |
+
// Otherwise return null
|
427 |
+
return NULL;
|
428 |
+
}
|
429 |
+
}
|
430 |
+
|
431 |
+
$woo_version = aftership_wpbo_get_woo_version_number();
|
432 |
+
|
433 |
+
if ($woo_version >= 2.2) {
|
434 |
+
// set base query arguments
|
435 |
+
$query_args = array(
|
436 |
+
'fields' => 'ids',
|
437 |
+
'post_type' => 'shop_order',
|
438 |
+
// 'post_status' => 'publish',
|
439 |
+
'post_status' => array_keys(wc_get_order_statuses())
|
440 |
+
);
|
441 |
+
} else {
|
442 |
+
// set base query arguments
|
443 |
+
$query_args = array(
|
444 |
+
'fields' => 'ids',
|
445 |
+
'post_type' => 'shop_order',
|
446 |
+
'post_status' => 'publish',
|
447 |
+
);
|
448 |
+
}
|
449 |
+
|
450 |
+
// add status argument
|
451 |
+
if (!empty($args['status'])) {
|
452 |
+
|
453 |
+
$statuses = explode(',', $args['status']);
|
454 |
+
|
455 |
+
$query_args['tax_query'] = array(
|
456 |
+
array(
|
457 |
+
'taxonomy' => 'shop_order_status',
|
458 |
+
'field' => 'slug',
|
459 |
+
'terms' => $statuses,
|
460 |
+
),
|
461 |
+
);
|
462 |
+
|
463 |
+
unset($args['status']);
|
464 |
+
}
|
465 |
+
|
466 |
+
$query_args = $this->merge_query_args($query_args, $args);
|
467 |
+
|
468 |
+
return new WP_Query($query_args);
|
469 |
+
}
|
470 |
+
|
471 |
+
/**
|
472 |
+
* Helper method to get the order subtotal
|
473 |
+
*
|
474 |
+
* @since 2.1
|
475 |
+
* @param WC_Order $order
|
476 |
+
* @return float
|
477 |
+
*/
|
478 |
+
private function get_order_subtotal($order)
|
479 |
+
{
|
480 |
+
|
481 |
+
$subtotal = 0;
|
482 |
+
|
483 |
+
// subtotal
|
484 |
+
foreach ($order->get_items() as $item) {
|
485 |
+
|
486 |
+
$subtotal += (isset($item['line_subtotal'])) ? $item['line_subtotal'] : 0;
|
487 |
+
}
|
488 |
+
|
489 |
+
return $subtotal;
|
490 |
+
}
|
491 |
+
|
492 |
+
/**
|
493 |
+
* Get the total number of orders
|
494 |
+
*
|
495 |
+
* @since 2.1
|
496 |
+
* @param string $status
|
497 |
+
* @param array $filter
|
498 |
+
* @return array
|
499 |
+
*/
|
500 |
+
public function ping()
|
501 |
+
{
|
502 |
+
return "pong";
|
503 |
+
}
|
504 |
+
|
505 |
+
}
|
trunk/api/class-aftership-api-resource.php
ADDED
@@ -0,0 +1,416 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
<?php
|
2 |
+
/**
|
3 |
+
* AfterShip API Resource class
|
4 |
+
*
|
5 |
+
* Provides shared functionality for resource-specific API classes
|
6 |
+
*
|
7 |
+
* @author AfterShip
|
8 |
+
* @category API
|
9 |
+
* @package AfterShip/API
|
10 |
+
* @since 1.0
|
11 |
+
*/
|
12 |
+
|
13 |
+
if (!defined('ABSPATH')) exit; // Exit if accessed directly
|
14 |
+
|
15 |
+
class AfterShip_API_Resource
|
16 |
+
{
|
17 |
+
|
18 |
+
/** @var WC_API_Server the API server */
|
19 |
+
protected $server;
|
20 |
+
|
21 |
+
/** @var string sub-classes override this to set a resource-specific base route */
|
22 |
+
protected $base;
|
23 |
+
|
24 |
+
/**
|
25 |
+
* Setup class
|
26 |
+
*
|
27 |
+
* @since 2.1
|
28 |
+
* @param WC_API_Server $server
|
29 |
+
* @return WC_API_Resource
|
30 |
+
*/
|
31 |
+
public function __construct(AfterShip_API_Server $server)
|
32 |
+
{
|
33 |
+
|
34 |
+
$this->server = $server;
|
35 |
+
|
36 |
+
// automatically register routes for sub-classes
|
37 |
+
add_filter('aftership_api_endpoints', array($this, 'register_routes'));
|
38 |
+
|
39 |
+
// remove fields from responses when requests specify certain fields
|
40 |
+
// note these are hooked at a later priority so data added via filters (e.g. customer data to the order response)
|
41 |
+
// still has the fields filtered properly
|
42 |
+
foreach (array('order', 'coupon', 'customer', 'product', 'report') as $resource) {
|
43 |
+
|
44 |
+
add_filter("aftership_api_{$resource}_response", array($this, 'maybe_add_meta'), 15, 2);
|
45 |
+
add_filter("aftership_api_{$resource}_response", array($this, 'filter_response_fields'), 20, 3);
|
46 |
+
}
|
47 |
+
}
|
48 |
+
|
49 |
+
/**
|
50 |
+
* Validate the request by checking:
|
51 |
+
*
|
52 |
+
* 1) the ID is a valid integer
|
53 |
+
* 2) the ID returns a valid post object and matches the provided post type
|
54 |
+
* 3) the current user has the proper permissions to read/edit/delete the post
|
55 |
+
*
|
56 |
+
* @since 2.1
|
57 |
+
* @param string|int $id the post ID
|
58 |
+
* @param string $type the post type, either `shop_order`, `shop_coupon`, or `product`
|
59 |
+
* @param string $context the context of the request, either `read`, `edit` or `delete`
|
60 |
+
* @return int|WP_Error valid post ID or WP_Error if any of the checks fails
|
61 |
+
*/
|
62 |
+
protected function validate_request($id, $type, $context)
|
63 |
+
{
|
64 |
+
|
65 |
+
if ('shop_order' === $type || 'shop_coupon' === $type)
|
66 |
+
$resource_name = str_replace('shop_', '', $type);
|
67 |
+
else
|
68 |
+
$resource_name = $type;
|
69 |
+
|
70 |
+
$id = absint($id);
|
71 |
+
|
72 |
+
// validate ID
|
73 |
+
if (empty($id))
|
74 |
+
return new WP_Error("aftership_api_invalid_{$resource_name}_id", sprintf(__('Invalid %s ID', 'aftership'), $type), array('status' => 404));
|
75 |
+
|
76 |
+
// only custom post types have per-post type/permission checks
|
77 |
+
if ('customer' !== $type) {
|
78 |
+
|
79 |
+
$post = get_post($id);
|
80 |
+
|
81 |
+
// for checking permissions, product variations are the same as the product post type
|
82 |
+
$post_type = ('product_variation' === $post->post_type) ? 'product' : $post->post_type;
|
83 |
+
|
84 |
+
// validate post type
|
85 |
+
if ($type !== $post_type)
|
86 |
+
return new WP_Error("aftership_api_invalid_{$resource_name}", sprintf(__('Invalid %s', 'aftership'), $resource_name), array('status' => 404));
|
87 |
+
|
88 |
+
// validate permissions
|
89 |
+
switch ($context) {
|
90 |
+
|
91 |
+
case 'read':
|
92 |
+
if (!$this->is_readable($post))
|
93 |
+
return new WP_Error("aftership_api_user_cannot_read_{$resource_name}", sprintf(__('You do not have permission to read this %s', 'aftership'), $resource_name), array('status' => 401));
|
94 |
+
break;
|
95 |
+
|
96 |
+
case 'edit':
|
97 |
+
if (!$this->is_editable($post))
|
98 |
+
return new WP_Error("aftership_api_user_cannot_edit_{$resource_name}", sprintf(__('You do not have permission to edit this %s', 'aftership'), $resource_name), array('status' => 401));
|
99 |
+
break;
|
100 |
+
|
101 |
+
case 'delete':
|
102 |
+
if (!$this->is_deletable($post))
|
103 |
+
return new WP_Error("aftership_api_user_cannot_delete_{$resource_name}", sprintf(__('You do not have permission to delete this %s', 'aftership'), $resource_name), array('status' => 401));
|
104 |
+
break;
|
105 |
+
}
|
106 |
+
}
|
107 |
+
|
108 |
+
return $id;
|
109 |
+
}
|
110 |
+
|
111 |
+
/**
|
112 |
+
* Add common request arguments to argument list before WP_Query is run
|
113 |
+
*
|
114 |
+
* @since 2.1
|
115 |
+
* @param array $base_args required arguments for the query (e.g. `post_type`, etc)
|
116 |
+
* @param array $request_args arguments provided in the request
|
117 |
+
* @return array
|
118 |
+
*/
|
119 |
+
protected function merge_query_args($base_args, $request_args)
|
120 |
+
{
|
121 |
+
|
122 |
+
$args = array();
|
123 |
+
|
124 |
+
// date
|
125 |
+
if (!empty($request_args['created_at_min']) || !empty($request_args['created_at_max']) || !empty($request_args['updated_at_min']) || !empty($request_args['updated_at_max'])) {
|
126 |
+
|
127 |
+
$args['date_query'] = array();
|
128 |
+
|
129 |
+
// resources created after specified date
|
130 |
+
if (!empty($request_args['created_at_min']))
|
131 |
+
$args['date_query'][] = array('column' => 'post_date_gmt', 'after' => $this->server->parse_datetime($request_args['created_at_min']), 'inclusive' => true);
|
132 |
+
|
133 |
+
// resources created before specified date
|
134 |
+
if (!empty($request_args['created_at_max']))
|
135 |
+
$args['date_query'][] = array('column' => 'post_date_gmt', 'before' => $this->server->parse_datetime($request_args['created_at_max']), 'inclusive' => true);
|
136 |
+
|
137 |
+
// resources updated after specified date
|
138 |
+
if (!empty($request_args['updated_at_min']))
|
139 |
+
$args['date_query'][] = array('column' => 'post_modified_gmt', 'after' => $this->server->parse_datetime($request_args['updated_at_min']), 'inclusive' => true);
|
140 |
+
|
141 |
+
// resources updated before specified date
|
142 |
+
if (!empty($request_args['updated_at_max']))
|
143 |
+
$args['date_query'][] = array('column' => 'post_modified_gmt', 'before' => $this->server->parse_datetime($request_args['updated_at_max']), 'inclusive' => true);
|
144 |
+
}
|
145 |
+
|
146 |
+
// search
|
147 |
+
if (!empty($request_args['q']))
|
148 |
+
$args['s'] = $request_args['q'];
|
149 |
+
|
150 |
+
// resources per response
|
151 |
+
if (!empty($request_args['limit']))
|
152 |
+
$args['posts_per_page'] = $request_args['limit'];
|
153 |
+
|
154 |
+
// resource offset
|
155 |
+
if (!empty($request_args['offset']))
|
156 |
+
$args['offset'] = $request_args['offset'];
|
157 |
+
|
158 |
+
// resource page
|
159 |
+
$args['paged'] = (isset($request_args['page'])) ? absint($request_args['page']) : 1;
|
160 |
+
|
161 |
+
// order
|
162 |
+
if (!empty($request_args['orderby']))
|
163 |
+
$args['orderby'] = $request_args['orderby'];
|
164 |
+
if (!empty($request_args['order']))
|
165 |
+
$args['order'] = $request_args['order'];
|
166 |
+
|
167 |
+
return array_merge($base_args, $args);
|
168 |
+
}
|
169 |
+
|
170 |
+
/**
|
171 |
+
* Add meta to resources when requested by the client. Meta is added as a top-level
|
172 |
+
* `<resource_name>_meta` attribute (e.g. `order_meta`) as a list of key/value pairs
|
173 |
+
*
|
174 |
+
* @since 2.1
|
175 |
+
* @param array $data the resource data
|
176 |
+
* @param object $resource the resource object (e.g WC_Order)
|
177 |
+
* @return mixed
|
178 |
+
*/
|
179 |
+
public function maybe_add_meta($data, $resource)
|
180 |
+
{
|
181 |
+
|
182 |
+
if (isset($this->server->params['GET']['filter']['meta']) && 'true' === $this->server->params['GET']['filter']['meta'] && is_object($resource)) {
|
183 |
+
|
184 |
+
// don't attempt to add meta more than once
|
185 |
+
if (preg_grep('/[a-z]+_meta/', array_keys($data)))
|
186 |
+
return $data;
|
187 |
+
|
188 |
+
// define the top-level property name for the meta
|
189 |
+
switch (get_class($resource)) {
|
190 |
+
|
191 |
+
case 'WC_Order':
|
192 |
+
$meta_name = 'order_meta';
|
193 |
+
break;
|
194 |
+
|
195 |
+
case 'WC_Coupon':
|
196 |
+
$meta_name = 'coupon_meta';
|
197 |
+
break;
|
198 |
+
|
199 |
+
case 'WP_User':
|
200 |
+
$meta_name = 'customer_meta';
|
201 |
+
break;
|
202 |
+
|
203 |
+
default:
|
204 |
+
$meta_name = 'product_meta';
|
205 |
+
break;
|
206 |
+
}
|
207 |
+
|
208 |
+
if (is_a($resource, 'WP_User')) {
|
209 |
+
|
210 |
+
// customer meta
|
211 |
+
$meta = (array)get_user_meta($resource->ID);
|
212 |
+
|
213 |
+
} elseif (is_a($resource, 'WC_Product_Variation')) {
|
214 |
+
|
215 |
+
// product variation meta
|
216 |
+
$meta = (array)get_post_meta($resource->get_variation_id());
|
217 |
+
|
218 |
+
} else {
|
219 |
+
|
220 |
+
// coupon/order/product meta
|
221 |
+
$meta = (array)get_post_meta($resource->id);
|
222 |
+
}
|
223 |
+
|
224 |
+
foreach ($meta as $meta_key => $meta_value) {
|
225 |
+
|
226 |
+
// don't add hidden meta by default
|
227 |
+
if (!is_protected_meta($meta_key)) {
|
228 |
+
$data[$meta_name][$meta_key] = maybe_unserialize($meta_value[0]);
|
229 |
+
}
|
230 |
+
}
|
231 |
+
|
232 |
+
}
|
233 |
+
|
234 |
+
return $data;
|
235 |
+
}
|
236 |
+
|
237 |
+
/**
|
238 |
+
* Restrict the fields included in the response if the request specified certain only certain fields should be returned
|
239 |
+
*
|
240 |
+
* @since 2.1
|
241 |
+
* @param array $data the response data
|
242 |
+
* @param object $resource the object that provided the response data, e.g. WC_Coupon or WC_Order
|
243 |
+
* @param array|string the requested list of fields to include in the response
|
244 |
+
* @return array response data
|
245 |
+
*/
|
246 |
+
public function filter_response_fields($data, $resource, $fields)
|
247 |
+
{
|
248 |
+
|
249 |
+
if (!is_array($data) || empty($fields))
|
250 |
+
return $data;
|
251 |
+
|
252 |
+
$fields = explode(',', $fields);
|
253 |
+
$sub_fields = array();
|
254 |
+
|
255 |
+
// get sub fields
|
256 |
+
foreach ($fields as $field) {
|
257 |
+
|
258 |
+
if (false !== strpos($field, '.')) {
|
259 |
+
|
260 |
+
list($name, $value) = explode('.', $field);
|
261 |
+
|
262 |
+
$sub_fields[$name] = $value;
|
263 |
+
}
|
264 |
+
}
|
265 |
+
|
266 |
+
// iterate through top-level fields
|
267 |
+
foreach ($data as $data_field => $data_value) {
|
268 |
+
|
269 |
+
// if a field has sub-fields and the top-level field has sub-fields to filter
|
270 |
+
if (is_array($data_value) && in_array($data_field, array_keys($sub_fields))) {
|
271 |
+
|
272 |
+
// iterate through each sub-field
|
273 |
+
foreach ($data_value as $sub_field => $sub_field_value) {
|
274 |
+
|
275 |
+
// remove non-matching sub-fields
|
276 |
+
if (!in_array($sub_field, $sub_fields)) {
|
277 |
+
unset($data[$data_field][$sub_field]);
|
278 |
+
}
|
279 |
+
}
|
280 |
+
|
281 |
+
} else {
|
282 |
+
|
283 |
+
// remove non-matching top-level fields
|
284 |
+
if (!in_array($data_field, $fields)) {
|
285 |
+
unset($data[$data_field]);
|
286 |
+
}
|
287 |
+
}
|
288 |
+
}
|
289 |
+
|
290 |
+
return $data;
|
291 |
+
}
|
292 |
+
|
293 |
+
/**
|
294 |
+
* Delete a given resource
|
295 |
+
*
|
296 |
+
* @since 2.1
|
297 |
+
* @param int $id the resource ID
|
298 |
+
* @param string $type the resource post type, or `customer`
|
299 |
+
* @param bool $force true to permanently delete resource, false to move to trash (not supported for `customer`)
|
300 |
+
* @return array|WP_Error
|
301 |
+
*/
|
302 |
+
protected function delete($id, $type, $force = false)
|
303 |
+
{
|
304 |
+
|
305 |
+
if ('shop_order' === $type || 'shop_coupon' === $type)
|
306 |
+
$resource_name = str_replace('shop_', '', $type);
|
307 |
+
else
|
308 |
+
$resource_name = $type;
|
309 |
+
|
310 |
+
if ('customer' === $type) {
|
311 |
+
|
312 |
+
$result = wp_delete_user($id);
|
313 |
+
|
314 |
+
if ($result)
|
315 |
+
return array('message' => __('Permanently deleted customer', 'aftership'));
|
316 |
+
else
|
317 |
+
return new WP_Error('aftership_api_cannot_delete_customer', __('The customer cannot be deleted', 'aftership'), array('status' => 500));
|
318 |
+
|
319 |
+
} else {
|
320 |
+
|
321 |
+
// delete order/coupon/product
|
322 |
+
|
323 |
+
$result = ($force) ? wp_delete_post($id, true) : wp_trash_post($id);
|
324 |
+
|
325 |
+
if (!$result)
|
326 |
+
return new WP_Error("aftership_api_cannot_delete_{$resource_name}", sprintf(__('This %s cannot be deleted', 'aftership'), $resource_name), array('status' => 500));
|
327 |
+
|
328 |
+
if ($force) {
|
329 |
+
return array('message' => sprintf(__('Permanently deleted %s', 'aftership'), $resource_name));
|
330 |
+
|
331 |
+
} else {
|
332 |
+
|
333 |
+
$this->server->send_status('202');
|
334 |
+
|
335 |
+
return array('message' => sprintf(__('Deleted %s', 'aftership'), $resource_name));
|
336 |
+
}
|
337 |
+
}
|
338 |
+
}
|
339 |
+
|
340 |
+
|
341 |
+
/**
|
342 |
+
* Checks if the given post is readable by the current user
|
343 |
+
*
|
344 |
+
* @since 2.1
|
345 |
+
* @see WC_API_Resource::check_permission()
|
346 |
+
* @param WP_Post|int $post
|
347 |
+
* @return bool
|
348 |
+
*/
|
349 |
+
protected function is_readable($post)
|
350 |
+
{
|
351 |
+
|
352 |
+
return $this->check_permission($post, 'read');
|
353 |
+
}
|
354 |
+
|
355 |
+
/**
|
356 |
+
* Checks if the given post is editable by the current user
|
357 |
+
*
|
358 |
+
* @since 2.1
|
359 |
+
* @see WC_API_Resource::check_permission()
|
360 |
+
* @param WP_Post|int $post
|
361 |
+
* @return bool
|
362 |
+
*/
|
363 |
+
protected function is_editable($post)
|
364 |
+
{
|
365 |
+
|
366 |
+
return $this->check_permission($post, 'edit');
|
367 |
+
|
368 |
+
}
|
369 |
+
|
370 |
+
/**
|
371 |
+
* Checks if the given post is deletable by the current user
|
372 |
+
*
|
373 |
+
* @since 2.1
|
374 |
+
* @see WC_API_Resource::check_permission()
|
375 |
+
* @param WP_Post|int $post
|
376 |
+
* @return bool
|
377 |
+
*/
|
378 |
+
protected function is_deletable($post)
|
379 |
+
{
|
380 |
+
|
381 |
+
return $this->check_permission($post, 'delete');
|
382 |
+
}
|
383 |
+
|
384 |
+
/**
|
385 |
+
* Checks the permissions for the current user given a post and context
|
386 |
+
*
|
387 |
+
* @since 2.1
|
388 |
+
* @param WP_Post|int $post
|
389 |
+
* @param string $context the type of permission to check, either `read`, `write`, or `delete`
|
390 |
+
* @return bool true if the current user has the permissions to perform the context on the post
|
391 |
+
*/
|
392 |
+
private function check_permission($post, $context)
|
393 |
+
{
|
394 |
+
|
395 |
+
if (!is_a($post, 'WP_Post'))
|
396 |
+
$post = get_post($post);
|
397 |
+
|
398 |
+
if (is_null($post))
|
399 |
+
return false;
|
400 |
+
|
401 |
+
$post_type = get_post_type_object($post->post_type);
|
402 |
+
|
403 |
+
if ('read' === $context)
|
404 |
+
return current_user_can($post_type->cap->read_private_posts, $post->ID);
|
405 |
+
|
406 |
+
elseif ('edit' === $context)
|
407 |
+
return current_user_can($post_type->cap->edit_post, $post->ID);
|
408 |
+
|
409 |
+
elseif ('delete' === $context)
|
410 |
+
return current_user_can($post_type->cap->delete_post, $post->ID);
|
411 |
+
|
412 |
+
else
|
413 |
+
return false;
|
414 |
+
}
|
415 |
+
|
416 |
+
}
|
trunk/api/class-aftership-api-server.php
ADDED
@@ -0,0 +1,758 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
<?php
|
2 |
+
/**
|
3 |
+
* AfterShip API
|
4 |
+
*
|
5 |
+
* Handles REST API requests
|
6 |
+
*
|
7 |
+
* This class and related code (JSON response handler, resource classes) are based on WP-API v0.6 (https://github.com/WP-API/WP-API)
|
8 |
+
* Many thanks to Ryan McCue and any other contributors!
|
9 |
+
*
|
10 |
+
* @author AfterShip
|
11 |
+
* @category API
|
12 |
+
* @package AfterShip/API
|
13 |
+
* @since 1.0
|
14 |
+
*/
|
15 |
+
|
16 |
+
if (!defined('ABSPATH')) exit; // Exit if accessed directly
|
17 |
+
|
18 |
+
require_once ABSPATH . 'wp-admin/includes/admin.php';
|
19 |
+
|
20 |
+
class AfterShip_API_Server
|
21 |
+
{
|
22 |
+
|
23 |
+
const METHOD_GET = 1;
|
24 |
+
const METHOD_POST = 2;
|
25 |
+
const METHOD_PUT = 4;
|
26 |
+
const METHOD_PATCH = 8;
|
27 |
+
const METHOD_DELETE = 16;
|
28 |
+
|
29 |
+
const READABLE = 1; // GET
|
30 |
+
const CREATABLE = 2; // POST
|
31 |
+
const EDITABLE = 14; // POST | PUT | PATCH
|
32 |
+
const DELETABLE = 16; // DELETE
|
33 |
+
const ALLMETHODS = 31; // GET | POST | PUT | PATCH | DELETE
|
34 |
+
|
35 |
+
/**
|
36 |
+
* Does the endpoint accept a raw request body?
|
37 |
+
*/
|
38 |
+
const ACCEPT_RAW_DATA = 64;
|
39 |
+
|
40 |
+
/** Does the endpoint accept a request body? (either JSON or XML) */
|
41 |
+
const ACCEPT_DATA = 128;
|
42 |
+
|
43 |
+
/**
|
44 |
+
* Should we hide this endpoint from the index?
|
45 |
+
*/
|
46 |
+
const HIDDEN_ENDPOINT = 256;
|
47 |
+
|
48 |
+
/**
|
49 |
+
* Map of HTTP verbs to constants
|
50 |
+
* @var array
|
51 |
+
*/
|
52 |
+
public static $method_map = array(
|
53 |
+
'HEAD' => self::METHOD_GET,
|
54 |
+
'GET' => self::METHOD_GET,
|
55 |
+
'POST' => self::METHOD_POST,
|
56 |
+
'PUT' => self::METHOD_PUT,
|
57 |
+
'PATCH' => self::METHOD_PATCH,
|
58 |
+
'DELETE' => self::METHOD_DELETE,
|
59 |
+
);
|
60 |
+
|
61 |
+
/**
|
62 |
+
* Requested path (relative to the API root, wp-json.php)
|
63 |
+
*
|
64 |
+
* @var string
|
65 |
+
*/
|
66 |
+
public $path = '';
|
67 |
+
|
68 |
+
/**
|
69 |
+
* Requested method (GET/HEAD/POST/PUT/PATCH/DELETE)
|
70 |
+
*
|
71 |
+
* @var string
|
72 |
+
*/
|
73 |
+
public $method = 'HEAD';
|
74 |
+
|
75 |
+
/**
|
76 |
+
* Request parameters
|
77 |
+
*
|
78 |
+
* This acts as an abstraction of the superglobals
|
79 |
+
* (GET => $_GET, POST => $_POST)
|
80 |
+
*
|
81 |
+
* @var array
|
82 |
+
*/
|
83 |
+
public $params = array('GET' => array(), 'POST' => array());
|
84 |
+
|
85 |
+
/**
|
86 |
+
* Request headers
|
87 |
+
*
|
88 |
+
* @var array
|
89 |
+
*/
|
90 |
+
public $headers = array();
|
91 |
+
|
92 |
+
/**
|
93 |
+
* Request files (matches $_FILES)
|
94 |
+
*
|
95 |
+
* @var array
|
96 |
+
*/
|
97 |
+
public $files = array();
|
98 |
+
|
99 |
+
/**
|
100 |
+
* Request/Response handler, either JSON by default
|
101 |
+
* or XML if requested by client
|
102 |
+
*
|
103 |
+
* @var WC_API_Handler
|
104 |
+
*/
|
105 |
+
public $handler;
|
106 |
+
|
107 |
+
|
108 |
+
/**
|
109 |
+
* Setup class and set request/response handler
|
110 |
+
*
|
111 |
+
* @since 2.1
|
112 |
+
* @param $path
|
113 |
+
* @return WC_API_Server
|
114 |
+
*/
|
115 |
+
public function __construct($path)
|
116 |
+
{
|
117 |
+
|
118 |
+
if (empty($path)) {
|
119 |
+
if (isset($_SERVER['PATH_INFO']))
|
120 |
+
$path = $_SERVER['PATH_INFO'];
|
121 |
+
else
|
122 |
+
$path = '/';
|
123 |
+
}
|
124 |
+
|
125 |
+
$this->path = $path;
|
126 |
+
$this->method = $_SERVER['REQUEST_METHOD'];
|
127 |
+
$this->params['GET'] = $_GET;
|
128 |
+
$this->params['POST'] = $_POST;
|
129 |
+
$this->headers = $this->get_headers($_SERVER);
|
130 |
+
$this->files = $_FILES;
|
131 |
+
|
132 |
+
// Compatibility for clients that can't use PUT/PATCH/DELETE
|
133 |
+
if (isset($_GET['_method'])) {
|
134 |
+
$this->method = strtoupper($_GET['_method']);
|
135 |
+
}
|
136 |
+
|
137 |
+
// determine type of request/response and load handler, JSON by default
|
138 |
+
if ($this->is_json_request())
|
139 |
+
$handler_class = 'AfterShip_API_JSON_Handler';
|
140 |
+
|
141 |
+
elseif ($this->is_xml_request())
|
142 |
+
$handler_class = 'WC_API_XML_Handler';
|
143 |
+
|
144 |
+
else
|
145 |
+
$handler_class = apply_filters('aftership_api_default_response_handler', 'AfterShip_API_JSON_Handler', $this->path, $this);
|
146 |
+
|
147 |
+
$this->handler = new $handler_class();
|
148 |
+
}
|
149 |
+
|
150 |
+
/**
|
151 |
+
* Check authentication for the request
|
152 |
+
*
|
153 |
+
* @since 2.1
|
154 |
+
* @return WP_User|WP_Error WP_User object indicates successful login, WP_Error indicates unsuccessful login
|
155 |
+
*/
|
156 |
+
public function check_authentication()
|
157 |
+
{
|
158 |
+
|
159 |
+
// allow plugins to remove default authentication or add their own authentication
|
160 |
+
$user = apply_filters('aftership_api_check_authentication', null, $this);
|
161 |
+
|
162 |
+
// API requests run under the context of the authenticated user
|
163 |
+
if (is_a($user, 'WP_User'))
|
164 |
+
wp_set_current_user($user->ID);
|
165 |
+
|
166 |
+
// WP_Errors are handled in serve_request()
|
167 |
+
elseif (!is_wp_error($user))
|
168 |
+
$user = new WP_Error('aftership_api_authentication_error', __('Invalid authentication method', 'aftership'), array('code' => 500));
|
169 |
+
|
170 |
+
return $user;
|
171 |
+
}
|
172 |
+
|
173 |
+
/**
|
174 |
+
* Convert an error to an array
|
175 |
+
*
|
176 |
+
* This iterates over all error codes and messages to change it into a flat
|
177 |
+
* array. This enables simpler client behaviour, as it is represented as a
|
178 |
+
* list in JSON rather than an object/map
|
179 |
+
*
|
180 |
+
* @since 2.1
|
181 |
+
* @param WP_Error $error
|
182 |
+
* @return array List of associative arrays with code and message keys
|
183 |
+
*/
|
184 |
+
protected function error_to_array($error)
|
185 |
+
{
|
186 |
+
$errors = array();
|
187 |
+
foreach ((array)$error->errors as $code => $messages) {
|
188 |
+
foreach ((array)$messages as $message) {
|
189 |
+
$errors[] = array('code' => $code, 'message' => $message);
|
190 |
+
}
|
191 |
+
}
|
192 |
+
return array('errors' => $errors);
|
193 |
+
}
|
194 |
+
|
195 |
+
/**
|
196 |
+
* Handle serving an API request
|
197 |
+
*
|
198 |
+
* Matches the current server URI to a route and runs the first matching
|
199 |
+
* callback then outputs a JSON representation of the returned value.
|
200 |
+
*
|
201 |
+
* @since 2.1
|
202 |
+
* @uses WC_API_Server::dispatch()
|
203 |
+
*/
|
204 |
+
public function serve_request()
|
205 |
+
{
|
206 |
+
|
207 |
+
do_action('aftership_api_server_before_serve', $this);
|
208 |
+
|
209 |
+
$this->header('Content-Type', $this->handler->get_content_type(), true);
|
210 |
+
|
211 |
+
// the API is enabled by default
|
212 |
+
if (!apply_filters('aftership_api_enabled', true, $this) || ('no' === get_option('aftership_api_enabled'))) {
|
213 |
+
|
214 |
+
$this->send_status(404);
|
215 |
+
|
216 |
+
echo $this->handler->generate_response(array('errors' => array('code' => 'aftership_api_disabled', 'message' => 'The WooCommerce API is disabled on this site')));
|
217 |
+
|
218 |
+
return;
|
219 |
+
}
|
220 |
+
|
221 |
+
$result = $this->check_authentication();
|
222 |
+
|
223 |
+
// if authorization check was successful, dispatch the request
|
224 |
+
if (!is_wp_error($result)) {
|
225 |
+
$result = $this->dispatch();
|
226 |
+
}
|
227 |
+
|
228 |
+
// handle any dispatch errors
|
229 |
+
if (is_wp_error($result)) {
|
230 |
+
$data = $result->get_error_data();
|
231 |
+
if (is_array($data) && isset($data['status'])) {
|
232 |
+
$this->send_status($data['status']);
|
233 |
+
}
|
234 |
+
|
235 |
+
$result = $this->error_to_array($result);
|
236 |
+
}
|
237 |
+
|
238 |
+
// This is a filter rather than an action, since this is designed to be
|
239 |
+
// re-entrant if needed
|
240 |
+
$served = apply_filters('aftership_api_serve_request', false, $result, $this);
|
241 |
+
|
242 |
+
if (!$served) {
|
243 |
+
|
244 |
+
if ('HEAD' === $this->method)
|
245 |
+
return;
|
246 |
+
|
247 |
+
echo $this->handler->generate_response($result);
|
248 |
+
}
|
249 |
+
}
|
250 |
+
|
251 |
+
/**
|
252 |
+
* Retrieve the route map
|
253 |
+
*
|
254 |
+
* The route map is an associative array with path regexes as the keys. The
|
255 |
+
* value is an indexed array with the callback function/method as the first
|
256 |
+
* item, and a bitmask of HTTP methods as the second item (see the class
|
257 |
+
* constants).
|
258 |
+
*
|
259 |
+
* Each route can be mapped to more than one callback by using an array of
|
260 |
+
* the indexed arrays. This allows mapping e.g. GET requests to one callback
|
261 |
+
* and POST requests to another.
|
262 |
+
*
|
263 |
+
* Note that the path regexes (array keys) must have @ escaped, as this is
|
264 |
+
* used as the delimiter with preg_match()
|
265 |
+
*
|
266 |
+
* @since 2.1
|
267 |
+
* @return array `'/path/regex' => array( $callback, $bitmask )` or `'/path/regex' => array( array( $callback, $bitmask ), ...)`
|
268 |
+
*/
|
269 |
+
public function get_routes()
|
270 |
+
{
|
271 |
+
|
272 |
+
// index added by default
|
273 |
+
$endpoints = array(
|
274 |
+
|
275 |
+
'/' => array(array($this, 'get_index'), self::READABLE),
|
276 |
+
);
|
277 |
+
|
278 |
+
$endpoints = apply_filters('aftership_api_endpoints', $endpoints);
|
279 |
+
|
280 |
+
// Normalise the endpoints
|
281 |
+
foreach ($endpoints as $route => &$handlers) {
|
282 |
+
if (count($handlers) <= 2 && isset($handlers[1]) && !is_array($handlers[1])) {
|
283 |
+
$handlers = array($handlers);
|
284 |
+
}
|
285 |
+
}
|
286 |
+
|
287 |
+
return $endpoints;
|
288 |
+
}
|
289 |
+
|
290 |
+
/**
|
291 |
+
* Match the request to a callback and call it
|
292 |
+
*
|
293 |
+
* @since 2.1
|
294 |
+
* @return mixed The value returned by the callback, or a WP_Error instance
|
295 |
+
*/
|
296 |
+
public function dispatch()
|
297 |
+
{
|
298 |
+
|
299 |
+
switch ($this->method) {
|
300 |
+
|
301 |
+
case 'HEAD':
|
302 |
+
case 'GET':
|
303 |
+
$method = self::METHOD_GET;
|
304 |
+
break;
|
305 |
+
/*
|
306 |
+
case 'POST':
|
307 |
+
$method = self::METHOD_POST;
|
308 |
+
break;
|
309 |
+
|
310 |
+
case 'PUT':
|
311 |
+
$method = self::METHOD_PUT;
|
312 |
+
break;
|
313 |
+
|
314 |
+
case 'PATCH':
|
315 |
+
$method = self::METHOD_PATCH;
|
316 |
+
break;
|
317 |
+
|
318 |
+
case 'DELETE':
|
319 |
+
$method = self::METHOD_DELETE;
|
320 |
+
break;
|
321 |
+
*/
|
322 |
+
default:
|
323 |
+
return new WP_Error('aftership_api_unsupported_method', __('Unsupported request method', 'aftership'), array('status' => 400));
|
324 |
+
}
|
325 |
+
|
326 |
+
foreach ($this->get_routes() as $route => $handlers) {
|
327 |
+
foreach ($handlers as $handler) {
|
328 |
+
$callback = $handler[0];
|
329 |
+
$supported = isset($handler[1]) ? $handler[1] : self::METHOD_GET;
|
330 |
+
|
331 |
+
if (!($supported & $method))
|
332 |
+
continue;
|
333 |
+
|
334 |
+
$match = preg_match('@^' . $route . '$@i', urldecode($this->path), $args);
|
335 |
+
|
336 |
+
if (!$match)
|
337 |
+
continue;
|
338 |
+
|
339 |
+
if (!is_callable($callback))
|
340 |
+
return new WP_Error('aftership_api_invalid_handler', __('The handler for the route is invalid', 'aftership'), array('status' => 500));
|
341 |
+
|
342 |
+
$args = array_merge($args, $this->params['GET']);
|
343 |
+
if ($method & self::METHOD_POST) {
|
344 |
+
$args = array_merge($args, $this->params['POST']);
|
345 |
+
}
|
346 |
+
if ($supported & self::ACCEPT_DATA) {
|
347 |
+
$data = $this->handler->parse_body($this->get_raw_data());
|
348 |
+
$args = array_merge($args, array('data' => $data));
|
349 |
+
} elseif ($supported & self::ACCEPT_RAW_DATA) {
|
350 |
+
$data = $this->get_raw_data();
|
351 |
+
$args = array_merge($args, array('data' => $data));
|
352 |
+
}
|
353 |
+
|
354 |
+
$args['_method'] = $method;
|
355 |
+
$args['_route'] = $route;
|
356 |
+
$args['_path'] = $this->path;
|
357 |
+
$args['_headers'] = $this->headers;
|
358 |
+
$args['_files'] = $this->files;
|
359 |
+
|
360 |
+
$args = apply_filters('aftership_api_dispatch_args', $args, $callback);
|
361 |
+
|
362 |
+
// Allow plugins to halt the request via this filter
|
363 |
+
if (is_wp_error($args)) {
|
364 |
+
return $args;
|
365 |
+
}
|
366 |
+
|
367 |
+
$params = $this->sort_callback_params($callback, $args);
|
368 |
+
if (is_wp_error($params))
|
369 |
+
return $params;
|
370 |
+
|
371 |
+
return call_user_func_array($callback, $params);
|
372 |
+
}
|
373 |
+
}
|
374 |
+
|
375 |
+
return new WP_Error('aftership_api_no_route', __('No route was found matching the URL and request method', 'aftership'), array('status' => 404));
|
376 |
+
}
|
377 |
+
|
378 |
+
/**
|
379 |
+
* Sort parameters by order specified in method declaration
|
380 |
+
*
|
381 |
+
* Takes a callback and a list of available params, then filters and sorts
|
382 |
+
* by the parameters the method actually needs, using the Reflection API
|
383 |
+
*
|
384 |
+
* @since 2.1
|
385 |
+
* @param callable|array $callback the endpoint callback
|
386 |
+
* @param array $provided the provided request parameters
|
387 |
+
* @return array
|
388 |
+
*/
|
389 |
+
protected function sort_callback_params($callback, $provided)
|
390 |
+
{
|
391 |
+
if (is_array($callback))
|
392 |
+
$ref_func = new ReflectionMethod($callback[0], $callback[1]);
|
393 |
+
else
|
394 |
+
$ref_func = new ReflectionFunction($callback);
|
395 |
+
|
396 |
+
$wanted = $ref_func->getParameters();
|
397 |
+
$ordered_parameters = array();
|
398 |
+
|
399 |
+
foreach ($wanted as $param) {
|
400 |
+
if (isset($provided[$param->getName()])) {
|
401 |
+
// We have this parameters in the list to choose from
|
402 |
+
|
403 |
+
$ordered_parameters[] = is_array($provided[$param->getName()]) ? array_map('urldecode', $provided[$param->getName()]) : urldecode($provided[$param->getName()]);
|
404 |
+
} elseif ($param->isDefaultValueAvailable()) {
|
405 |
+
// We don't have this parameter, but it's optional
|
406 |
+
$ordered_parameters[] = $param->getDefaultValue();
|
407 |
+
} else {
|
408 |
+
// We don't have this parameter and it wasn't optional, abort!
|
409 |
+
return new WP_Error('aftership_api_missing_callback_param', sprintf(__('Missing parameter %s', 'aftership'), $param->getName()), array('status' => 400));
|
410 |
+
}
|
411 |
+
}
|
412 |
+
return $ordered_parameters;
|
413 |
+
}
|
414 |
+
|
415 |
+
/**
|
416 |
+
* Get the site index.
|
417 |
+
*
|
418 |
+
* This endpoint describes the capabilities of the site.
|
419 |
+
*
|
420 |
+
* @since 2.1
|
421 |
+
* @return array Index entity
|
422 |
+
*/
|
423 |
+
public function get_index()
|
424 |
+
{
|
425 |
+
|
426 |
+
// General site data
|
427 |
+
$available = array('store' => array(
|
428 |
+
'name' => get_option('blogname'),
|
429 |
+
'description' => get_option('blogdescription'),
|
430 |
+
'URL' => get_option('siteurl'),
|
431 |
+
'wc_version' => WC()->version,
|
432 |
+
'routes' => array(),
|
433 |
+
'meta' => array(
|
434 |
+
'timezone' => wc_timezone_string(),
|
435 |
+
'currency' => get_aftership_currency(),
|
436 |
+
'currency_format' => get_aftership_currency_symbol(),
|
437 |
+
'tax_included' => ('yes' === get_option('aftership_prices_include_tax')),
|
438 |
+
'weight_unit' => get_option('aftership_weight_unit'),
|
439 |
+
'dimension_unit' => get_option('aftership_dimension_unit'),
|
440 |
+
'ssl_enabled' => ('yes' === get_option('aftership_force_ssl_checkout')),
|
441 |
+
'permalinks_enabled' => ('' !== get_option('permalink_structure')),
|
442 |
+
'links' => array(
|
443 |
+
'help' => 'https://aftership.uservoice.com/knowledgebase',
|
444 |
+
),
|
445 |
+
),
|
446 |
+
));
|
447 |
+
|
448 |
+
// Find the available routes
|
449 |
+
foreach ($this->get_routes() as $route => $callbacks) {
|
450 |
+
$data = array();
|
451 |
+
|
452 |
+
$route = preg_replace('#\(\?P(<\w+?>).*?\)#', '$1', $route);
|
453 |
+
$methods = array();
|
454 |
+
foreach (self::$method_map as $name => $bitmask) {
|
455 |
+
foreach ($callbacks as $callback) {
|
456 |
+
// Skip to the next route if any callback is hidden
|
457 |
+
if ($callback[1] & self::HIDDEN_ENDPOINT)
|
458 |
+
continue 3;
|
459 |
+
|
460 |
+
if ($callback[1] & $bitmask)
|
461 |
+
$data['supports'][] = $name;
|
462 |
+
|
463 |
+
if ($callback[1] & self::ACCEPT_DATA)
|
464 |
+
$data['accepts_data'] = true;
|
465 |
+
|
466 |
+
// For non-variable routes, generate links
|
467 |
+
if (strpos($route, '<') === false) {
|
468 |
+
$data['meta'] = array(
|
469 |
+
'self' => get_aftership_api_url($route),
|
470 |
+
);
|
471 |
+
}
|
472 |
+
}
|
473 |
+
}
|
474 |
+
$available['store']['routes'][$route] = apply_filters('aftership_api_endpoints_description', $data);
|
475 |
+
}
|
476 |
+
return apply_filters('aftership_api_index', $available);
|
477 |
+
}
|
478 |
+
|
479 |
+
/**
|
480 |
+
* Send a HTTP status code
|
481 |
+
*
|
482 |
+
* @since 2.1
|
483 |
+
* @param int $code HTTP status
|
484 |
+
*/
|
485 |
+
public function send_status($code)
|
486 |
+
{
|
487 |
+
status_header($code);
|
488 |
+
}
|
489 |
+
|
490 |
+
/**
|
491 |
+
* Send a HTTP header
|
492 |
+
*
|
493 |
+
* @since 2.1
|
494 |
+
* @param string $key Header key
|
495 |
+
* @param string $value Header value
|
496 |
+
* @param boolean $replace Should we replace the existing header?
|
497 |
+
*/
|
498 |
+
public function header($key, $value, $replace = true)
|
499 |
+
{
|
500 |
+
header(sprintf('%s: %s', $key, $value), $replace);
|
501 |
+
}
|
502 |
+
|
503 |
+
/**
|
504 |
+
* Send a Link header
|
505 |
+
*
|
506 |
+
* @internal The $rel parameter is first, as this looks nicer when sending multiple
|
507 |
+
*
|
508 |
+
* @link http://tools.ietf.org/html/rfc5988
|
509 |
+
* @link http://www.iana.org/assignments/link-relations/link-relations.xml
|
510 |
+
*
|
511 |
+
* @since 2.1
|
512 |
+
* @param string $rel Link relation. Either a registered type, or an absolute URL
|
513 |
+
* @param string $link Target IRI for the link
|
514 |
+
* @param array $other Other parameters to send, as an associative array
|
515 |
+
*/
|
516 |
+
public function link_header($rel, $link, $other = array())
|
517 |
+
{
|
518 |
+
|
519 |
+
$header = sprintf('<%s>; rel="%s"', $link, esc_attr($rel));
|
520 |
+
|
521 |
+
foreach ($other as $key => $value) {
|
522 |
+
|
523 |
+
if ('title' == $key) {
|
524 |
+
|
525 |
+
$value = '"' . $value . '"';
|
526 |
+
}
|
527 |
+
|
528 |
+
$header .= '; ' . $key . '=' . $value;
|
529 |
+
}
|
530 |
+
|
531 |
+
$this->header('Link', $header, false);
|
532 |
+
}
|
533 |
+
|
534 |
+
/**
|
535 |
+
* Send pagination headers for resources
|
536 |
+
*
|
537 |
+
* @since 2.1
|
538 |
+
* @param WP_Query|WP_User_Query $query
|
539 |
+
*/
|
540 |
+
public function add_pagination_headers($query)
|
541 |
+
{
|
542 |
+
|
543 |
+
// WP_User_Query
|
544 |
+
if (is_a($query, 'WP_User_Query')) {
|
545 |
+
|
546 |
+
$page = $query->page;
|
547 |
+
$single = count($query->get_results()) > 1;
|
548 |
+
$total = $query->get_total();
|
549 |
+
$total_pages = $query->total_pages;
|
550 |
+
|
551 |
+
// WP_Query
|
552 |
+
} else {
|
553 |
+
|
554 |
+
$page = $query->get('paged');
|
555 |
+
$single = $query->is_single();
|
556 |
+
$total = $query->found_posts;
|
557 |
+
$total_pages = $query->max_num_pages;
|
558 |
+
}
|
559 |
+
|
560 |
+
if (!$page)
|
561 |
+
$page = 1;
|
562 |
+
|
563 |
+
$next_page = absint($page) + 1;
|
564 |
+
|
565 |
+
if (!$single) {
|
566 |
+
|
567 |
+
// first/prev
|
568 |
+
if ($page > 1) {
|
569 |
+
$this->link_header('first', $this->get_paginated_url(1));
|
570 |
+
$this->link_header('prev', $this->get_paginated_url($page - 1));
|
571 |
+
}
|
572 |
+
|
573 |
+
// next
|
574 |
+
if ($next_page <= $total_pages) {
|
575 |
+
$this->link_header('next', $this->get_paginated_url($next_page));
|
576 |
+
}
|
577 |
+
|
578 |
+
// last
|
579 |
+
if ($page != $total_pages)
|
580 |
+
$this->link_header('last', $this->get_paginated_url($total_pages));
|
581 |
+
}
|
582 |
+
|
583 |
+
$this->header('X-WC-Total', $total);
|
584 |
+
$this->header('X-WC-TotalPages', $total_pages);
|
585 |
+
|
586 |
+
do_action('aftership_api_pagination_headers', $this, $query);
|
587 |
+
}
|
588 |
+
|
589 |
+
/**
|
590 |
+
* Returns the request URL with the page query parameter set to the specified page
|
591 |
+
*
|
592 |
+
* @since 2.1
|
593 |
+
* @param int $page
|
594 |
+
* @return string
|
595 |
+
*/
|
596 |
+
private function get_paginated_url($page)
|
597 |
+
{
|
598 |
+
|
599 |
+
// remove existing page query param
|
600 |
+
$request = remove_query_arg('page');
|
601 |
+
|
602 |
+
// add provided page query param
|
603 |
+
$request = urldecode(add_query_arg('page', $page, $request));
|
604 |
+
|
605 |
+
// get the home host
|
606 |
+
$host = parse_url(get_home_url(), PHP_URL_HOST);
|
607 |
+
|
608 |
+
return set_url_scheme("http://{$host}{$request}");
|
609 |
+
}
|
610 |
+
|
611 |
+
/**
|
612 |
+
* Retrieve the raw request entity (body)
|
613 |
+
*
|
614 |
+
* @since 2.1
|
615 |
+
* @return string
|
616 |
+
*/
|
617 |
+
public function get_raw_data()
|
618 |
+
{
|
619 |
+
return file_get_contents('php://input');
|
620 |
+
}
|
621 |
+
|
622 |
+
/**
|
623 |
+
* Parse an RFC3339 datetime into a MySQl datetime
|
624 |
+
*
|
625 |
+
* Invalid dates default to unix epoch
|
626 |
+
*
|
627 |
+
* @since 2.1
|
628 |
+
* @param string $datetime RFC3339 datetime
|
629 |
+
* @return string MySQl datetime (YYYY-MM-DD HH:MM:SS)
|
630 |
+
*/
|
631 |
+
public function parse_datetime($datetime)
|
632 |
+
{
|
633 |
+
|
634 |
+
// Strip millisecond precision (a full stop followed by one or more digits)
|
635 |
+
if (strpos($datetime, '.') !== false) {
|
636 |
+
$datetime = preg_replace('/\.\d+/', '', $datetime);
|
637 |
+
}
|
638 |
+
|
639 |
+
// default timezone to UTC
|
640 |
+
$datetime = preg_replace('/[+-]\d+:+\d+$/', '+00:00', $datetime);
|
641 |
+
|
642 |
+
try {
|
643 |
+
|
644 |
+
$datetime = new DateTime($datetime, new DateTimeZone('UTC'));
|
645 |
+
|
646 |
+
} catch (Exception $e) {
|
647 |
+
|
648 |
+
$datetime = new DateTime('@0');
|
649 |
+
|
650 |
+
}
|
651 |
+
|
652 |
+
return $datetime->format('Y-m-d H:i:s');
|
653 |
+
}
|
654 |
+
|
655 |
+
/**
|
656 |
+
* Format a unix timestamp or MySQL datetime into an RFC3339 datetime
|
657 |
+
*
|
658 |
+
* @since 2.1
|
659 |
+
* @param int|string $timestamp unix timestamp or MySQL datetime
|
660 |
+
* @param bool $convert_to_utc
|
661 |
+
* @return string RFC3339 datetime
|
662 |
+
*/
|
663 |
+
public function format_datetime($timestamp, $convert_to_utc = false)
|
664 |
+
{
|
665 |
+
|
666 |
+
if ($convert_to_utc) {
|
667 |
+
$timezone = new DateTimeZone(wc_timezone_string());
|
668 |
+
} else {
|
669 |
+
$timezone = new DateTimeZone('UTC');
|
670 |
+
}
|
671 |
+
|
672 |
+
try {
|
673 |
+
|
674 |
+
if (is_numeric($timestamp)) {
|
675 |
+
$date = new DateTime("@{$timestamp}");
|
676 |
+
} else {
|
677 |
+
$date = new DateTime($timestamp, $timezone);
|
678 |
+
}
|
679 |
+
|
680 |
+
// convert to UTC by adjusting the time based on the offset of the site's timezone
|
681 |
+
if ($convert_to_utc) {
|
682 |
+
$date->modify(-1 * $date->getOffset() . ' seconds');
|
683 |
+
}
|
684 |
+
|
685 |
+
} catch (Exception $e) {
|
686 |
+
|
687 |
+
$date = new DateTime('@0');
|
688 |
+
}
|
689 |
+
|
690 |
+
return $date->format('Y-m-d\TH:i:s\Z');
|
691 |
+
}
|
692 |
+
|
693 |
+
/**
|
694 |
+
* Extract headers from a PHP-style $_SERVER array
|
695 |
+
*
|
696 |
+
* @since 2.1
|
697 |
+
* @param array $server Associative array similar to $_SERVER
|
698 |
+
* @return array Headers extracted from the input
|
699 |
+
*/
|
700 |
+
public function get_headers($server)
|
701 |
+
{
|
702 |
+
$headers = array();
|
703 |
+
// CONTENT_* headers are not prefixed with HTTP_
|
704 |
+
$additional = array('CONTENT_LENGTH' => true, 'CONTENT_MD5' => true, 'CONTENT_TYPE' => true);
|
705 |
+
|
706 |
+
foreach ($server as $key => $value) {
|
707 |
+
if (strpos($key, 'HTTP_') === 0) {
|
708 |
+
$headers[substr($key, 5)] = $value;
|
709 |
+
} elseif (isset($additional[$key])) {
|
710 |
+
$headers[$key] = $value;
|
711 |
+
}
|
712 |
+
}
|
713 |
+
|
714 |
+
return $headers;
|
715 |
+
}
|
716 |
+
|
717 |
+
/**
|
718 |
+
* Check if the current request accepts a JSON response by checking the endpoint suffix (.json) or
|
719 |
+
* the HTTP ACCEPT header
|
720 |
+
*
|
721 |
+
* @since 2.1
|
722 |
+
* @return bool
|
723 |
+
*/
|
724 |
+
private function is_json_request()
|
725 |
+
{
|
726 |
+
|
727 |
+
// check path
|
728 |
+
if (false !== stripos($this->path, '.json'))
|
729 |
+
return true;
|
730 |
+
|
731 |
+
// check ACCEPT header, only 'application/json' is acceptable, see RFC 4627
|
732 |
+
if (isset($this->headers['ACCEPT']) && 'application/json' == $this->headers['ACCEPT'])
|
733 |
+
return true;
|
734 |
+
|
735 |
+
return false;
|
736 |
+
}
|
737 |
+
|
738 |
+
/**
|
739 |
+
* Check if the current request accepts an XML response by checking the endpoint suffix (.xml) or
|
740 |
+
* the HTTP ACCEPT header
|
741 |
+
*
|
742 |
+
* @since 2.1
|
743 |
+
* @return bool
|
744 |
+
*/
|
745 |
+
private function is_xml_request()
|
746 |
+
{
|
747 |
+
|
748 |
+
// check path
|
749 |
+
if (false !== stripos($this->path, '.xml'))
|
750 |
+
return true;
|
751 |
+
|
752 |
+
// check headers, 'application/xml' or 'text/xml' are acceptable, see RFC 2376
|
753 |
+
if (isset($this->headers['ACCEPT']) && ('application/xml' == $this->headers['ACCEPT'] || 'text/xml' == $this->headers['ACCEPT']))
|
754 |
+
return true;
|
755 |
+
|
756 |
+
return false;
|
757 |
+
}
|
758 |
+
}
|
trunk/api/interface-aftership-api-handler.php
ADDED
@@ -0,0 +1,46 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
<?php
|
2 |
+
/**
|
3 |
+
* AfterShip API
|
4 |
+
*
|
5 |
+
* Defines an interface that API request/response handlers should implement
|
6 |
+
*
|
7 |
+
* @author AfterShip
|
8 |
+
* @category API
|
9 |
+
* @package AfterShip/API
|
10 |
+
* @since 1.0
|
11 |
+
*/
|
12 |
+
|
13 |
+
if (!defined('ABSPATH')) exit; // Exit if accessed directly
|
14 |
+
|
15 |
+
interface AfterShip_API_Handler
|
16 |
+
{
|
17 |
+
|
18 |
+
/**
|
19 |
+
* Get the content type for the response
|
20 |
+
*
|
21 |
+
* This should return the proper HTTP content-type for the response
|
22 |
+
*
|
23 |
+
* @since 2.1
|
24 |
+
* @return string
|
25 |
+
*/
|
26 |
+
public function get_content_type();
|
27 |
+
|
28 |
+
/**
|
29 |
+
* Parse the raw request body entity into an array
|
30 |
+
*
|
31 |
+
* @since 2.1
|
32 |
+
* @param string $data
|
33 |
+
* @return array
|
34 |
+
*/
|
35 |
+
public function parse_body($data);
|
36 |
+
|
37 |
+
/**
|
38 |
+
* Generate a response from an array of data
|
39 |
+
*
|
40 |
+
* @since 2.1
|
41 |
+
* @param array $data
|
42 |
+
* @return string
|
43 |
+
*/
|
44 |
+
public function generate_response($data);
|
45 |
+
|
46 |
+
}
|
trunk/assets/css/admin.css
ADDED
@@ -0,0 +1,15 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
.hidden-field {
|
2 |
+
display: none;
|
3 |
+
}
|
4 |
+
|
5 |
+
#aftership_tracking_provider {
|
6 |
+
width: 100%;
|
7 |
+
}
|
8 |
+
|
9 |
+
.aftership_input_text {
|
10 |
+
width: 300px;
|
11 |
+
}
|
12 |
+
|
13 |
+
.aftership_dropdown {
|
14 |
+
width: 300px;
|
15 |
+
}
|
trunk/assets/js/admin.js
ADDED
@@ -0,0 +1,123 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
var aftership_woocommerce_tracking_onload_run = false;
|
2 |
+
|
3 |
+
var aftership_woocommerce_tracking_onload = function () {
|
4 |
+
if (aftership_woocommerce_tracking_onload_run) {
|
5 |
+
return aftership_woocommerce_tracking_onload_run;
|
6 |
+
}
|
7 |
+
aftership_woocommerce_tracking_onload_run = true;
|
8 |
+
|
9 |
+
var fields_id = {
|
10 |
+
'tracking_ship_date': 'aftership_tracking_shipdate',
|
11 |
+
'tracking_postal_code': 'aftership_tracking_postal',
|
12 |
+
'tracking_account_number': 'aftership_tracking_account',
|
13 |
+
'tracking_key': 'aftership_tracking_key',
|
14 |
+
'tracking_destination_country': 'aftership_tracking_destination_country'
|
15 |
+
};
|
16 |
+
|
17 |
+
var providers;
|
18 |
+
|
19 |
+
function hide_input_and_label(id) {
|
20 |
+
jQuery('#' + id).hide();
|
21 |
+
jQuery('label[for=' + id + ']').hide();
|
22 |
+
}
|
23 |
+
|
24 |
+
function show_input_and_label(id) {
|
25 |
+
jQuery('#' + id).show();
|
26 |
+
jQuery('label[for=' + id + ']').show();
|
27 |
+
}
|
28 |
+
|
29 |
+
function set_aftership_tracking_provider() {
|
30 |
+
|
31 |
+
jQuery('#aftership_tracking_provider').change(function () {
|
32 |
+
jQuery.each(fields_id, function (index, item) {
|
33 |
+
hide_input_and_label(item);
|
34 |
+
});
|
35 |
+
|
36 |
+
var slug = jQuery(this).val();
|
37 |
+
if (slug) {
|
38 |
+
var provider = providers[slug];
|
39 |
+
var fields = [];
|
40 |
+
if (jQuery.isArray(provider.required_fields)) {
|
41 |
+
fields = provider.required_fields;
|
42 |
+
} else {
|
43 |
+
fields.push(provider.required_fields);
|
44 |
+
}
|
45 |
+
jQuery.each(fields, function (index, item) {
|
46 |
+
if (fields_id[item]) {
|
47 |
+
show_input_and_label(fields_id[item]);
|
48 |
+
}
|
49 |
+
});
|
50 |
+
jQuery('#aftership_tracking_provider_name').val(provider.name);
|
51 |
+
jQuery('#aftership_tracking_required_fields').val(fields.join());
|
52 |
+
}
|
53 |
+
});
|
54 |
+
}
|
55 |
+
|
56 |
+
|
57 |
+
function fill_meta_box(couriers_selected) {
|
58 |
+
var response = get_couriers();
|
59 |
+
var couriers = [];
|
60 |
+
jQuery.each(response, function (index, courier) {
|
61 |
+
if (couriers_selected.indexOf(courier.slug) != -1) {
|
62 |
+
couriers.push(courier);
|
63 |
+
}
|
64 |
+
});
|
65 |
+
|
66 |
+
var selected_provider = jQuery('#aftership_tracking_provider_hidden').val();
|
67 |
+
var find_selected_provider = couriers_selected.indexOf(selected_provider) != -1;
|
68 |
+
if (!find_selected_provider && selected_provider) {
|
69 |
+
couriers.push({
|
70 |
+
slug: selected_provider,
|
71 |
+
name: jQuery("#aftership_tracking_provider_name").val(),
|
72 |
+
required_fields: jQuery("#aftership_tracking_required_fields").val()
|
73 |
+
});
|
74 |
+
}
|
75 |
+
// console.log(couriers);
|
76 |
+
|
77 |
+
couriers = sort_couriers(couriers);
|
78 |
+
|
79 |
+
jQuery.each(couriers, function (key, courier) {
|
80 |
+
var str = '<option ';
|
81 |
+
if (!find_selected_provider && courier['slug'] == selected_provider) {
|
82 |
+
str += 'style="display:none;" ';
|
83 |
+
}
|
84 |
+
str += 'value="' + courier['slug'] + '" ';
|
85 |
+
if (courier['slug'] == selected_provider) {
|
86 |
+
str += 'selected="selected"';
|
87 |
+
}
|
88 |
+
str += '>' + courier['name'] + '</option>';
|
89 |
+
jQuery('#aftership_tracking_provider').append(str);
|
90 |
+
});
|
91 |
+
// jQuery('#aftership_tracking_provider').val(selected_provider);
|
92 |
+
jQuery('#aftership_tracking_provider').trigger("chosen:updated");
|
93 |
+
jQuery('#aftership_tracking_provider_chosen').css({width: '100%'});
|
94 |
+
|
95 |
+
providers = {};
|
96 |
+
jQuery.each(couriers, function (index, courier) {
|
97 |
+
providers[courier.slug] = courier;
|
98 |
+
});
|
99 |
+
set_aftership_tracking_provider();
|
100 |
+
jQuery('#aftership_tracking_provider').trigger('change');
|
101 |
+
}
|
102 |
+
|
103 |
+
if (jQuery('#aftership_tracking_provider').length > 0) {
|
104 |
+
|
105 |
+
jQuery.each(fields_id, function (index, item) {
|
106 |
+
hide_input_and_label(item);
|
107 |
+
});
|
108 |
+
|
109 |
+
var couriers_selected = jQuery('#aftership_couriers_selected').val();
|
110 |
+
var couriers_selected_arr = (couriers_selected) ? couriers_selected.split(',') : [];
|
111 |
+
fill_meta_box(couriers_selected_arr);
|
112 |
+
}
|
113 |
+
|
114 |
+
if (jQuery('#aftership_tracking_provider_name').length > 0) {
|
115 |
+
jQuery('#aftership_tracking_provider_name').parent().hide();
|
116 |
+
}
|
117 |
+
|
118 |
+
if (jQuery('#aftership_tracking_required_fields').length > 0) {
|
119 |
+
jQuery('#aftership_tracking_required_fields').parent().hide();
|
120 |
+
}
|
121 |
+
|
122 |
+
return aftership_woocommerce_tracking_onload_run;
|
123 |
+
};
|
trunk/assets/js/couriers.js
ADDED
@@ -0,0 +1,2494 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
function get_couriers() {
|
2 |
+
var data = [
|
3 |
+
{
|
4 |
+
"slug": "alliedexpress",
|
5 |
+
"name": "Allied Express",
|
6 |
+
"other_name": "",
|
7 |
+
"required_fields": []
|
8 |
+
},
|
9 |
+
{
|
10 |
+
"slug": "17postservice",
|
11 |
+
"name": "17 Post Service",
|
12 |
+
"other_name": "17PostService",
|
13 |
+
"required_fields": []
|
14 |
+
},
|
15 |
+
{
|
16 |
+
"slug": "2go",
|
17 |
+
"name": "2GO",
|
18 |
+
"other_name": "Negros Navigation",
|
19 |
+
"required_fields": []
|
20 |
+
},
|
21 |
+
{
|
22 |
+
"slug": "360lion",
|
23 |
+
"name": "360 Lion Express",
|
24 |
+
"other_name": "",
|
25 |
+
"required_fields": []
|
26 |
+
},
|
27 |
+
{
|
28 |
+
"slug": "4-72",
|
29 |
+
"name": "4-72 Entregando",
|
30 |
+
"other_name": "Colombia Postal Service",
|
31 |
+
"required_fields": []
|
32 |
+
},
|
33 |
+
{
|
34 |
+
"slug": "4px",
|
35 |
+
"name": "4PX",
|
36 |
+
"other_name": "递四方",
|
37 |
+
"required_fields": []
|
38 |
+
},
|
39 |
+
{
|
40 |
+
"slug": "4squaregroup",
|
41 |
+
"name": "4Square Group",
|
42 |
+
"other_name": "4 Square",
|
43 |
+
"required_fields": []
|
44 |
+
},
|
45 |
+
{
|
46 |
+
"slug": "800bestex",
|
47 |
+
"name": "Best Express",
|
48 |
+
"other_name": "百世汇通",
|
49 |
+
"required_fields": []
|
50 |
+
},
|
51 |
+
{
|
52 |
+
"slug": "abf",
|
53 |
+
"name": "ABF Freight",
|
54 |
+
"other_name": "Arkansas Best Corporation",
|
55 |
+
"required_fields": []
|
56 |
+
},
|
57 |
+
{
|
58 |
+
"slug": "abxexpress-my",
|
59 |
+
"name": "ABX Express",
|
60 |
+
"other_name": "ABX Express (M) Sdn Bhd",
|
61 |
+
"required_fields": []
|
62 |
+
},
|
63 |
+
{
|
64 |
+
"slug": "acommerce",
|
65 |
+
"name": "aCommerce",
|
66 |
+
"other_name": "",
|
67 |
+
"required_fields": []
|
68 |
+
},
|
69 |
+
{
|
70 |
+
"slug": "acscourier",
|
71 |
+
"name": "ACS Courier",
|
72 |
+
"other_name": "Αναζήτηση Καταστημάτων",
|
73 |
+
"required_fields": []
|
74 |
+
},
|
75 |
+
{
|
76 |
+
"slug": "adicional",
|
77 |
+
"name": "Adicional Logistics",
|
78 |
+
"other_name": "",
|
79 |
+
"required_fields": []
|
80 |
+
},
|
81 |
+
{
|
82 |
+
"slug": "adsone",
|
83 |
+
"name": "ADSOne",
|
84 |
+
"other_name": "ADSOne Group",
|
85 |
+
"required_fields": []
|
86 |
+
},
|
87 |
+
{
|
88 |
+
"slug": "aeroflash",
|
89 |
+
"name": "Mexico AeroFlash",
|
90 |
+
"other_name": "AeroFlash",
|
91 |
+
"required_fields": []
|
92 |
+
},
|
93 |
+
{
|
94 |
+
"slug": "air21",
|
95 |
+
"name": "AIR21",
|
96 |
+
"other_name": "AIR 21 PH",
|
97 |
+
"required_fields": []
|
98 |
+
},
|
99 |
+
{
|
100 |
+
"slug": "airpak-express",
|
101 |
+
"name": "Airpak Express",
|
102 |
+
"other_name": "",
|
103 |
+
"required_fields": []
|
104 |
+
},
|
105 |
+
{
|
106 |
+
"slug": "airspeed",
|
107 |
+
"name": "Airspeed International Corporation",
|
108 |
+
"other_name": "Airspeed Philippines",
|
109 |
+
"required_fields": []
|
110 |
+
},
|
111 |
+
{
|
112 |
+
"slug": "ajexpress",
|
113 |
+
"name": "a j express",
|
114 |
+
"other_name": "",
|
115 |
+
"required_fields": []
|
116 |
+
},
|
117 |
+
{
|
118 |
+
"slug": "alphafast",
|
119 |
+
"name": "alphaFAST",
|
120 |
+
"other_name": "Alpha",
|
121 |
+
"required_fields": []
|
122 |
+
},
|
123 |
+
{
|
124 |
+
"slug": "an-post",
|
125 |
+
"name": "An Post",
|
126 |
+
"other_name": "Ireland Post",
|
127 |
+
"required_fields": []
|
128 |
+
},
|
129 |
+
{
|
130 |
+
"slug": "apc",
|
131 |
+
"name": "APC Postal Logistics",
|
132 |
+
"other_name": "APC-PLI",
|
133 |
+
"required_fields": []
|
134 |
+
},
|
135 |
+
{
|
136 |
+
"slug": "apc-overnight",
|
137 |
+
"name": "APC Overnight",
|
138 |
+
"other_name": "Net Despatch",
|
139 |
+
"required_fields": [
|
140 |
+
"tracking_account_number"
|
141 |
+
]
|
142 |
+
},
|
143 |
+
{
|
144 |
+
"slug": "apc-overnight-reference",
|
145 |
+
"name": "APC Overnight Reference",
|
146 |
+
"other_name": "Net Despatch",
|
147 |
+
"required_fields": [
|
148 |
+
"tracking_account_number"
|
149 |
+
]
|
150 |
+
},
|
151 |
+
{
|
152 |
+
"slug": "aramex",
|
153 |
+
"name": "Aramex",
|
154 |
+
"other_name": "ارامكس",
|
155 |
+
"required_fields": []
|
156 |
+
},
|
157 |
+
{
|
158 |
+
"slug": "arrowxl",
|
159 |
+
"name": "Arrow XL",
|
160 |
+
"other_name": "Yodel XL",
|
161 |
+
"required_fields": [
|
162 |
+
"tracking_postal_code"
|
163 |
+
]
|
164 |
+
},
|
165 |
+
{
|
166 |
+
"slug": "asendia-de",
|
167 |
+
"name": "Asendia Germany",
|
168 |
+
"other_name": "Asendia De",
|
169 |
+
"required_fields": []
|
170 |
+
},
|
171 |
+
{
|
172 |
+
"slug": "asendia-uk",
|
173 |
+
"name": "Asendia UK",
|
174 |
+
"other_name": "Asendia United Kingdom",
|
175 |
+
"required_fields": []
|
176 |
+
},
|
177 |
+
{
|
178 |
+
"slug": "asendia-usa",
|
179 |
+
"name": "Asendia USA",
|
180 |
+
"other_name": "Brokers Worldwide",
|
181 |
+
"required_fields": []
|
182 |
+
},
|
183 |
+
{
|
184 |
+
"slug": "asm",
|
185 |
+
"name": "ASM",
|
186 |
+
"other_name": "Asm-Red",
|
187 |
+
"required_fields": [
|
188 |
+
"tracking_postal_code"
|
189 |
+
]
|
190 |
+
},
|
191 |
+
{
|
192 |
+
"slug": "aupost-china",
|
193 |
+
"name": "AuPost China",
|
194 |
+
"other_name": "澳邮宝",
|
195 |
+
"required_fields": []
|
196 |
+
},
|
197 |
+
{
|
198 |
+
"slug": "australia-post",
|
199 |
+
"name": "Australia Post",
|
200 |
+
"other_name": "AusPost",
|
201 |
+
"required_fields": []
|
202 |
+
},
|
203 |
+
{
|
204 |
+
"slug": "australia-post-sftp",
|
205 |
+
"name": "Australia Post Sftp",
|
206 |
+
"other_name": "AusPostSftp",
|
207 |
+
"required_fields": [
|
208 |
+
"tracking_account_number"
|
209 |
+
]
|
210 |
+
},
|
211 |
+
{
|
212 |
+
"slug": "austrian-post",
|
213 |
+
"name": "Austrian Post (Express)",
|
214 |
+
"other_name": "Österreichische Post AG",
|
215 |
+
"required_fields": []
|
216 |
+
},
|
217 |
+
{
|
218 |
+
"slug": "austrian-post-registered",
|
219 |
+
"name": "Austrian Post (Registered)",
|
220 |
+
"other_name": "Österreichische Post AG",
|
221 |
+
"required_fields": []
|
222 |
+
},
|
223 |
+
{
|
224 |
+
"slug": "axl",
|
225 |
+
"name": "AXL Express & Logistics",
|
226 |
+
"other_name": "AXL",
|
227 |
+
"required_fields": []
|
228 |
+
},
|
229 |
+
{
|
230 |
+
"slug": "b2ceurope",
|
231 |
+
"name": "B2C Europe",
|
232 |
+
"other_name": "trackyourparcel.eu",
|
233 |
+
"required_fields": [
|
234 |
+
"tracking_postal_code",
|
235 |
+
"tracking_destination_country"
|
236 |
+
]
|
237 |
+
},
|
238 |
+
{
|
239 |
+
"slug": "belpost",
|
240 |
+
"name": "Belpost",
|
241 |
+
"other_name": "Belposhta, Белпочта",
|
242 |
+
"required_fields": []
|
243 |
+
},
|
244 |
+
{
|
245 |
+
"slug": "bert-fr",
|
246 |
+
"name": "Bert Transport",
|
247 |
+
"other_name": "",
|
248 |
+
"required_fields": []
|
249 |
+
},
|
250 |
+
{
|
251 |
+
"slug": "bgpost",
|
252 |
+
"name": "Bulgarian Posts",
|
253 |
+
"other_name": "Български пощи",
|
254 |
+
"required_fields": []
|
255 |
+
},
|
256 |
+
{
|
257 |
+
"slug": "bh-posta",
|
258 |
+
"name": "JP BH Pošta",
|
259 |
+
"other_name": "Bosnia and Herzegovina Post",
|
260 |
+
"required_fields": []
|
261 |
+
},
|
262 |
+
{
|
263 |
+
"slug": "bluedart",
|
264 |
+
"name": "Bluedart",
|
265 |
+
"other_name": "Blue Dart Express",
|
266 |
+
"required_fields": []
|
267 |
+
},
|
268 |
+
{
|
269 |
+
"slug": "bondscouriers",
|
270 |
+
"name": "Bonds Couriers",
|
271 |
+
"other_name": "",
|
272 |
+
"required_fields": []
|
273 |
+
},
|
274 |
+
{
|
275 |
+
"slug": "boxc",
|
276 |
+
"name": "BOXC",
|
277 |
+
"other_name": "BOXC快遞",
|
278 |
+
"required_fields": []
|
279 |
+
},
|
280 |
+
{
|
281 |
+
"slug": "bpost",
|
282 |
+
"name": "Bpost",
|
283 |
+
"other_name": "Belgian Post, Belgium Post",
|
284 |
+
"required_fields": []
|
285 |
+
},
|
286 |
+
{
|
287 |
+
"slug": "bpost-international",
|
288 |
+
"name": "Bpost international",
|
289 |
+
"other_name": "Landmark Global",
|
290 |
+
"required_fields": []
|
291 |
+
},
|
292 |
+
{
|
293 |
+
"slug": "brazil-correios",
|
294 |
+
"name": "Brazil Correios",
|
295 |
+
"other_name": "Brazilian Post",
|
296 |
+
"required_fields": []
|
297 |
+
},
|
298 |
+
{
|
299 |
+
"slug": "brt-it",
|
300 |
+
"name": "BRT Bartolini",
|
301 |
+
"other_name": "BRT Corriere Espresso, DPD Italy",
|
302 |
+
"required_fields": []
|
303 |
+
},
|
304 |
+
{
|
305 |
+
"slug": "brt-it-parcelid",
|
306 |
+
"name": "BRT Bartolini(Parcel ID)",
|
307 |
+
"other_name": "BRT Corriere Espresso, DPD Italy",
|
308 |
+
"required_fields": []
|
309 |
+
},
|
310 |
+
{
|
311 |
+
"slug": "buylogic",
|
312 |
+
"name": "Buylogic",
|
313 |
+
"other_name": "捷买送",
|
314 |
+
"required_fields": []
|
315 |
+
},
|
316 |
+
{
|
317 |
+
"slug": "cambodia-post",
|
318 |
+
"name": "Cambodia Post",
|
319 |
+
"other_name": "Cambodia Post",
|
320 |
+
"required_fields": []
|
321 |
+
},
|
322 |
+
{
|
323 |
+
"slug": "canada-post",
|
324 |
+
"name": "Canada Post",
|
325 |
+
"other_name": "Postes Canada",
|
326 |
+
"required_fields": []
|
327 |
+
},
|
328 |
+
{
|
329 |
+
"slug": "canpar",
|
330 |
+
"name": "Canpar Courier",
|
331 |
+
"other_name": "TransForce",
|
332 |
+
"required_fields": []
|
333 |
+
},
|
334 |
+
{
|
335 |
+
"slug": "cbl-logistica",
|
336 |
+
"name": "CBL Logistics",
|
337 |
+
"other_name": "",
|
338 |
+
"required_fields": []
|
339 |
+
},
|
340 |
+
{
|
341 |
+
"slug": "ceska-posta",
|
342 |
+
"name": "Česká Pošta",
|
343 |
+
"other_name": "Czech Post",
|
344 |
+
"required_fields": []
|
345 |
+
},
|
346 |
+
{
|
347 |
+
"slug": "china-ems",
|
348 |
+
"name": "China EMS",
|
349 |
+
"other_name": "中国邮政速递物流",
|
350 |
+
"required_fields": []
|
351 |
+
},
|
352 |
+
{
|
353 |
+
"slug": "china-post",
|
354 |
+
"name": "China Post",
|
355 |
+
"other_name": "中国邮政, ePacket, e-Packet",
|
356 |
+
"required_fields": []
|
357 |
+
},
|
358 |
+
{
|
359 |
+
"slug": "chronopost-france",
|
360 |
+
"name": "Chronopost France",
|
361 |
+
"other_name": "La Poste EMS",
|
362 |
+
"required_fields": []
|
363 |
+
},
|
364 |
+
{
|
365 |
+
"slug": "chronopost-portugal",
|
366 |
+
"name": "Chronopost Portugal",
|
367 |
+
"other_name": "Chronopost pt",
|
368 |
+
"required_fields": []
|
369 |
+
},
|
370 |
+
{
|
371 |
+
"slug": "city-link",
|
372 |
+
"name": "City Link",
|
373 |
+
"other_name": "City Link UK",
|
374 |
+
"required_fields": []
|
375 |
+
},
|
376 |
+
{
|
377 |
+
"slug": "city-link-international",
|
378 |
+
"name": "City Link International",
|
379 |
+
"other_name": "citylink.norsknet.com",
|
380 |
+
"required_fields": []
|
381 |
+
},
|
382 |
+
{
|
383 |
+
"slug": "citylinkexpress",
|
384 |
+
"name": "City-Link Express",
|
385 |
+
"other_name": "Citylink Malaysia",
|
386 |
+
"required_fields": []
|
387 |
+
},
|
388 |
+
{
|
389 |
+
"slug": "cj-gls",
|
390 |
+
"name": "CJ GLS",
|
391 |
+
"other_name": "CJ Korea Express, 씨제이지엘에스주식회사",
|
392 |
+
"required_fields": []
|
393 |
+
},
|
394 |
+
{
|
395 |
+
"slug": "cj-korea-thai",
|
396 |
+
"name": "CJ Korea Express (Thailand)",
|
397 |
+
"other_name": "",
|
398 |
+
"required_fields": []
|
399 |
+
},
|
400 |
+
{
|
401 |
+
"slug": "cnexps",
|
402 |
+
"name": "CNE Express",
|
403 |
+
"other_name": "国际快递",
|
404 |
+
"required_fields": []
|
405 |
+
},
|
406 |
+
{
|
407 |
+
"slug": "colis-prive",
|
408 |
+
"name": "Colis Privé",
|
409 |
+
"other_name": "ColisPrivé",
|
410 |
+
"required_fields": [
|
411 |
+
"tracking_postal_code"
|
412 |
+
]
|
413 |
+
},
|
414 |
+
{
|
415 |
+
"slug": "colissimo",
|
416 |
+
"name": "Colissimo",
|
417 |
+
"other_name": "Colissimo fr",
|
418 |
+
"required_fields": []
|
419 |
+
},
|
420 |
+
{
|
421 |
+
"slug": "collectplus",
|
422 |
+
"name": "Collect+",
|
423 |
+
"other_name": "Collect Plus UK",
|
424 |
+
"required_fields": []
|
425 |
+
},
|
426 |
+
{
|
427 |
+
"slug": "con-way",
|
428 |
+
"name": "Con-way Freight",
|
429 |
+
"other_name": "Conway",
|
430 |
+
"required_fields": []
|
431 |
+
},
|
432 |
+
{
|
433 |
+
"slug": "copa-courier",
|
434 |
+
"name": "Copa Airlines Courier",
|
435 |
+
"other_name": "Copa Courier",
|
436 |
+
"required_fields": []
|
437 |
+
},
|
438 |
+
{
|
439 |
+
"slug": "correo-argentino",
|
440 |
+
"name": "Correo Argentino",
|
441 |
+
"other_name": "Argentina Post",
|
442 |
+
"required_fields": []
|
443 |
+
},
|
444 |
+
{
|
445 |
+
"slug": "correos-chile",
|
446 |
+
"name": "Correos Chile",
|
447 |
+
"other_name": "Chile Post",
|
448 |
+
"required_fields": []
|
449 |
+
},
|
450 |
+
{
|
451 |
+
"slug": "correos-de-costa-rica",
|
452 |
+
"name": "Correos de Costa Rica",
|
453 |
+
"other_name": "",
|
454 |
+
"required_fields": []
|
455 |
+
},
|
456 |
+
{
|
457 |
+
"slug": "correos-de-mexico",
|
458 |
+
"name": "Correos de Mexico",
|
459 |
+
"other_name": "Mexico Post",
|
460 |
+
"required_fields": []
|
461 |
+
},
|
462 |
+
{
|
463 |
+
"slug": "correosexpress",
|
464 |
+
"name": "Correos Express",
|
465 |
+
"other_name": "",
|
466 |
+
"required_fields": [
|
467 |
+
"tracking_postal_code"
|
468 |
+
]
|
469 |
+
},
|
470 |
+
{
|
471 |
+
"slug": "costmeticsnow",
|
472 |
+
"name": "Cosmetics Now",
|
473 |
+
"other_name": "CosmeticsNow",
|
474 |
+
"required_fields": []
|
475 |
+
},
|
476 |
+
{
|
477 |
+
"slug": "courex",
|
478 |
+
"name": "Courex",
|
479 |
+
"other_name": "",
|
480 |
+
"required_fields": []
|
481 |
+
},
|
482 |
+
{
|
483 |
+
"slug": "courier-plus",
|
484 |
+
"name": "Courier Plus",
|
485 |
+
"other_name": "Courier Plus",
|
486 |
+
"required_fields": []
|
487 |
+
},
|
488 |
+
{
|
489 |
+
"slug": "courierit",
|
490 |
+
"name": "Courier IT",
|
491 |
+
"other_name": "Courierit",
|
492 |
+
"required_fields": []
|
493 |
+
},
|
494 |
+
{
|
495 |
+
"slug": "courierpost",
|
496 |
+
"name": "CourierPost",
|
497 |
+
"other_name": "Express Couriers",
|
498 |
+
"required_fields": []
|
499 |
+
},
|
500 |
+
{
|
501 |
+
"slug": "couriers-please",
|
502 |
+
"name": "Couriers Please",
|
503 |
+
"other_name": "CouriersPlease",
|
504 |
+
"required_fields": []
|
505 |
+
},
|
506 |
+
{
|
507 |
+
"slug": "cpacket",
|
508 |
+
"name": "cPacket",
|
509 |
+
"other_name": "u52a0u90aeu5b9d",
|
510 |
+
"required_fields": []
|
511 |
+
},
|
512 |
+
{
|
513 |
+
"slug": "cuckooexpress",
|
514 |
+
"name": "Cuckoo Express",
|
515 |
+
"other_name": "布谷鸟",
|
516 |
+
"required_fields": []
|
517 |
+
},
|
518 |
+
{
|
519 |
+
"slug": "cyprus-post",
|
520 |
+
"name": "Cyprus Post",
|
521 |
+
"other_name": "ΚΥΠΡΙΑΚΑ ΤΑΧΥΔΡΟΜΕΙΑ",
|
522 |
+
"required_fields": []
|
523 |
+
},
|
524 |
+
{
|
525 |
+
"slug": "dachser",
|
526 |
+
"name": "DACHSER",
|
527 |
+
"other_name": "Azkar",
|
528 |
+
"required_fields": []
|
529 |
+
},
|
530 |
+
{
|
531 |
+
"slug": "danmark-post",
|
532 |
+
"name": "PostNord Denmark",
|
533 |
+
"other_name": "Danmark Post",
|
534 |
+
"required_fields": []
|
535 |
+
},
|
536 |
+
{
|
537 |
+
"slug": "dawnwing",
|
538 |
+
"name": "Dawn Wing",
|
539 |
+
"other_name": "DPD Laser Express Logistics",
|
540 |
+
"required_fields": []
|
541 |
+
},
|
542 |
+
{
|
543 |
+
"slug": "dbschenker-se",
|
544 |
+
"name": "DB Schenker",
|
545 |
+
"other_name": "Deutsche Bahn",
|
546 |
+
"required_fields": []
|
547 |
+
},
|
548 |
+
{
|
549 |
+
"slug": "delcart-in",
|
550 |
+
"name": "Delcart",
|
551 |
+
"other_name": "",
|
552 |
+
"required_fields": []
|
553 |
+
},
|
554 |
+
{
|
555 |
+
"slug": "delhivery",
|
556 |
+
"name": "Delhivery",
|
557 |
+
"other_name": "Gharpay",
|
558 |
+
"required_fields": []
|
559 |
+
},
|
560 |
+
{
|
561 |
+
"slug": "delivreeking",
|
562 |
+
"name": "Delivree King",
|
563 |
+
"other_name": "delivery king",
|
564 |
+
"required_fields": []
|
565 |
+
},
|
566 |
+
{
|
567 |
+
"slug": "deltec-courier",
|
568 |
+
"name": "Deltec Courier",
|
569 |
+
"other_name": "Deltec Interntional Courier",
|
570 |
+
"required_fields": []
|
571 |
+
},
|
572 |
+
{
|
573 |
+
"slug": "detrack",
|
574 |
+
"name": "Detrack",
|
575 |
+
"other_name": "Detrack Singapore",
|
576 |
+
"required_fields": []
|
577 |
+
},
|
578 |
+
{
|
579 |
+
"slug": "deutsch-post",
|
580 |
+
"name": "Deutsche Post Mail",
|
581 |
+
"other_name": "dpdhl",
|
582 |
+
"required_fields": [
|
583 |
+
"tracking_ship_date"
|
584 |
+
]
|
585 |
+
},
|
586 |
+
{
|
587 |
+
"slug": "dex-i",
|
588 |
+
"name": "DEX-I",
|
589 |
+
"other_name": "",
|
590 |
+
"required_fields": []
|
591 |
+
},
|
592 |
+
{
|
593 |
+
"slug": "dhl",
|
594 |
+
"name": "DHL Express",
|
595 |
+
"other_name": "DHL International",
|
596 |
+
"required_fields": []
|
597 |
+
},
|
598 |
+
{
|
599 |
+
"slug": "dhl-active-tracing",
|
600 |
+
"name": "DHL Active Tracing",
|
601 |
+
"other_name": "",
|
602 |
+
"required_fields": []
|
603 |
+
},
|
604 |
+
{
|
605 |
+
"slug": "dhl-benelux",
|
606 |
+
"name": "DHL Benelux",
|
607 |
+
"other_name": "DHL TrackNet Benelux",
|
608 |
+
"required_fields": []
|
609 |
+
},
|
610 |
+
{
|
611 |
+
"slug": "dhl-deliverit",
|
612 |
+
"name": "DHL 2-Mann-Handling",
|
613 |
+
"other_name": "DHL Deliver IT",
|
614 |
+
"required_fields": [
|
615 |
+
"tracking_postal_code"
|
616 |
+
]
|
617 |
+
},
|
618 |
+
{
|
619 |
+
"slug": "dhl-es",
|
620 |
+
"name": "DHL Spain Domestic",
|
621 |
+
"other_name": "DHL España",
|
622 |
+
"required_fields": []
|
623 |
+
},
|
624 |
+
{
|
625 |
+
"slug": "dhl-germany",
|
626 |
+
"name": "Deutsche Post DHL",
|
627 |
+
"other_name": "DHL Germany",
|
628 |
+
"required_fields": []
|
629 |
+
},
|
630 |
+
{
|
631 |
+
"slug": "dhl-global-forwarding",
|
632 |
+
"name": "DHL Global Forwarding",
|
633 |
+
"other_name": "DHL Logistics",
|
634 |
+
"required_fields": []
|
635 |
+
},
|
636 |
+
{
|
637 |
+
"slug": "dhl-global-mail",
|
638 |
+
"name": "DHL eCommerce",
|
639 |
+
"other_name": "DHL Global Mail",
|
640 |
+
"required_fields": []
|
641 |
+
},
|
642 |
+
{
|
643 |
+
"slug": "dhl-global-mail-asia",
|
644 |
+
"name": "DHL Global Mail Asia",
|
645 |
+
"other_name": "DGM Asia",
|
646 |
+
"required_fields": []
|
647 |
+
},
|
648 |
+
{
|
649 |
+
"slug": "dhl-hk",
|
650 |
+
"name": "DHL Hong Kong",
|
651 |
+
"other_name": "DHL HK Domestic",
|
652 |
+
"required_fields": []
|
653 |
+
},
|
654 |
+
{
|
655 |
+
"slug": "dhl-nl",
|
656 |
+
"name": "DHL Netherlands",
|
657 |
+
"other_name": "DHL Nederlands",
|
658 |
+
"required_fields": []
|
659 |
+
},
|
660 |
+
{
|
661 |
+
"slug": "dhl-pieceid",
|
662 |
+
"name": "DHL Express (Piece ID)",
|
663 |
+
"other_name": "DHL International",
|
664 |
+
"required_fields": []
|
665 |
+
},
|
666 |
+
{
|
667 |
+
"slug": "dhl-poland",
|
668 |
+
"name": "DHL Poland Domestic",
|
669 |
+
"other_name": "DHL Polska",
|
670 |
+
"required_fields": []
|
671 |
+
},
|
672 |
+
{
|
673 |
+
"slug": "dhlparcel-nl",
|
674 |
+
"name": "DHL Parcel NL",
|
675 |
+
"other_name": "Selektvracht, dhlparcel.nl",
|
676 |
+
"required_fields": []
|
677 |
+
},
|
678 |
+
{
|
679 |
+
"slug": "directfreight-au",
|
680 |
+
"name": "Direct Freight Express",
|
681 |
+
"other_name": "",
|
682 |
+
"required_fields": []
|
683 |
+
},
|
684 |
+
{
|
685 |
+
"slug": "directlink",
|
686 |
+
"name": "Direct Link",
|
687 |
+
"other_name": "Direct Link",
|
688 |
+
"required_fields": []
|
689 |
+
},
|
690 |
+
{
|
691 |
+
"slug": "directlog",
|
692 |
+
"name": "Directlog",
|
693 |
+
"other_name": "Direct Express",
|
694 |
+
"required_fields": []
|
695 |
+
},
|
696 |
+
{
|
697 |
+
"slug": "dmm-network",
|
698 |
+
"name": "DMM Network",
|
699 |
+
"other_name": "dmmnetwork.it",
|
700 |
+
"required_fields": []
|
701 |
+
},
|
702 |
+
{
|
703 |
+
"slug": "dotzot",
|
704 |
+
"name": "Dotzot",
|
705 |
+
"other_name": "Dotzot",
|
706 |
+
"required_fields": []
|
707 |
+
},
|
708 |
+
{
|
709 |
+
"slug": "dpd",
|
710 |
+
"name": "DPD",
|
711 |
+
"other_name": "Dynamic Parcel Distribution",
|
712 |
+
"required_fields": []
|
713 |
+
},
|
714 |
+
{
|
715 |
+
"slug": "dpd-de",
|
716 |
+
"name": "DPD Germany",
|
717 |
+
"other_name": "DPD Germany",
|
718 |
+
"required_fields": []
|
719 |
+
},
|
720 |
+
{
|
721 |
+
"slug": "dpd-ireland",
|
722 |
+
"name": "DPD Ireland",
|
723 |
+
"other_name": "DPD ie",
|
724 |
+
"required_fields": []
|
725 |
+
},
|
726 |
+
{
|
727 |
+
"slug": "dpd-poland",
|
728 |
+
"name": "DPD Poland",
|
729 |
+
"other_name": "Dynamic Parcel Distribution Poland",
|
730 |
+
"required_fields": []
|
731 |
+
},
|
732 |
+
{
|
733 |
+
"slug": "dpd-uk",
|
734 |
+
"name": "DPD UK",
|
735 |
+
"other_name": "Dynamic Parcel Distribution UK",
|
736 |
+
"required_fields": []
|
737 |
+
},
|
738 |
+
{
|
739 |
+
"slug": "dpe-express",
|
740 |
+
"name": "DPE Express",
|
741 |
+
"other_name": "Delivery Perfect Express Co.",
|
742 |
+
"required_fields": []
|
743 |
+
},
|
744 |
+
{
|
745 |
+
"slug": "dpe-za",
|
746 |
+
"name": "DPE South Africa",
|
747 |
+
"other_name": "DPE Worldwide Express",
|
748 |
+
"required_fields": []
|
749 |
+
},
|
750 |
+
{
|
751 |
+
"slug": "dpex",
|
752 |
+
"name": "DPEX",
|
753 |
+
"other_name": "TGX, Toll Global Express Asia",
|
754 |
+
"required_fields": []
|
755 |
+
},
|
756 |
+
{
|
757 |
+
"slug": "dsv",
|
758 |
+
"name": "DSV",
|
759 |
+
"other_name": "",
|
760 |
+
"required_fields": []
|
761 |
+
},
|
762 |
+
{
|
763 |
+
"slug": "dtdc",
|
764 |
+
"name": "DTDC India",
|
765 |
+
"other_name": "DTDC Courier & Cargo",
|
766 |
+
"required_fields": []
|
767 |
+
},
|
768 |
+
{
|
769 |
+
"slug": "dtdc-au",
|
770 |
+
"name": "DTDC Australia",
|
771 |
+
"other_name": "",
|
772 |
+
"required_fields": []
|
773 |
+
},
|
774 |
+
{
|
775 |
+
"slug": "dx",
|
776 |
+
"name": "DX",
|
777 |
+
"other_name": "-",
|
778 |
+
"required_fields": [
|
779 |
+
"tracking_account_number"
|
780 |
+
]
|
781 |
+
},
|
782 |
+
{
|
783 |
+
"slug": "dx-freight",
|
784 |
+
"name": "DX Freight",
|
785 |
+
"other_name": "",
|
786 |
+
"required_fields": [
|
787 |
+
"tracking_account_number"
|
788 |
+
]
|
789 |
+
},
|
790 |
+
{
|
791 |
+
"slug": "dynamic-logistics",
|
792 |
+
"name": "Dynamic Logistics",
|
793 |
+
"other_name": "Dynamic Logistics Thailand",
|
794 |
+
"required_fields": [
|
795 |
+
"tracking_account_number"
|
796 |
+
]
|
797 |
+
},
|
798 |
+
{
|
799 |
+
"slug": "easy-mail",
|
800 |
+
"name": "Easy Mail",
|
801 |
+
"other_name": "",
|
802 |
+
"required_fields": []
|
803 |
+
},
|
804 |
+
{
|
805 |
+
"slug": "ec-firstclass",
|
806 |
+
"name": "EC-Firstclass",
|
807 |
+
"other_name": "ChuKou1, CK1",
|
808 |
+
"required_fields": []
|
809 |
+
},
|
810 |
+
{
|
811 |
+
"slug": "ecargo-asia",
|
812 |
+
"name": "Ecargo",
|
813 |
+
"other_name": "Ecargo Pte. Ltd",
|
814 |
+
"required_fields": []
|
815 |
+
},
|
816 |
+
{
|
817 |
+
"slug": "ecexpress-cn",
|
818 |
+
"name": "EC Express",
|
819 |
+
"other_name": "CIS Post, u4e0au6d77u4e1cu64ce",
|
820 |
+
"required_fields": []
|
821 |
+
},
|
822 |
+
{
|
823 |
+
"slug": "echo",
|
824 |
+
"name": "Echo",
|
825 |
+
"other_name": "Echo Global Logistics",
|
826 |
+
"required_fields": []
|
827 |
+
},
|
828 |
+
{
|
829 |
+
"slug": "ecom-express",
|
830 |
+
"name": "Ecom Express",
|
831 |
+
"other_name": "EcomExpress",
|
832 |
+
"required_fields": []
|
833 |
+
},
|
834 |
+
{
|
835 |
+
"slug": "ekart",
|
836 |
+
"name": "Ekart",
|
837 |
+
"other_name": "Ekart Logistics",
|
838 |
+
"required_fields": []
|
839 |
+
},
|
840 |
+
{
|
841 |
+
"slug": "elta-courier",
|
842 |
+
"name": "ELTA Hellenic Post",
|
843 |
+
"other_name": "Greece Post, Ελληνικά Ταχυδρομεία, ELTA Courier, Ταχυμεταφορές ΕΛΤΑ",
|
844 |
+
"required_fields": []
|
845 |
+
},
|
846 |
+
{
|
847 |
+
"slug": "emirates-post",
|
848 |
+
"name": "Emirates Post",
|
849 |
+
"other_name": "مجموعة بريد الإمارات, UAE Post",
|
850 |
+
"required_fields": []
|
851 |
+
},
|
852 |
+
{
|
853 |
+
"slug": "empsexpress",
|
854 |
+
"name": "EMPS Express",
|
855 |
+
"other_name": "快信快包",
|
856 |
+
"required_fields": []
|
857 |
+
},
|
858 |
+
{
|
859 |
+
"slug": "ensenda",
|
860 |
+
"name": "Ensenda",
|
861 |
+
"other_name": "",
|
862 |
+
"required_fields": []
|
863 |
+
},
|
864 |
+
{
|
865 |
+
"slug": "envialia",
|
866 |
+
"name": "Envialia",
|
867 |
+
"other_name": "Envialia Spain",
|
868 |
+
"required_fields": []
|
869 |
+
},
|
870 |
+
{
|
871 |
+
"slug": "eparcel-kr",
|
872 |
+
"name": "eParcel Korea",
|
873 |
+
"other_name": "Yong Seoung",
|
874 |
+
"required_fields": []
|
875 |
+
},
|
876 |
+
{
|
877 |
+
"slug": "equick-cn",
|
878 |
+
"name": "Equick China",
|
879 |
+
"other_name": "北京网易速达",
|
880 |
+
"required_fields": []
|
881 |
+
},
|
882 |
+
{
|
883 |
+
"slug": "estafeta",
|
884 |
+
"name": "Estafeta",
|
885 |
+
"other_name": "Estafeta Mexicana",
|
886 |
+
"required_fields": []
|
887 |
+
},
|
888 |
+
{
|
889 |
+
"slug": "estes",
|
890 |
+
"name": "Estes",
|
891 |
+
"other_name": "Estes Express Lines",
|
892 |
+
"required_fields": []
|
893 |
+
},
|
894 |
+
{
|
895 |
+
"slug": "evergreen",
|
896 |
+
"name": "Evergreen",
|
897 |
+
"other_name": "Evergreen Marine Corp",
|
898 |
+
"required_fields": []
|
899 |
+
},
|
900 |
+
{
|
901 |
+
"slug": "exapaq",
|
902 |
+
"name": "DPD France",
|
903 |
+
"other_name": "Exapaq",
|
904 |
+
"required_fields": []
|
905 |
+
},
|
906 |
+
{
|
907 |
+
"slug": "expeditors",
|
908 |
+
"name": "Expeditors",
|
909 |
+
"other_name": "",
|
910 |
+
"required_fields": []
|
911 |
+
},
|
912 |
+
{
|
913 |
+
"slug": "fastrak-th",
|
914 |
+
"name": "Fastrak Services",
|
915 |
+
"other_name": "Fastrak Advanced Delivery Systems",
|
916 |
+
"required_fields": []
|
917 |
+
},
|
918 |
+
{
|
919 |
+
"slug": "fastway-au",
|
920 |
+
"name": "Fastway Australia",
|
921 |
+
"other_name": "Fastway Couriers",
|
922 |
+
"required_fields": []
|
923 |
+
},
|
924 |
+
{
|
925 |
+
"slug": "fastway-ireland",
|
926 |
+
"name": "Fastway Ireland",
|
927 |
+
"other_name": "Fastway Couriers",
|
928 |
+
"required_fields": []
|
929 |
+
},
|
930 |
+
{
|
931 |
+
"slug": "fastway-nz",
|
932 |
+
"name": "Fastway New Zealand",
|
933 |
+
"other_name": "",
|
934 |
+
"required_fields": []
|
935 |
+
},
|
936 |
+
{
|
937 |
+
"slug": "fastway-za",
|
938 |
+
"name": "Fastway South Africa",
|
939 |
+
"other_name": "Fastway Couriers",
|
940 |
+
"required_fields": []
|
941 |
+
},
|
942 |
+
{
|
943 |
+
"slug": "fedex",
|
944 |
+
"name": "FedEx",
|
945 |
+
"other_name": "Federal Express",
|
946 |
+
"required_fields": []
|
947 |
+
},
|
948 |
+
{
|
949 |
+
"slug": "fedex-freight",
|
950 |
+
"name": "FedEx Freight",
|
951 |
+
"other_name": "FedEx LTL",
|
952 |
+
"required_fields": []
|
953 |
+
},
|
954 |
+
{
|
955 |
+
"slug": "fedex-uk",
|
956 |
+
"name": "FedEx UK",
|
957 |
+
"other_name": "FedEx United Kingdom",
|
958 |
+
"required_fields": []
|
959 |
+
},
|
960 |
+
{
|
961 |
+
"slug": "fercam",
|
962 |
+
"name": "FERCAM Logistics & Transport",
|
963 |
+
"other_name": "FERCAM SpA",
|
964 |
+
"required_fields": []
|
965 |
+
},
|
966 |
+
{
|
967 |
+
"slug": "first-flight",
|
968 |
+
"name": "First Flight Couriers",
|
969 |
+
"other_name": "FirstFlight India",
|
970 |
+
"required_fields": []
|
971 |
+
},
|
972 |
+
{
|
973 |
+
"slug": "first-logistics",
|
974 |
+
"name": "First Logistics",
|
975 |
+
"other_name": "PT Synergy First Logistics",
|
976 |
+
"required_fields": []
|
977 |
+
},
|
978 |
+
{
|
979 |
+
"slug": "flash-courier",
|
980 |
+
"name": "Flash Courier",
|
981 |
+
"other_name": "Flash Courier Brazil",
|
982 |
+
"required_fields": []
|
983 |
+
},
|
984 |
+
{
|
985 |
+
"slug": "flytexpress",
|
986 |
+
"name": "Flyt Express",
|
987 |
+
"other_name": "飞特物流",
|
988 |
+
"required_fields": []
|
989 |
+
},
|
990 |
+
{
|
991 |
+
"slug": "gati-kwe",
|
992 |
+
"name": "Gati-KWE",
|
993 |
+
"other_name": "Gati-Kintetsu Express",
|
994 |
+
"required_fields": []
|
995 |
+
},
|
996 |
+
{
|
997 |
+
"slug": "gdex",
|
998 |
+
"name": "GDEX",
|
999 |
+
"other_name": "GD Express",
|
1000 |
+
"required_fields": []
|
1001 |
+
},
|
1002 |
+
{
|
1003 |
+
"slug": "geodis-calberson-fr",
|
1004 |
+
"name": "GEODIS - Distribution & Express",
|
1005 |
+
"other_name": "Geodiscalberson",
|
1006 |
+
"required_fields": [
|
1007 |
+
"tracking_postal_code"
|
1008 |
+
]
|
1009 |
+
},
|
1010 |
+
{
|
1011 |
+
"slug": "geodis-espace",
|
1012 |
+
"name": "Geodis E-space",
|
1013 |
+
"other_name": "Geodis Distribution & Express",
|
1014 |
+
"required_fields": [
|
1015 |
+
"tracking_key"
|
1016 |
+
]
|
1017 |
+
},
|
1018 |
+
{
|
1019 |
+
"slug": "ghn",
|
1020 |
+
"name": "Giao hàng nhanh",
|
1021 |
+
"other_name": "Giaohangnhanh.vn, GHN",
|
1022 |
+
"required_fields": []
|
1023 |
+
},
|
1024 |
+
{
|
1025 |
+
"slug": "globegistics",
|
1026 |
+
"name": "Globegistics Inc.",
|
1027 |
+
"other_name": "",
|
1028 |
+
"required_fields": []
|
1029 |
+
},
|
1030 |
+
{
|
1031 |
+
"slug": "gls",
|
1032 |
+
"name": "GLS",
|
1033 |
+
"other_name": "General Logistics Systems",
|
1034 |
+
"required_fields": []
|
1035 |
+
},
|
1036 |
+
{
|
1037 |
+
"slug": "gls-italy",
|
1038 |
+
"name": "GLS Italy",
|
1039 |
+
"other_name": "GLS Corriere Espresso",
|
1040 |
+
"required_fields": []
|
1041 |
+
},
|
1042 |
+
{
|
1043 |
+
"slug": "gls-netherlands",
|
1044 |
+
"name": "GLS Netherlands",
|
1045 |
+
"other_name": "GLS NL",
|
1046 |
+
"required_fields": [
|
1047 |
+
"tracking_postal_code"
|
1048 |
+
]
|
1049 |
+
},
|
1050 |
+
{
|
1051 |
+
"slug": "gofly",
|
1052 |
+
"name": "GoFly",
|
1053 |
+
"other_name": "GoFlyi",
|
1054 |
+
"required_fields": []
|
1055 |
+
},
|
1056 |
+
{
|
1057 |
+
"slug": "gojavas",
|
1058 |
+
"name": "GoJavas",
|
1059 |
+
"other_name": "Javas",
|
1060 |
+
"required_fields": []
|
1061 |
+
},
|
1062 |
+
{
|
1063 |
+
"slug": "greyhound",
|
1064 |
+
"name": "Greyhound",
|
1065 |
+
"other_name": "Greyhound Package Express",
|
1066 |
+
"required_fields": []
|
1067 |
+
},
|
1068 |
+
{
|
1069 |
+
"slug": "hermes",
|
1070 |
+
"name": "Hermesworld",
|
1071 |
+
"other_name": "Hermes-europe UK",
|
1072 |
+
"required_fields": []
|
1073 |
+
},
|
1074 |
+
{
|
1075 |
+
"slug": "hermes-de",
|
1076 |
+
"name": "Hermes Germany",
|
1077 |
+
"other_name": "myhermes.de, Hermes Logistik Gruppe Deutschland",
|
1078 |
+
"required_fields": []
|
1079 |
+
},
|
1080 |
+
{
|
1081 |
+
"slug": "hh-exp",
|
1082 |
+
"name": "Hua Han Logistics",
|
1083 |
+
"other_name": "u534eu7ff0u56fdu9645u7269u6d41",
|
1084 |
+
"required_fields": []
|
1085 |
+
},
|
1086 |
+
{
|
1087 |
+
"slug": "holisol",
|
1088 |
+
"name": "Holisol",
|
1089 |
+
"other_name": "",
|
1090 |
+
"required_fields": []
|
1091 |
+
},
|
1092 |
+
{
|
1093 |
+
"slug": "homedirect-logistics",
|
1094 |
+
"name": "Homedirect Logistics",
|
1095 |
+
"other_name": "",
|
1096 |
+
"required_fields": []
|
1097 |
+
},
|
1098 |
+
{
|
1099 |
+
"slug": "hong-kong-post",
|
1100 |
+
"name": "Hong Kong Post",
|
1101 |
+
"other_name": "香港郵政",
|
1102 |
+
"required_fields": []
|
1103 |
+
},
|
1104 |
+
{
|
1105 |
+
"slug": "hrvatska-posta",
|
1106 |
+
"name": "Hrvatska Pošta",
|
1107 |
+
"other_name": "Croatia Post",
|
1108 |
+
"required_fields": []
|
1109 |
+
},
|
1110 |
+
{
|
1111 |
+
"slug": "hunter-express",
|
1112 |
+
"name": "Hunter Express",
|
1113 |
+
"other_name": "",
|
1114 |
+
"required_fields": []
|
1115 |
+
},
|
1116 |
+
{
|
1117 |
+
"slug": "i-parcel",
|
1118 |
+
"name": "i-parcel",
|
1119 |
+
"other_name": "iparcel",
|
1120 |
+
"required_fields": []
|
1121 |
+
},
|
1122 |
+
{
|
1123 |
+
"slug": "idexpress",
|
1124 |
+
"name": "IDEX",
|
1125 |
+
"other_name": "上海宏杉国际物流",
|
1126 |
+
"required_fields": []
|
1127 |
+
},
|
1128 |
+
{
|
1129 |
+
"slug": "imexglobalsolutions",
|
1130 |
+
"name": " IMEX Global Solutions",
|
1131 |
+
"other_name": "",
|
1132 |
+
"required_fields": []
|
1133 |
+
},
|
1134 |
+
{
|
1135 |
+
"slug": "imxmail",
|
1136 |
+
"name": "IMX Mail",
|
1137 |
+
"other_name": "IMX International Mail Consolidator",
|
1138 |
+
"required_fields": []
|
1139 |
+
},
|
1140 |
+
{
|
1141 |
+
"slug": "india-post",
|
1142 |
+
"name": "India Post Domestic",
|
1143 |
+
"other_name": "भारतीय डाक",
|
1144 |
+
"required_fields": []
|
1145 |
+
},
|
1146 |
+
{
|
1147 |
+
"slug": "india-post-int",
|
1148 |
+
"name": "India Post International",
|
1149 |
+
"other_name": "भारतीय डाक, Speed Post & eMO, EMS, IPS Web",
|
1150 |
+
"required_fields": []
|
1151 |
+
},
|
1152 |
+
{
|
1153 |
+
"slug": "inpost-paczkomaty",
|
1154 |
+
"name": "InPost Paczkomaty",
|
1155 |
+
"other_name": "",
|
1156 |
+
"required_fields": []
|
1157 |
+
},
|
1158 |
+
{
|
1159 |
+
"slug": "interlink-express",
|
1160 |
+
"name": "Interlink Express",
|
1161 |
+
"other_name": "Interlink UK",
|
1162 |
+
"required_fields": []
|
1163 |
+
},
|
1164 |
+
{
|
1165 |
+
"slug": "interlink-express-reference",
|
1166 |
+
"name": "Interlink Express Reference",
|
1167 |
+
"other_name": "",
|
1168 |
+
"required_fields": [
|
1169 |
+
"tracking_postal_code"
|
1170 |
+
]
|
1171 |
+
},
|
1172 |
+
{
|
1173 |
+
"slug": "international-seur",
|
1174 |
+
"name": "International Seur",
|
1175 |
+
"other_name": "SEUR Internacional",
|
1176 |
+
"required_fields": []
|
1177 |
+
},
|
1178 |
+
{
|
1179 |
+
"slug": "israel-post",
|
1180 |
+
"name": "Israel Post",
|
1181 |
+
"other_name": "חברת דואר ישראל",
|
1182 |
+
"required_fields": []
|
1183 |
+
},
|
1184 |
+
{
|
1185 |
+
"slug": "israel-post-domestic",
|
1186 |
+
"name": "Israel Post Domestic",
|
1187 |
+
"other_name": "חברת דואר ישראל מקומית",
|
1188 |
+
"required_fields": []
|
1189 |
+
},
|
1190 |
+
{
|
1191 |
+
"slug": "italy-sda",
|
1192 |
+
"name": "Italy SDA",
|
1193 |
+
"other_name": "SDA Express Courier",
|
1194 |
+
"required_fields": []
|
1195 |
+
},
|
1196 |
+
{
|
1197 |
+
"slug": "itis",
|
1198 |
+
"name": "ITIS International",
|
1199 |
+
"other_name": "ITIS International",
|
1200 |
+
"required_fields": []
|
1201 |
+
},
|
1202 |
+
{
|
1203 |
+
"slug": "jam-express",
|
1204 |
+
"name": "Jam Express",
|
1205 |
+
"other_name": "JAM Global Express",
|
1206 |
+
"required_fields": []
|
1207 |
+
},
|
1208 |
+
{
|
1209 |
+
"slug": "japan-post",
|
1210 |
+
"name": "Japan Post",
|
1211 |
+
"other_name": "日本郵便",
|
1212 |
+
"required_fields": []
|
1213 |
+
},
|
1214 |
+
{
|
1215 |
+
"slug": "jayonexpress",
|
1216 |
+
"name": "Jayon Express (JEX)",
|
1217 |
+
"other_name": "",
|
1218 |
+
"required_fields": []
|
1219 |
+
},
|
1220 |
+
{
|
1221 |
+
"slug": "jcex",
|
1222 |
+
"name": "JCEX",
|
1223 |
+
"other_name": "JiaCheng, 杭州佳成",
|
1224 |
+
"required_fields": []
|
1225 |
+
},
|
1226 |
+
{
|
1227 |
+
"slug": "jersey-post",
|
1228 |
+
"name": "Jersey Post",
|
1229 |
+
"other_name": "",
|
1230 |
+
"required_fields": []
|
1231 |
+
},
|
1232 |
+
{
|
1233 |
+
"slug": "jet-ship",
|
1234 |
+
"name": "Jet-Ship Worldwide",
|
1235 |
+
"other_name": "",
|
1236 |
+
"required_fields": []
|
1237 |
+
},
|
1238 |
+
{
|
1239 |
+
"slug": "jne",
|
1240 |
+
"name": "JNE",
|
1241 |
+
"other_name": "Express Across Nation, Tiki Jalur Nugraha Ekakurir",
|
1242 |
+
"required_fields": []
|
1243 |
+
},
|
1244 |
+
{
|
1245 |
+
"slug": "jocom",
|
1246 |
+
"name": "Jocom",
|
1247 |
+
"other_name": "",
|
1248 |
+
"required_fields": []
|
1249 |
+
},
|
1250 |
+
{
|
1251 |
+
"slug": "kangaroo-my",
|
1252 |
+
"name": "Kangaroo Worldwide Express",
|
1253 |
+
"other_name": "",
|
1254 |
+
"required_fields": []
|
1255 |
+
},
|
1256 |
+
{
|
1257 |
+
"slug": "kerry-logistics",
|
1258 |
+
"name": "Kerry Express Thailand",
|
1259 |
+
"other_name": "嘉里物流, Kerry Logistics",
|
1260 |
+
"required_fields": []
|
1261 |
+
},
|
1262 |
+
{
|
1263 |
+
"slug": "kerryttc-vn",
|
1264 |
+
"name": "Kerry TTC Express",
|
1265 |
+
"other_name": "KTTC",
|
1266 |
+
"required_fields": []
|
1267 |
+
},
|
1268 |
+
{
|
1269 |
+
"slug": "kgmhub",
|
1270 |
+
"name": "KGM Hub",
|
1271 |
+
"other_name": "KGM",
|
1272 |
+
"required_fields": []
|
1273 |
+
},
|
1274 |
+
{
|
1275 |
+
"slug": "kiala",
|
1276 |
+
"name": "Kiala",
|
1277 |
+
"other_name": "",
|
1278 |
+
"required_fields": []
|
1279 |
+
},
|
1280 |
+
{
|
1281 |
+
"slug": "kn",
|
1282 |
+
"name": "Kuehne + Nagel",
|
1283 |
+
"other_name": "KN",
|
1284 |
+
"required_fields": []
|
1285 |
+
},
|
1286 |
+
{
|
1287 |
+
"slug": "korea-post",
|
1288 |
+
"name": "Korea Post",
|
1289 |
+
"other_name": "우정사업본부",
|
1290 |
+
"required_fields": []
|
1291 |
+
},
|
1292 |
+
{
|
1293 |
+
"slug": "la-poste-colissimo",
|
1294 |
+
"name": "La Poste",
|
1295 |
+
"other_name": "Coliposte",
|
1296 |
+
"required_fields": []
|
1297 |
+
},
|
1298 |
+
{
|
1299 |
+
"slug": "landmark-global",
|
1300 |
+
"name": "Landmark Global",
|
1301 |
+
"other_name": "",
|
1302 |
+
"required_fields": []
|
1303 |
+
},
|
1304 |
+
{
|
1305 |
+
"slug": "lao-post",
|
1306 |
+
"name": "Lao Post",
|
1307 |
+
"other_name": "Laos Postal Service",
|
1308 |
+
"required_fields": []
|
1309 |
+
},
|
1310 |
+
{
|
1311 |
+
"slug": "lasership",
|
1312 |
+
"name": "LaserShip",
|
1313 |
+
"other_name": "LaserShip",
|
1314 |
+
"required_fields": []
|
1315 |
+
},
|
1316 |
+
{
|
1317 |
+
"slug": "lbcexpress",
|
1318 |
+
"name": "LBC Express",
|
1319 |
+
"other_name": "LBC Express",
|
1320 |
+
"required_fields": []
|
1321 |
+
},
|
1322 |
+
{
|
1323 |
+
"slug": "lietuvos-pastas",
|
1324 |
+
"name": "Lietuvos Paštas",
|
1325 |
+
"other_name": "Lithuania Post, LP Express",
|
1326 |
+
"required_fields": []
|
1327 |
+
},
|
1328 |
+
{
|
1329 |
+
"slug": "lion-parcel",
|
1330 |
+
"name": "Lion Parcel",
|
1331 |
+
"other_name": "",
|
1332 |
+
"required_fields": []
|
1333 |
+
},
|
1334 |
+
{
|
1335 |
+
"slug": "logwin-logistics",
|
1336 |
+
"name": "Logwin Logistics",
|
1337 |
+
"other_name": "",
|
1338 |
+
"required_fields": []
|
1339 |
+
},
|
1340 |
+
{
|
1341 |
+
"slug": "lwe-hk",
|
1342 |
+
"name": "Logistic Worldwide Express",
|
1343 |
+
"other_name": "LWE",
|
1344 |
+
"required_fields": []
|
1345 |
+
},
|
1346 |
+
{
|
1347 |
+
"slug": "magyar-posta",
|
1348 |
+
"name": "Magyar Posta",
|
1349 |
+
"other_name": "Hungarian Post",
|
1350 |
+
"required_fields": []
|
1351 |
+
},
|
1352 |
+
{
|
1353 |
+
"slug": "mailamericas",
|
1354 |
+
"name": "MailAmericas",
|
1355 |
+
"other_name": "",
|
1356 |
+
"required_fields": []
|
1357 |
+
},
|
1358 |
+
{
|
1359 |
+
"slug": "malaysia-post",
|
1360 |
+
"name": "Malaysia Post EMS / Pos Laju",
|
1361 |
+
"other_name": "Pos Ekspres, Pos Malaysia Express",
|
1362 |
+
"required_fields": []
|
1363 |
+
},
|
1364 |
+
{
|
1365 |
+
"slug": "malaysia-post-posdaftar",
|
1366 |
+
"name": "Malaysia Post - Registered",
|
1367 |
+
"other_name": "PosDaftar",
|
1368 |
+
"required_fields": []
|
1369 |
+
},
|
1370 |
+
{
|
1371 |
+
"slug": "mara-xpress",
|
1372 |
+
"name": "Mara Xpress",
|
1373 |
+
"other_name": "",
|
1374 |
+
"required_fields": []
|
1375 |
+
},
|
1376 |
+
{
|
1377 |
+
"slug": "matdespatch",
|
1378 |
+
"name": "Matdespatch",
|
1379 |
+
"other_name": "",
|
1380 |
+
"required_fields": []
|
1381 |
+
},
|
1382 |
+
{
|
1383 |
+
"slug": "matkahuolto",
|
1384 |
+
"name": "Matkahuolto",
|
1385 |
+
"other_name": "Oy Matkahuolto Ab",
|
1386 |
+
"required_fields": []
|
1387 |
+
},
|
1388 |
+
{
|
1389 |
+
"slug": "maxcellents",
|
1390 |
+
"name": "Maxcellents Pte Ltd",
|
1391 |
+
"other_name": "Maxcellent",
|
1392 |
+
"required_fields": []
|
1393 |
+
},
|
1394 |
+
{
|
1395 |
+
"slug": "mexico-multipack",
|
1396 |
+
"name": "Mexico Multipack",
|
1397 |
+
"other_name": "Fedex Mexico",
|
1398 |
+
"required_fields": []
|
1399 |
+
},
|
1400 |
+
{
|
1401 |
+
"slug": "mexico-redpack",
|
1402 |
+
"name": "Mexico Redpack",
|
1403 |
+
"other_name": "TNT Mexico",
|
1404 |
+
"required_fields": []
|
1405 |
+
},
|
1406 |
+
{
|
1407 |
+
"slug": "mexico-senda-express",
|
1408 |
+
"name": "Mexico Senda Express",
|
1409 |
+
"other_name": "Mexico Senda Express",
|
1410 |
+
"required_fields": []
|
1411 |
+
},
|
1412 |
+
{
|
1413 |
+
"slug": "mikropakket",
|
1414 |
+
"name": "Mikropakket",
|
1415 |
+
"other_name": "",
|
1416 |
+
"required_fields": [
|
1417 |
+
"tracking_postal_code"
|
1418 |
+
]
|
1419 |
+
},
|
1420 |
+
{
|
1421 |
+
"slug": "mondialrelay",
|
1422 |
+
"name": "Mondial Relay",
|
1423 |
+
"other_name": "Mondial Relay France",
|
1424 |
+
"required_fields": [
|
1425 |
+
"tracking_postal_code"
|
1426 |
+
]
|
1427 |
+
},
|
1428 |
+
{
|
1429 |
+
"slug": "mrw-spain",
|
1430 |
+
"name": "MRW",
|
1431 |
+
"other_name": "MRW Spain",
|
1432 |
+
"required_fields": []
|
1433 |
+
},
|
1434 |
+
{
|
1435 |
+
"slug": "myhermes-uk",
|
1436 |
+
"name": "myHermes UK",
|
1437 |
+
"other_name": "",
|
1438 |
+
"required_fields": []
|
1439 |
+
},
|
1440 |
+
{
|
1441 |
+
"slug": "mypostonline",
|
1442 |
+
"name": "Mypostonline",
|
1443 |
+
"other_name": "MYBOXPOST",
|
1444 |
+
"required_fields": []
|
1445 |
+
},
|
1446 |
+
{
|
1447 |
+
"slug": "nacex-spain",
|
1448 |
+
"name": "NACEX Spain",
|
1449 |
+
"other_name": "NACEX Logista",
|
1450 |
+
"required_fields": [
|
1451 |
+
"tracking_postal_code"
|
1452 |
+
]
|
1453 |
+
},
|
1454 |
+
{
|
1455 |
+
"slug": "nanjingwoyuan",
|
1456 |
+
"name": "Nanjing Woyuan",
|
1457 |
+
"other_name": "u6c83u6e90",
|
1458 |
+
"required_fields": []
|
1459 |
+
},
|
1460 |
+
{
|
1461 |
+
"slug": "nationwide-my",
|
1462 |
+
"name": "Nationwide Express",
|
1463 |
+
"other_name": "nationwide2u",
|
1464 |
+
"required_fields": []
|
1465 |
+
},
|
1466 |
+
{
|
1467 |
+
"slug": "new-zealand-post",
|
1468 |
+
"name": "New Zealand Post",
|
1469 |
+
"other_name": "NZ Post",
|
1470 |
+
"required_fields": []
|
1471 |
+
},
|
1472 |
+
{
|
1473 |
+
"slug": "newgistics",
|
1474 |
+
"name": "Newgistics",
|
1475 |
+
"other_name": "",
|
1476 |
+
"required_fields": []
|
1477 |
+
},
|
1478 |
+
{
|
1479 |
+
"slug": "nhans-solutions",
|
1480 |
+
"name": "Nhans Solutions",
|
1481 |
+
"other_name": "Nhans Courier",
|
1482 |
+
"required_fields": []
|
1483 |
+
},
|
1484 |
+
{
|
1485 |
+
"slug": "nightline",
|
1486 |
+
"name": "Nightline",
|
1487 |
+
"other_name": "",
|
1488 |
+
"required_fields": []
|
1489 |
+
},
|
1490 |
+
{
|
1491 |
+
"slug": "ninjavan",
|
1492 |
+
"name": "Ninja Van",
|
1493 |
+
"other_name": "",
|
1494 |
+
"required_fields": []
|
1495 |
+
},
|
1496 |
+
{
|
1497 |
+
"slug": "ninjavan-id",
|
1498 |
+
"name": "Ninja Van Indonesia",
|
1499 |
+
"other_name": "NinjaVan Indonesia",
|
1500 |
+
"required_fields": []
|
1501 |
+
},
|
1502 |
+
{
|
1503 |
+
"slug": "ninjavan-my",
|
1504 |
+
"name": "Ninja Van Malaysia",
|
1505 |
+
"other_name": "NinjaVan MY",
|
1506 |
+
"required_fields": []
|
1507 |
+
},
|
1508 |
+
{
|
1509 |
+
"slug": "nipost",
|
1510 |
+
"name": "NiPost",
|
1511 |
+
"other_name": "Nigerian Postal Service",
|
1512 |
+
"required_fields": []
|
1513 |
+
},
|
1514 |
+
{
|
1515 |
+
"slug": "norsk-global",
|
1516 |
+
"name": "Norsk Global",
|
1517 |
+
"other_name": "Norsk European Wholesale",
|
1518 |
+
"required_fields": []
|
1519 |
+
},
|
1520 |
+
{
|
1521 |
+
"slug": "nova-poshta",
|
1522 |
+
"name": "Nova Poshta",
|
1523 |
+
"other_name": "Новая Почта",
|
1524 |
+
"required_fields": []
|
1525 |
+
},
|
1526 |
+
{
|
1527 |
+
"slug": "nuvoex",
|
1528 |
+
"name": "NuvoEx",
|
1529 |
+
"other_name": "Nuvo Ex",
|
1530 |
+
"required_fields": []
|
1531 |
+
},
|
1532 |
+
{
|
1533 |
+
"slug": "oca-ar",
|
1534 |
+
"name": "OCA Argentina",
|
1535 |
+
"other_name": "OCA e-Pak",
|
1536 |
+
"required_fields": []
|
1537 |
+
},
|
1538 |
+
{
|
1539 |
+
"slug": "old-dominion",
|
1540 |
+
"name": "Old Dominion Freight Line",
|
1541 |
+
"other_name": "ODFL",
|
1542 |
+
"required_fields": []
|
1543 |
+
},
|
1544 |
+
{
|
1545 |
+
"slug": "omniparcel",
|
1546 |
+
"name": "Omni Parcel",
|
1547 |
+
"other_name": "Omni-Channel Logistics (Seko)",
|
1548 |
+
"required_fields": []
|
1549 |
+
},
|
1550 |
+
{
|
1551 |
+
"slug": "oneworldexpress",
|
1552 |
+
"name": "One World Express",
|
1553 |
+
"other_name": "u6613u65f6u9039u7269u6d41",
|
1554 |
+
"required_fields": []
|
1555 |
+
},
|
1556 |
+
{
|
1557 |
+
"slug": "ontrac",
|
1558 |
+
"name": "OnTrac",
|
1559 |
+
"other_name": "OnTrac Shipping",
|
1560 |
+
"required_fields": []
|
1561 |
+
},
|
1562 |
+
{
|
1563 |
+
"slug": "opek",
|
1564 |
+
"name": "FedEx Poland Domestic",
|
1565 |
+
"other_name": "OPEK",
|
1566 |
+
"required_fields": []
|
1567 |
+
},
|
1568 |
+
{
|
1569 |
+
"slug": "packlink",
|
1570 |
+
"name": "Packlink",
|
1571 |
+
"other_name": "Packlink Spain",
|
1572 |
+
"required_fields": []
|
1573 |
+
},
|
1574 |
+
{
|
1575 |
+
"slug": "pandulogistics",
|
1576 |
+
"name": "Pandu Logistics",
|
1577 |
+
"other_name": "",
|
1578 |
+
"required_fields": []
|
1579 |
+
},
|
1580 |
+
{
|
1581 |
+
"slug": "panther",
|
1582 |
+
"name": "Panther",
|
1583 |
+
"other_name": "Panther Group UK",
|
1584 |
+
"required_fields": []
|
1585 |
+
},
|
1586 |
+
{
|
1587 |
+
"slug": "panther-reference",
|
1588 |
+
"name": "Panther Reference",
|
1589 |
+
"other_name": "Panther Group UK",
|
1590 |
+
"required_fields": [
|
1591 |
+
"tracking_account_number"
|
1592 |
+
]
|
1593 |
+
},
|
1594 |
+
{
|
1595 |
+
"slug": "parcel-express",
|
1596 |
+
"name": "Parcel Express",
|
1597 |
+
"other_name": "Parcel Express Pte Ltd",
|
1598 |
+
"required_fields": []
|
1599 |
+
},
|
1600 |
+
{
|
1601 |
+
"slug": "parcel-force",
|
1602 |
+
"name": "Parcel Force",
|
1603 |
+
"other_name": "Parcelforce UK",
|
1604 |
+
"required_fields": []
|
1605 |
+
},
|
1606 |
+
{
|
1607 |
+
"slug": "parcelled-in",
|
1608 |
+
"name": "Parcelled.in",
|
1609 |
+
"other_name": "Parcelled",
|
1610 |
+
"required_fields": []
|
1611 |
+
},
|
1612 |
+
{
|
1613 |
+
"slug": "parcelpost-sg",
|
1614 |
+
"name": "Parcel Post Singapore",
|
1615 |
+
"other_name": "ParcelPost",
|
1616 |
+
"required_fields": []
|
1617 |
+
},
|
1618 |
+
{
|
1619 |
+
"slug": "pfcexpress",
|
1620 |
+
"name": "PFC Express",
|
1621 |
+
"other_name": "PFCu7687u5bb6u7269u6d41",
|
1622 |
+
"required_fields": []
|
1623 |
+
},
|
1624 |
+
{
|
1625 |
+
"slug": "poczta-polska",
|
1626 |
+
"name": "Poczta Polska",
|
1627 |
+
"other_name": "Poland Post",
|
1628 |
+
"required_fields": []
|
1629 |
+
},
|
1630 |
+
{
|
1631 |
+
"slug": "portugal-ctt",
|
1632 |
+
"name": "Portugal CTT",
|
1633 |
+
"other_name": "Correios de Portugal",
|
1634 |
+
"required_fields": []
|
1635 |
+
},
|
1636 |
+
{
|
1637 |
+
"slug": "portugal-seur",
|
1638 |
+
"name": "Portugal Seur",
|
1639 |
+
"other_name": "SEUR",
|
1640 |
+
"required_fields": []
|
1641 |
+
},
|
1642 |
+
{
|
1643 |
+
"slug": "pos-indonesia",
|
1644 |
+
"name": "Pos Indonesia Domestic",
|
1645 |
+
"other_name": "Indonesian Post Domestic",
|
1646 |
+
"required_fields": []
|
1647 |
+
},
|
1648 |
+
{
|
1649 |
+
"slug": "pos-indonesia-int",
|
1650 |
+
"name": "Pos Indonesia Int'l",
|
1651 |
+
"other_name": "Indonesian Post International EMS",
|
1652 |
+
"required_fields": []
|
1653 |
+
},
|
1654 |
+
{
|
1655 |
+
"slug": "post-serbia",
|
1656 |
+
"name": "Post Serbia",
|
1657 |
+
"other_name": "Pou0161ta Srbije",
|
1658 |
+
"required_fields": []
|
1659 |
+
},
|
1660 |
+
{
|
1661 |
+
"slug": "post56",
|
1662 |
+
"name": "Post56",
|
1663 |
+
"other_name": "捷邮快递",
|
1664 |
+
"required_fields": []
|
1665 |
+
},
|
1666 |
+
{
|
1667 |
+
"slug": "posta-romana",
|
1668 |
+
"name": "Poșta Română",
|
1669 |
+
"other_name": "Romania Post",
|
1670 |
+
"required_fields": []
|
1671 |
+
},
|
1672 |
+
{
|
1673 |
+
"slug": "postaplus",
|
1674 |
+
"name": "Posta Plus",
|
1675 |
+
"other_name": "PostaPlus",
|
1676 |
+
"required_fields": []
|
1677 |
+
},
|
1678 |
+
{
|
1679 |
+
"slug": "poste-italiane",
|
1680 |
+
"name": "Poste Italiane",
|
1681 |
+
"other_name": "Italian Post",
|
1682 |
+
"required_fields": []
|
1683 |
+
},
|
1684 |
+
{
|
1685 |
+
"slug": "poste-italiane-paccocelere",
|
1686 |
+
"name": "Poste Italiane Paccocelere",
|
1687 |
+
"other_name": "Italian Post EMS / Express",
|
1688 |
+
"required_fields": []
|
1689 |
+
},
|
1690 |
+
{
|
1691 |
+
"slug": "posten-norge",
|
1692 |
+
"name": "Posten Norge / Bring",
|
1693 |
+
"other_name": "Norway Post, Norska Posten",
|
1694 |
+
"required_fields": []
|
1695 |
+
},
|
1696 |
+
{
|
1697 |
+
"slug": "posti",
|
1698 |
+
"name": "Posti",
|
1699 |
+
"other_name": "Finland Post",
|
1700 |
+
"required_fields": []
|
1701 |
+
},
|
1702 |
+
{
|
1703 |
+
"slug": "postnl",
|
1704 |
+
"name": "PostNL Domestic",
|
1705 |
+
"other_name": "PostNL Pakketten, TNT Post Netherlands",
|
1706 |
+
"required_fields": [
|
1707 |
+
"tracking_postal_code"
|
1708 |
+
]
|
1709 |
+
},
|
1710 |
+
{
|
1711 |
+
"slug": "postnl-3s",
|
1712 |
+
"name": "PostNL International 3S",
|
1713 |
+
"other_name": "TNT Post parcel service United Kingdom",
|
1714 |
+
"required_fields": [
|
1715 |
+
"tracking_destination_country",
|
1716 |
+
"tracking_postal_code"
|
1717 |
+
]
|
1718 |
+
},
|
1719 |
+
{
|
1720 |
+
"slug": "postnl-international",
|
1721 |
+
"name": "PostNL International",
|
1722 |
+
"other_name": "Netherlands Post, Spring Global Mail",
|
1723 |
+
"required_fields": []
|
1724 |
+
},
|
1725 |
+
{
|
1726 |
+
"slug": "postnord",
|
1727 |
+
"name": "PostNord Logistics",
|
1728 |
+
"other_name": "Posten Norden",
|
1729 |
+
"required_fields": []
|
1730 |
+
},
|
1731 |
+
{
|
1732 |
+
"slug": "postur-is",
|
1733 |
+
"name": "Iceland Post",
|
1734 |
+
"other_name": "Postur.is, Íslandspóstur",
|
1735 |
+
"required_fields": []
|
1736 |
+
},
|
1737 |
+
{
|
1738 |
+
"slug": "ppbyb",
|
1739 |
+
"name": "PayPal Package",
|
1740 |
+
"other_name": "贝邮宝",
|
1741 |
+
"required_fields": []
|
1742 |
+
},
|
1743 |
+
{
|
1744 |
+
"slug": "professional-couriers",
|
1745 |
+
"name": "Professional Couriers",
|
1746 |
+
"other_name": "TPC India",
|
1747 |
+
"required_fields": []
|
1748 |
+
},
|
1749 |
+
{
|
1750 |
+
"slug": "ptt-posta",
|
1751 |
+
"name": "PTT Posta",
|
1752 |
+
"other_name": "Turkish Post",
|
1753 |
+
"required_fields": []
|
1754 |
+
},
|
1755 |
+
{
|
1756 |
+
"slug": "purolator",
|
1757 |
+
"name": "Purolator",
|
1758 |
+
"other_name": "Purolator Freight",
|
1759 |
+
"required_fields": []
|
1760 |
+
},
|
1761 |
+
{
|
1762 |
+
"slug": "quantium",
|
1763 |
+
"name": "Quantium",
|
1764 |
+
"other_name": "u51a0u5eadu7269u6d41",
|
1765 |
+
"required_fields": []
|
1766 |
+
},
|
1767 |
+
{
|
1768 |
+
"slug": "qxpress",
|
1769 |
+
"name": "Qxpress",
|
1770 |
+
"other_name": "Qxpress Qoo10",
|
1771 |
+
"required_fields": []
|
1772 |
+
},
|
1773 |
+
{
|
1774 |
+
"slug": "raben-group",
|
1775 |
+
"name": "Raben Group",
|
1776 |
+
"other_name": "myRaben",
|
1777 |
+
"required_fields": []
|
1778 |
+
},
|
1779 |
+
{
|
1780 |
+
"slug": "raf",
|
1781 |
+
"name": "RAF Philippines",
|
1782 |
+
"other_name": "RAF Int'l. Forwarding",
|
1783 |
+
"required_fields": []
|
1784 |
+
},
|
1785 |
+
{
|
1786 |
+
"slug": "raiderex",
|
1787 |
+
"name": "RaidereX",
|
1788 |
+
"other_name": "Detrack",
|
1789 |
+
"required_fields": []
|
1790 |
+
},
|
1791 |
+
{
|
1792 |
+
"slug": "ramgroup-za",
|
1793 |
+
"name": "RAM",
|
1794 |
+
"other_name": "RAM Group",
|
1795 |
+
"required_fields": []
|
1796 |
+
},
|
1797 |
+
{
|
1798 |
+
"slug": "red-express",
|
1799 |
+
"name": "Red Express",
|
1800 |
+
"other_name": "Red Express",
|
1801 |
+
"required_fields": []
|
1802 |
+
},
|
1803 |
+
{
|
1804 |
+
"slug": "red-express-wb",
|
1805 |
+
"name": "Red Express Waybill",
|
1806 |
+
"other_name": "Red Express WayBill",
|
1807 |
+
"required_fields": []
|
1808 |
+
},
|
1809 |
+
{
|
1810 |
+
"slug": "redur-es",
|
1811 |
+
"name": "Redur Spain",
|
1812 |
+
"other_name": "Eurodis",
|
1813 |
+
"required_fields": []
|
1814 |
+
},
|
1815 |
+
{
|
1816 |
+
"slug": "rl-carriers",
|
1817 |
+
"name": "RL Carriers",
|
1818 |
+
"other_name": "R+L Carriers",
|
1819 |
+
"required_fields": []
|
1820 |
+
},
|
1821 |
+
{
|
1822 |
+
"slug": "roadbull",
|
1823 |
+
"name": "Roadbull Logistics",
|
1824 |
+
"other_name": "Roadbull Logistics Pte Ltd",
|
1825 |
+
"required_fields": []
|
1826 |
+
},
|
1827 |
+
{
|
1828 |
+
"slug": "rocketparcel",
|
1829 |
+
"name": "Rocket Parcel International",
|
1830 |
+
"other_name": "",
|
1831 |
+
"required_fields": []
|
1832 |
+
},
|
1833 |
+
{
|
1834 |
+
"slug": "royal-mail",
|
1835 |
+
"name": "Royal Mail",
|
1836 |
+
"other_name": "Royal Mail United Kingdom",
|
1837 |
+
"required_fields": []
|
1838 |
+
},
|
1839 |
+
{
|
1840 |
+
"slug": "rpd2man",
|
1841 |
+
"name": "RPD2man Deliveries",
|
1842 |
+
"other_name": "RPD-2man",
|
1843 |
+
"required_fields": []
|
1844 |
+
},
|
1845 |
+
{
|
1846 |
+
"slug": "rpx",
|
1847 |
+
"name": "RPX Indonesia",
|
1848 |
+
"other_name": "Repex Perdana International",
|
1849 |
+
"required_fields": []
|
1850 |
+
},
|
1851 |
+
{
|
1852 |
+
"slug": "rpxonline",
|
1853 |
+
"name": "RPX Online",
|
1854 |
+
"other_name": "Cathay Pacific",
|
1855 |
+
"required_fields": []
|
1856 |
+
},
|
1857 |
+
{
|
1858 |
+
"slug": "rrdonnelley",
|
1859 |
+
"name": "RR Donnelley",
|
1860 |
+
"other_name": "RRD",
|
1861 |
+
"required_fields": []
|
1862 |
+
},
|
1863 |
+
{
|
1864 |
+
"slug": "russian-post",
|
1865 |
+
"name": "Russian Post",
|
1866 |
+
"other_name": "Почта России, EMS Post RU",
|
1867 |
+
"required_fields": []
|
1868 |
+
},
|
1869 |
+
{
|
1870 |
+
"slug": "ruston",
|
1871 |
+
"name": "Ruston",
|
1872 |
+
"other_name": "",
|
1873 |
+
"required_fields": []
|
1874 |
+
},
|
1875 |
+
{
|
1876 |
+
"slug": "rzyexpress",
|
1877 |
+
"name": "RZY Express",
|
1878 |
+
"other_name": "RZYExpress",
|
1879 |
+
"required_fields": []
|
1880 |
+
},
|
1881 |
+
{
|
1882 |
+
"slug": "safexpress",
|
1883 |
+
"name": "Safexpress",
|
1884 |
+
"other_name": "Safexpress",
|
1885 |
+
"required_fields": []
|
1886 |
+
},
|
1887 |
+
{
|
1888 |
+
"slug": "sagawa",
|
1889 |
+
"name": "Sagawa",
|
1890 |
+
"other_name": "佐川急便",
|
1891 |
+
"required_fields": []
|
1892 |
+
},
|
1893 |
+
{
|
1894 |
+
"slug": "sapo",
|
1895 |
+
"name": "South African Post Office",
|
1896 |
+
"other_name": "South African Post Office",
|
1897 |
+
"required_fields": []
|
1898 |
+
},
|
1899 |
+
{
|
1900 |
+
"slug": "saudi-post",
|
1901 |
+
"name": "Saudi Post",
|
1902 |
+
"other_name": "البريد السعودي",
|
1903 |
+
"required_fields": []
|
1904 |
+
},
|
1905 |
+
{
|
1906 |
+
"slug": "scudex-express",
|
1907 |
+
"name": "Scudex Express",
|
1908 |
+
"other_name": "",
|
1909 |
+
"required_fields": []
|
1910 |
+
},
|
1911 |
+
{
|
1912 |
+
"slug": "sekologistics",
|
1913 |
+
"name": "SEKO Logistics",
|
1914 |
+
"other_name": "SEKO",
|
1915 |
+
"required_fields": []
|
1916 |
+
},
|
1917 |
+
{
|
1918 |
+
"slug": "selektvracht",
|
1919 |
+
"name": "Selektvracht",
|
1920 |
+
"other_name": "Selektvracht NL",
|
1921 |
+
"required_fields": []
|
1922 |
+
},
|
1923 |
+
{
|
1924 |
+
"slug": "sendit",
|
1925 |
+
"name": "Sendit",
|
1926 |
+
"other_name": "",
|
1927 |
+
"required_fields": []
|
1928 |
+
},
|
1929 |
+
{
|
1930 |
+
"slug": "sendle",
|
1931 |
+
"name": "Sendle",
|
1932 |
+
"other_name": "",
|
1933 |
+
"required_fields": []
|
1934 |
+
},
|
1935 |
+
{
|
1936 |
+
"slug": "sf-express",
|
1937 |
+
"name": "S.F. Express",
|
1938 |
+
"other_name": "順豊快遞, SF",
|
1939 |
+
"required_fields": []
|
1940 |
+
},
|
1941 |
+
{
|
1942 |
+
"slug": "sfb2c",
|
1943 |
+
"name": "S.F International",
|
1944 |
+
"other_name": "順豐國際",
|
1945 |
+
"required_fields": []
|
1946 |
+
},
|
1947 |
+
{
|
1948 |
+
"slug": "sfcservice",
|
1949 |
+
"name": "SFC Service",
|
1950 |
+
"other_name": "u6df1u5733u4e09u6001u56fdu9645u901fu9012",
|
1951 |
+
"required_fields": []
|
1952 |
+
},
|
1953 |
+
{
|
1954 |
+
"slug": "sgt-it",
|
1955 |
+
"name": "SGT Corriere Espresso",
|
1956 |
+
"other_name": "SoGeTras Corriere Espresso",
|
1957 |
+
"required_fields": []
|
1958 |
+
},
|
1959 |
+
{
|
1960 |
+
"slug": "sic-teliway",
|
1961 |
+
"name": "Teliway SIC Express",
|
1962 |
+
"other_name": "Prevote",
|
1963 |
+
"required_fields": [
|
1964 |
+
"tracking_account_number",
|
1965 |
+
"tracking_key"
|
1966 |
+
]
|
1967 |
+
},
|
1968 |
+
{
|
1969 |
+
"slug": "simplypost",
|
1970 |
+
"name": "SimplyPost",
|
1971 |
+
"other_name": "",
|
1972 |
+
"required_fields": []
|
1973 |
+
},
|
1974 |
+
{
|
1975 |
+
"slug": "singapore-post",
|
1976 |
+
"name": "Singapore Post",
|
1977 |
+
"other_name": "SingPost",
|
1978 |
+
"required_fields": []
|
1979 |
+
},
|
1980 |
+
{
|
1981 |
+
"slug": "singapore-speedpost",
|
1982 |
+
"name": "Singapore Speedpost",
|
1983 |
+
"other_name": "Singapore EMS",
|
1984 |
+
"required_fields": []
|
1985 |
+
},
|
1986 |
+
{
|
1987 |
+
"slug": "singparcel",
|
1988 |
+
"name": "SingParcel Service",
|
1989 |
+
"other_name": "SPS",
|
1990 |
+
"required_fields": []
|
1991 |
+
},
|
1992 |
+
{
|
1993 |
+
"slug": "siodemka",
|
1994 |
+
"name": "Siodemka",
|
1995 |
+
"other_name": "Siodemka Kurier",
|
1996 |
+
"required_fields": []
|
1997 |
+
},
|
1998 |
+
{
|
1999 |
+
"slug": "skynet",
|
2000 |
+
"name": "SkyNet Malaysia",
|
2001 |
+
"other_name": "SkyNet MY",
|
2002 |
+
"required_fields": []
|
2003 |
+
},
|
2004 |
+
{
|
2005 |
+
"slug": "skynetworldwide",
|
2006 |
+
"name": "SkyNet Worldwide Express",
|
2007 |
+
"other_name": "Skynetwwe",
|
2008 |
+
"required_fields": []
|
2009 |
+
},
|
2010 |
+
{
|
2011 |
+
"slug": "skynetworldwide-uk",
|
2012 |
+
"name": "Skynet Worldwide Express UK",
|
2013 |
+
"other_name": "Skynet UK",
|
2014 |
+
"required_fields": []
|
2015 |
+
},
|
2016 |
+
{
|
2017 |
+
"slug": "skypostal",
|
2018 |
+
"name": "Asendia HK (LATAM)",
|
2019 |
+
"other_name": "SkyPostal (Postrac)",
|
2020 |
+
"required_fields": []
|
2021 |
+
},
|
2022 |
+
{
|
2023 |
+
"slug": "smsa-express",
|
2024 |
+
"name": "SMSA Express",
|
2025 |
+
"other_name": "",
|
2026 |
+
"required_fields": []
|
2027 |
+
},
|
2028 |
+
{
|
2029 |
+
"slug": "spain-correos-es",
|
2030 |
+
"name": "Correos de España",
|
2031 |
+
"other_name": "Spain Post, ChronoExpress",
|
2032 |
+
"required_fields": []
|
2033 |
+
},
|
2034 |
+
{
|
2035 |
+
"slug": "spanish-seur",
|
2036 |
+
"name": "Spanish Seur",
|
2037 |
+
"other_name": "SEUR",
|
2038 |
+
"required_fields": []
|
2039 |
+
},
|
2040 |
+
{
|
2041 |
+
"slug": "specialisedfreight-za",
|
2042 |
+
"name": "Specialised Freight",
|
2043 |
+
"other_name": "SFS",
|
2044 |
+
"required_fields": []
|
2045 |
+
},
|
2046 |
+
{
|
2047 |
+
"slug": "speedcouriers-gr",
|
2048 |
+
"name": "Speed Couriers",
|
2049 |
+
"other_name": "Speed Couriers",
|
2050 |
+
"required_fields": []
|
2051 |
+
},
|
2052 |
+
{
|
2053 |
+
"slug": "speedexcourier",
|
2054 |
+
"name": "Speedex Courier",
|
2055 |
+
"other_name": "Speedex Courier",
|
2056 |
+
"required_fields": []
|
2057 |
+
},
|
2058 |
+
{
|
2059 |
+
"slug": "spreadcourier",
|
2060 |
+
"name": "SpreadCourier",
|
2061 |
+
"other_name": "",
|
2062 |
+
"required_fields": []
|
2063 |
+
},
|
2064 |
+
{
|
2065 |
+
"slug": "spreadel",
|
2066 |
+
"name": "Spreadel",
|
2067 |
+
"other_name": "Jabong delivery",
|
2068 |
+
"required_fields": []
|
2069 |
+
},
|
2070 |
+
{
|
2071 |
+
"slug": "srekorea",
|
2072 |
+
"name": "SRE Korea",
|
2073 |
+
"other_name": "SRE 배송서비스",
|
2074 |
+
"required_fields": []
|
2075 |
+
},
|
2076 |
+
{
|
2077 |
+
"slug": "star-track",
|
2078 |
+
"name": "StarTrack",
|
2079 |
+
"other_name": "Star Track",
|
2080 |
+
"required_fields": []
|
2081 |
+
},
|
2082 |
+
{
|
2083 |
+
"slug": "star-track-express",
|
2084 |
+
"name": "Star Track Express",
|
2085 |
+
"other_name": "AaE Australian air Express",
|
2086 |
+
"required_fields": []
|
2087 |
+
},
|
2088 |
+
{
|
2089 |
+
"slug": "sto",
|
2090 |
+
"name": "STO Express",
|
2091 |
+
"other_name": "申通快递, Shentong Express",
|
2092 |
+
"required_fields": []
|
2093 |
+
},
|
2094 |
+
{
|
2095 |
+
"slug": "sweden-posten",
|
2096 |
+
"name": "PostNord Sweden",
|
2097 |
+
"other_name": "Sweden Post, Posten, Sweden Posten",
|
2098 |
+
"required_fields": []
|
2099 |
+
},
|
2100 |
+
{
|
2101 |
+
"slug": "swiss-post",
|
2102 |
+
"name": "Swiss Post",
|
2103 |
+
"other_name": "La Poste Suisse, Die Schweizerische Post, Die Post",
|
2104 |
+
"required_fields": []
|
2105 |
+
},
|
2106 |
+
{
|
2107 |
+
"slug": "szdpex",
|
2108 |
+
"name": "DPEX China",
|
2109 |
+
"other_name": "DPEX(深圳)国际物流, Toll China",
|
2110 |
+
"required_fields": []
|
2111 |
+
},
|
2112 |
+
{
|
2113 |
+
"slug": "taiwan-post",
|
2114 |
+
"name": "Taiwan Post",
|
2115 |
+
"other_name": "Chunghwa Post, 台灣中華郵政",
|
2116 |
+
"required_fields": []
|
2117 |
+
},
|
2118 |
+
{
|
2119 |
+
"slug": "taqbin-hk",
|
2120 |
+
"name": "TAQBIN Hong Kong",
|
2121 |
+
"other_name": "Yamat, 雅瑪多運輸- 宅急便",
|
2122 |
+
"required_fields": []
|
2123 |
+
},
|
2124 |
+
{
|
2125 |
+
"slug": "taqbin-jp",
|
2126 |
+
"name": "Yamato Japan",
|
2127 |
+
"other_name": "ヤマト運輸, TAQBIN",
|
2128 |
+
"required_fields": []
|
2129 |
+
},
|
2130 |
+
{
|
2131 |
+
"slug": "taqbin-my",
|
2132 |
+
"name": "TAQBIN Malaysia",
|
2133 |
+
"other_name": "TAQBIN Malaysia",
|
2134 |
+
"required_fields": []
|
2135 |
+
},
|
2136 |
+
{
|
2137 |
+
"slug": "taqbin-sg",
|
2138 |
+
"name": "TAQBIN Singapore",
|
2139 |
+
"other_name": "Yamato Singapore",
|
2140 |
+
"required_fields": []
|
2141 |
+
},
|
2142 |
+
{
|
2143 |
+
"slug": "taxydromiki",
|
2144 |
+
"name": "Geniki Taxydromiki",
|
2145 |
+
"other_name": "ΓΕΝΙΚΗ ΤΑΧΥΔΡΟΜΙΚΗ",
|
2146 |
+
"required_fields": []
|
2147 |
+
},
|
2148 |
+
{
|
2149 |
+
"slug": "tcs",
|
2150 |
+
"name": "TCS",
|
2151 |
+
"other_name": "TCS",
|
2152 |
+
"required_fields": []
|
2153 |
+
},
|
2154 |
+
{
|
2155 |
+
"slug": "tgx",
|
2156 |
+
"name": "Kerry Express Hong Kong",
|
2157 |
+
"other_name": "Top Gun Express, 精英速運, TGX",
|
2158 |
+
"required_fields": []
|
2159 |
+
},
|
2160 |
+
{
|
2161 |
+
"slug": "thailand-post",
|
2162 |
+
"name": "Thailand Thai Post",
|
2163 |
+
"other_name": "ไปรษณีย์ไทย",
|
2164 |
+
"required_fields": []
|
2165 |
+
},
|
2166 |
+
{
|
2167 |
+
"slug": "thecourierguy",
|
2168 |
+
"name": "The Courier Guy",
|
2169 |
+
"other_name": "TheCourierGuy",
|
2170 |
+
"required_fields": []
|
2171 |
+
},
|
2172 |
+
{
|
2173 |
+
"slug": "tiki",
|
2174 |
+
"name": "Tiki",
|
2175 |
+
"other_name": "Citra Van Titipan Kilat",
|
2176 |
+
"required_fields": []
|
2177 |
+
},
|
2178 |
+
{
|
2179 |
+
"slug": "tnt",
|
2180 |
+
"name": "TNT",
|
2181 |
+
"other_name": "TNT Express",
|
2182 |
+
"required_fields": []
|
2183 |
+
},
|
2184 |
+
{
|
2185 |
+
"slug": "tnt-au",
|
2186 |
+
"name": "TNT Australia",
|
2187 |
+
"other_name": "TNT AU",
|
2188 |
+
"required_fields": []
|
2189 |
+
},
|
2190 |
+
{
|
2191 |
+
"slug": "tnt-click",
|
2192 |
+
"name": "TNT-Click Italy",
|
2193 |
+
"other_name": "TNT Italy",
|
2194 |
+
"required_fields": []
|
2195 |
+
},
|
2196 |
+
{
|
2197 |
+
"slug": "tnt-fr",
|
2198 |
+
"name": "TNT France",
|
2199 |
+
"other_name": "TNT Express FR",
|
2200 |
+
"required_fields": []
|
2201 |
+
},
|
2202 |
+
{
|
2203 |
+
"slug": "tnt-it",
|
2204 |
+
"name": "TNT Italy",
|
2205 |
+
"other_name": "TNT Express IT",
|
2206 |
+
"required_fields": []
|
2207 |
+
},
|
2208 |
+
{
|
2209 |
+
"slug": "tnt-reference",
|
2210 |
+
"name": "TNT Reference",
|
2211 |
+
"other_name": "TNT consignment reference",
|
2212 |
+
"required_fields": []
|
2213 |
+
},
|
2214 |
+
{
|
2215 |
+
"slug": "tnt-uk",
|
2216 |
+
"name": "TNT UK",
|
2217 |
+
"other_name": "TNT United Kingdom",
|
2218 |
+
"required_fields": []
|
2219 |
+
},
|
2220 |
+
{
|
2221 |
+
"slug": "tnt-uk-reference",
|
2222 |
+
"name": "TNT UK Reference",
|
2223 |
+
"other_name": "TNT UK consignment reference",
|
2224 |
+
"required_fields": []
|
2225 |
+
},
|
2226 |
+
{
|
2227 |
+
"slug": "tntpost-it",
|
2228 |
+
"name": "Nexive (TNT Post Italy)",
|
2229 |
+
"other_name": "Postnl TNT",
|
2230 |
+
"required_fields": []
|
2231 |
+
},
|
2232 |
+
{
|
2233 |
+
"slug": "toll-global-express",
|
2234 |
+
"name": "Toll Global Express",
|
2235 |
+
"other_name": "DPEX",
|
2236 |
+
"required_fields": []
|
2237 |
+
},
|
2238 |
+
{
|
2239 |
+
"slug": "toll-ipec",
|
2240 |
+
"name": "Toll IPEC",
|
2241 |
+
"other_name": "Toll Express",
|
2242 |
+
"required_fields": []
|
2243 |
+
},
|
2244 |
+
{
|
2245 |
+
"slug": "toll-priority",
|
2246 |
+
"name": "Toll Priority",
|
2247 |
+
"other_name": "Toll Group, Toll Priority",
|
2248 |
+
"required_fields": []
|
2249 |
+
},
|
2250 |
+
{
|
2251 |
+
"slug": "trakpak",
|
2252 |
+
"name": "TrakPak",
|
2253 |
+
"other_name": "bpost international P2P Mailing Trak Pak",
|
2254 |
+
"required_fields": []
|
2255 |
+
},
|
2256 |
+
{
|
2257 |
+
"slug": "transmission-nl",
|
2258 |
+
"name": "TransMission",
|
2259 |
+
"other_name": "mijnzending",
|
2260 |
+
"required_fields": [
|
2261 |
+
"tracking_postal_code"
|
2262 |
+
]
|
2263 |
+
},
|
2264 |
+
{
|
2265 |
+
"slug": "tuffnells",
|
2266 |
+
"name": "Tuffnells Parcels Express",
|
2267 |
+
"other_name": "",
|
2268 |
+
"required_fields": [
|
2269 |
+
"tracking_account_number"
|
2270 |
+
]
|
2271 |
+
},
|
2272 |
+
{
|
2273 |
+
"slug": "ubi-logistics",
|
2274 |
+
"name": "UBI Logistics Australia",
|
2275 |
+
"other_name": "",
|
2276 |
+
"required_fields": []
|
2277 |
+
},
|
2278 |
+
{
|
2279 |
+
"slug": "uk-mail",
|
2280 |
+
"name": "UK Mail",
|
2281 |
+
"other_name": "Business Post Group",
|
2282 |
+
"required_fields": []
|
2283 |
+
},
|
2284 |
+
{
|
2285 |
+
"slug": "ukrposhta",
|
2286 |
+
"name": "UkrPoshta",
|
2287 |
+
"other_name": "Укрпошта",
|
2288 |
+
"required_fields": []
|
2289 |
+
},
|
2290 |
+
{
|
2291 |
+
"slug": "ups",
|
2292 |
+
"name": "UPS",
|
2293 |
+
"other_name": "United Parcel Service",
|
2294 |
+
"required_fields": []
|
2295 |
+
},
|
2296 |
+
{
|
2297 |
+
"slug": "ups-freight",
|
2298 |
+
"name": "UPS Freight",
|
2299 |
+
"other_name": "UPS LTL and Truckload",
|
2300 |
+
"required_fields": []
|
2301 |
+
},
|
2302 |
+
{
|
2303 |
+
"slug": "ups-mi",
|
2304 |
+
"name": "UPS Mail Innovations",
|
2305 |
+
"other_name": "UPS MI",
|
2306 |
+
"required_fields": []
|
2307 |
+
},
|
2308 |
+
{
|
2309 |
+
"slug": "usps",
|
2310 |
+
"name": "USPS",
|
2311 |
+
"other_name": "United States Postal Service",
|
2312 |
+
"required_fields": []
|
2313 |
+
},
|
2314 |
+
{
|
2315 |
+
"slug": "viettelpost",
|
2316 |
+
"name": "ViettelPost",
|
2317 |
+
"other_name": "Bưu chính Viettel",
|
2318 |
+
"required_fields": []
|
2319 |
+
},
|
2320 |
+
{
|
2321 |
+
"slug": "vnpost",
|
2322 |
+
"name": "Vietnam Post",
|
2323 |
+
"other_name": "VNPost",
|
2324 |
+
"required_fields": []
|
2325 |
+
},
|
2326 |
+
{
|
2327 |
+
"slug": "vnpost-ems",
|
2328 |
+
"name": "Vietnam Post EMS",
|
2329 |
+
"other_name": "VNPost EMS",
|
2330 |
+
"required_fields": []
|
2331 |
+
},
|
2332 |
+
{
|
2333 |
+
"slug": "vtfe",
|
2334 |
+
"name": "VicTas Freight Express",
|
2335 |
+
"other_name": "VTFE",
|
2336 |
+
"required_fields": []
|
2337 |
+
},
|
2338 |
+
{
|
2339 |
+
"slug": "wahana",
|
2340 |
+
"name": "Wahana",
|
2341 |
+
"other_name": "Wahana Indonesia",
|
2342 |
+
"required_fields": []
|
2343 |
+
},
|
2344 |
+
{
|
2345 |
+
"slug": "wanbexpress",
|
2346 |
+
"name": "WanbExpress",
|
2347 |
+
"other_name": "",
|
2348 |
+
"required_fields": []
|
2349 |
+
},
|
2350 |
+
{
|
2351 |
+
"slug": "wedo",
|
2352 |
+
"name": "WeDo Logistics",
|
2353 |
+
"other_name": "運德物流",
|
2354 |
+
"required_fields": []
|
2355 |
+
},
|
2356 |
+
{
|
2357 |
+
"slug": "wise-express",
|
2358 |
+
"name": "Wise Express",
|
2359 |
+
"other_name": "u4e07u8272u901fu9012",
|
2360 |
+
"required_fields": []
|
2361 |
+
},
|
2362 |
+
{
|
2363 |
+
"slug": "wiseloads",
|
2364 |
+
"name": "Wiseloads",
|
2365 |
+
"other_name": "",
|
2366 |
+
"required_fields": []
|
2367 |
+
},
|
2368 |
+
{
|
2369 |
+
"slug": "wishpost",
|
2370 |
+
"name": "WishPost",
|
2371 |
+
"other_name": "Wish",
|
2372 |
+
"required_fields": []
|
2373 |
+
},
|
2374 |
+
{
|
2375 |
+
"slug": "wndirect",
|
2376 |
+
"name": "wnDirect",
|
2377 |
+
"other_name": "",
|
2378 |
+
"required_fields": []
|
2379 |
+
},
|
2380 |
+
{
|
2381 |
+
"slug": "xdp-uk",
|
2382 |
+
"name": "XDP Express",
|
2383 |
+
"other_name": "XDP UK",
|
2384 |
+
"required_fields": [
|
2385 |
+
"tracking_postal_code"
|
2386 |
+
]
|
2387 |
+
},
|
2388 |
+
{
|
2389 |
+
"slug": "xdp-uk-reference",
|
2390 |
+
"name": "XDP Express Reference",
|
2391 |
+
"other_name": "XDP UK",
|
2392 |
+
"required_fields": [
|
2393 |
+
"tracking_postal_code"
|
2394 |
+
]
|
2395 |
+
},
|
2396 |
+
{
|
2397 |
+
"slug": "xend",
|
2398 |
+
"name": "Xend Express",
|
2399 |
+
"other_name": "Xend Business Solutions",
|
2400 |
+
"required_fields": []
|
2401 |
+
},
|
2402 |
+
{
|
2403 |
+
"slug": "xl-express",
|
2404 |
+
"name": "XL Express",
|
2405 |
+
"other_name": "",
|
2406 |
+
"required_fields": []
|
2407 |
+
},
|
2408 |
+
{
|
2409 |
+
"slug": "xpressbees",
|
2410 |
+
"name": "XpressBees",
|
2411 |
+
"other_name": "XpressBees logistics",
|
2412 |
+
"required_fields": []
|
2413 |
+
},
|
2414 |
+
{
|
2415 |
+
"slug": "xq-express",
|
2416 |
+
"name": "XQ Express",
|
2417 |
+
"other_name": "u661fu4e7eu7269u6d41",
|
2418 |
+
"required_fields": []
|
2419 |
+
},
|
2420 |
+
{
|
2421 |
+
"slug": "yakit",
|
2422 |
+
"name": "Yakit",
|
2423 |
+
"other_name": "",
|
2424 |
+
"required_fields": []
|
2425 |
+
},
|
2426 |
+
{
|
2427 |
+
"slug": "yanwen",
|
2428 |
+
"name": "Yanwen",
|
2429 |
+
"other_name": "燕文物流",
|
2430 |
+
"required_fields": []
|
2431 |
+
},
|
2432 |
+
{
|
2433 |
+
"slug": "yodel",
|
2434 |
+
"name": "Yodel Domestic",
|
2435 |
+
"other_name": "Home Delivery Network Limited (HDNL)",
|
2436 |
+
"required_fields": []
|
2437 |
+
},
|
2438 |
+
{
|
2439 |
+
"slug": "yodel-international",
|
2440 |
+
"name": "Yodel International",
|
2441 |
+
"other_name": "Home Delivery Network, HDNL",
|
2442 |
+
"required_fields": []
|
2443 |
+
},
|
2444 |
+
{
|
2445 |
+
"slug": "yrc",
|
2446 |
+
"name": "YRC",
|
2447 |
+
"other_name": "YRC Freight",
|
2448 |
+
"required_fields": []
|
2449 |
+
},
|
2450 |
+
{
|
2451 |
+
"slug": "yto",
|
2452 |
+
"name": "YTO Express",
|
2453 |
+
"other_name": "u5706u901au901fu9012",
|
2454 |
+
"required_fields": []
|
2455 |
+
},
|
2456 |
+
{
|
2457 |
+
"slug": "yundaex",
|
2458 |
+
"name": "Yunda Express",
|
2459 |
+
"other_name": "韵达快递",
|
2460 |
+
"required_fields": []
|
2461 |
+
},
|
2462 |
+
{
|
2463 |
+
"slug": "yunexpress",
|
2464 |
+
"name": "Yun Express",
|
2465 |
+
"other_name": "云途物流",
|
2466 |
+
"required_fields": []
|
2467 |
+
},
|
2468 |
+
{
|
2469 |
+
"slug": "zalora-7-eleven",
|
2470 |
+
"name": "Zalora 7-Eleven",
|
2471 |
+
"other_name": "7-11",
|
2472 |
+
"required_fields": []
|
2473 |
+
},
|
2474 |
+
{
|
2475 |
+
"slug": "zjs-express",
|
2476 |
+
"name": "ZJS International",
|
2477 |
+
"other_name": "宅急送快運",
|
2478 |
+
"required_fields": []
|
2479 |
+
},
|
2480 |
+
{
|
2481 |
+
"slug": "zyllem",
|
2482 |
+
"name": "Zyllem",
|
2483 |
+
"other_name": "RocketUncle",
|
2484 |
+
"required_fields": []
|
2485 |
+
},
|
2486 |
+
{
|
2487 |
+
"slug": "tipsa",
|
2488 |
+
"name": "TIPSA",
|
2489 |
+
"other_name": "",
|
2490 |
+
"required_fields": []
|
2491 |
+
}
|
2492 |
+
];
|
2493 |
+
return data;
|
2494 |
+
}
|
trunk/assets/js/footer.js
ADDED
@@ -0,0 +1 @@
|
|
|
1 |
+
aftership_woocommerce_tracking_onload();
|
trunk/assets/js/setting.js
ADDED
@@ -0,0 +1,72 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
jQuery(function () {
|
2 |
+
function set_aftership_tracking_provider(selected_couriers) {
|
3 |
+
var couriers = sort_couriers(get_couriers());
|
4 |
+
|
5 |
+
// console.log(couriers);
|
6 |
+
|
7 |
+
jQuery.each(couriers, function (key, courier) {
|
8 |
+
// console.log(courier.name);
|
9 |
+
var str = '<option ';
|
10 |
+
str += 'value="' + courier['slug'] + '" ';
|
11 |
+
if (selected_couriers.hasOwnProperty(courier['slug'])) {
|
12 |
+
str += 'selected="selected"';
|
13 |
+
}
|
14 |
+
str += '>' + courier['name'] + '</option>';
|
15 |
+
jQuery('#couriers_select').append(str);
|
16 |
+
});
|
17 |
+
|
18 |
+
jQuery('#couriers_select').val(selected_couriers);
|
19 |
+
jQuery('#couriers_select').chosen();
|
20 |
+
jQuery('#couriers_select').trigger('chosen:updated');
|
21 |
+
}
|
22 |
+
|
23 |
+
function set_track_message_demo(){
|
24 |
+
jQuery('#track_message_demo_1').html(
|
25 |
+
jQuery('#track_message_1').val() + 'UPS' +
|
26 |
+
'<br/>'+
|
27 |
+
jQuery('#track_message_2').val() + '1Z0X118A0324011613'
|
28 |
+
);
|
29 |
+
}
|
30 |
+
|
31 |
+
jQuery('#couriers_select').change(function () {
|
32 |
+
var couriers_select = jQuery('#couriers_select').val();
|
33 |
+
var value = (couriers_select) ? couriers_select.join(',') : '';
|
34 |
+
jQuery('#couriers').val(value);
|
35 |
+
});
|
36 |
+
|
37 |
+
jQuery('#plugin').change(function () {
|
38 |
+
if (jQuery(this).val() == 'aftership') {
|
39 |
+
jQuery('#couriers').parent().parent().show();
|
40 |
+
jQuery('#track_message_demo_1').parent().parent().show();
|
41 |
+
} else {
|
42 |
+
jQuery('#couriers').parent().parent().hide();
|
43 |
+
jQuery('#track_message_demo_1').parent().parent().hide();
|
44 |
+
}
|
45 |
+
});
|
46 |
+
|
47 |
+
if (jQuery('#couriers')) {
|
48 |
+
var couriers_select = jQuery('#couriers').val();
|
49 |
+
var couriers_select_array = (couriers_select) ? couriers_select.split(',') : [];
|
50 |
+
set_aftership_tracking_provider(couriers_select_array);
|
51 |
+
|
52 |
+
if (jQuery('#plugin').val() != 'aftership') {
|
53 |
+
jQuery('#couriers').parent().parent().hide();
|
54 |
+
}
|
55 |
+
}
|
56 |
+
|
57 |
+
if (jQuery('#track_message_demo_1')) {
|
58 |
+
set_track_message_demo();
|
59 |
+
|
60 |
+
if (jQuery('#plugin').val() != 'aftership') {
|
61 |
+
jQuery('#track_message_demo_1').parent().parent().hide();
|
62 |
+
}
|
63 |
+
}
|
64 |
+
|
65 |
+
jQuery('#track_message_1').keyup(function () {
|
66 |
+
set_track_message_demo();
|
67 |
+
});
|
68 |
+
|
69 |
+
jQuery('#track_message_2').keyup(function () {
|
70 |
+
set_track_message_demo();
|
71 |
+
});
|
72 |
+
});
|
trunk/assets/js/util.js
ADDED
@@ -0,0 +1,18 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
function sort_couriers(data){
|
2 |
+
var n = data.length;
|
3 |
+
for (var i = 0; i < n - 1; i++) {
|
4 |
+
var find = false;
|
5 |
+
for (var j = i+1; j < n; j++) {
|
6 |
+
if (data[i].name.toLowerCase() > data[j].name.toLowerCase()) {
|
7 |
+
var tmp = data[i];
|
8 |
+
data[i] = data[j];
|
9 |
+
data[j] = tmp;
|
10 |
+
find = true;
|
11 |
+
}
|
12 |
+
}
|
13 |
+
if (!find) {
|
14 |
+
break;
|
15 |
+
}
|
16 |
+
}
|
17 |
+
return data;
|
18 |
+
}
|
trunk/assets/plugin/chosen/chosen-sprite.png
ADDED
Binary file
|
trunk/assets/plugin/chosen/chosen-sprite@2x.png
ADDED
Binary file
|
trunk/assets/plugin/chosen/chosen.jquery.min.js
ADDED
@@ -0,0 +1,2 @@
|
|
|
|
|
1 |
+
/* Chosen v1.2.0 | (c) 2011-2014 by Harvest | MIT License, https://github.com/harvesthq/chosen/blob/master/LICENSE.md */
|
2 |
+
!function(){var a,AbstractChosen,Chosen,SelectParser,b,c={}.hasOwnProperty,d=function(a,b){function d(){this.constructor=a}for(var e in b)c.call(b,e)&&(a[e]=b[e]);return d.prototype=b.prototype,a.prototype=new d,a.__super__=b.prototype,a};SelectParser=function(){function SelectParser(){this.options_index=0,this.parsed=[]}return SelectParser.prototype.add_node=function(a){return"OPTGROUP"===a.nodeName.toUpperCase()?this.add_group(a):this.add_option(a)},SelectParser.prototype.add_group=function(a){var b,c,d,e,f,g;for(b=this.parsed.length,this.parsed.push({array_index:b,group:!0,label:this.escapeExpression(a.label),children:0,disabled:a.disabled}),f=a.childNodes,g=[],d=0,e=f.length;e>d;d++)c=f[d],g.push(this.add_option(c,b,a.disabled));return g},SelectParser.prototype.add_option=function(a,b,c){return"OPTION"===a.nodeName.toUpperCase()?(""!==a.text?(null!=b&&(this.parsed[b].children+=1),this.parsed.push({array_index:this.parsed.length,options_index:this.options_index,value:a.value,text:a.text,html:a.innerHTML,selected:a.selected,disabled:c===!0?c:a.disabled,group_array_index:b,classes:a.className,style:a.style.cssText})):this.parsed.push({array_index:this.parsed.length,options_index:this.options_index,empty:!0}),this.options_index+=1):void 0},SelectParser.prototype.escapeExpression=function(a){var b,c;return null==a||a===!1?"":/[\&\<\>\"\'\`]/.test(a)?(b={"<":"<",">":">",'"':""","'":"'","`":"`"},c=/&(?!\w+;)|[\<\>\"\'\`]/g,a.replace(c,function(a){return b[a]||"&"})):a},SelectParser}(),SelectParser.select_to_array=function(a){var b,c,d,e,f;for(c=new SelectParser,f=a.childNodes,d=0,e=f.length;e>d;d++)b=f[d],c.add_node(b);return c.parsed},AbstractChosen=function(){function AbstractChosen(a,b){this.form_field=a,this.options=null!=b?b:{},AbstractChosen.browser_is_supported()&&(this.is_multiple=this.form_field.multiple,this.set_default_text(),this.set_default_values(),this.setup(),this.set_up_html(),this.register_observers())}return AbstractChosen.prototype.set_default_values=function(){var a=this;return this.click_test_action=function(b){return a.test_active_click(b)},this.activate_action=function(b){return a.activate_field(b)},this.active_field=!1,this.mouse_on_container=!1,this.results_showing=!1,this.result_highlighted=null,this.allow_single_deselect=null!=this.options.allow_single_deselect&&null!=this.form_field.options[0]&&""===this.form_field.options[0].text?this.options.allow_single_deselect:!1,this.disable_search_threshold=this.options.disable_search_threshold||0,this.disable_search=this.options.disable_search||!1,this.enable_split_word_search=null!=this.options.enable_split_word_search?this.options.enable_split_word_search:!0,this.group_search=null!=this.options.group_search?this.options.group_search:!0,this.search_contains=this.options.search_contains||!1,this.single_backstroke_delete=null!=this.options.single_backstroke_delete?this.options.single_backstroke_delete:!0,this.max_selected_options=this.options.max_selected_options||1/0,this.inherit_select_classes=this.options.inherit_select_classes||!1,this.display_selected_options=null!=this.options.display_selected_options?this.options.display_selected_options:!0,this.display_disabled_options=null!=this.options.display_disabled_options?this.options.display_disabled_options:!0},AbstractChosen.prototype.set_default_text=function(){return this.default_text=this.form_field.getAttribute("data-placeholder")?this.form_field.getAttribute("data-placeholder"):this.is_multiple?this.options.placeholder_text_multiple||this.options.placeholder_text||AbstractChosen.default_multiple_text:this.options.placeholder_text_single||this.options.placeholder_text||AbstractChosen.default_single_text,this.results_none_found=this.form_field.getAttribute("data-no_results_text")||this.options.no_results_text||AbstractChosen.default_no_result_text},AbstractChosen.prototype.mouse_enter=function(){return this.mouse_on_container=!0},AbstractChosen.prototype.mouse_leave=function(){return this.mouse_on_container=!1},AbstractChosen.prototype.input_focus=function(){var a=this;if(this.is_multiple){if(!this.active_field)return setTimeout(function(){return a.container_mousedown()},50)}else if(!this.active_field)return this.activate_field()},AbstractChosen.prototype.input_blur=function(){var a=this;return this.mouse_on_container?void 0:(this.active_field=!1,setTimeout(function(){return a.blur_test()},100))},AbstractChosen.prototype.results_option_build=function(a){var b,c,d,e,f;for(b="",f=this.results_data,d=0,e=f.length;e>d;d++)c=f[d],b+=c.group?this.result_add_group(c):this.result_add_option(c),(null!=a?a.first:void 0)&&(c.selected&&this.is_multiple?this.choice_build(c):c.selected&&!this.is_multiple&&this.single_set_selected_text(c.text));return b},AbstractChosen.prototype.result_add_option=function(a){var b,c;return a.search_match?this.include_option_in_results(a)?(b=[],a.disabled||a.selected&&this.is_multiple||b.push("active-result"),!a.disabled||a.selected&&this.is_multiple||b.push("disabled-result"),a.selected&&b.push("result-selected"),null!=a.group_array_index&&b.push("group-option"),""!==a.classes&&b.push(a.classes),c=document.createElement("li"),c.className=b.join(" "),c.style.cssText=a.style,c.setAttribute("data-option-array-index",a.array_index),c.innerHTML=a.search_text,this.outerHTML(c)):"":""},AbstractChosen.prototype.result_add_group=function(a){var b;return a.search_match||a.group_match?a.active_options>0?(b=document.createElement("li"),b.className="group-result",b.innerHTML=a.search_text,this.outerHTML(b)):"":""},AbstractChosen.prototype.results_update_field=function(){return this.set_default_text(),this.is_multiple||this.results_reset_cleanup(),this.result_clear_highlight(),this.results_build(),this.results_showing?this.winnow_results():void 0},AbstractChosen.prototype.reset_single_select_options=function(){var a,b,c,d,e;for(d=this.results_data,e=[],b=0,c=d.length;c>b;b++)a=d[b],a.selected?e.push(a.selected=!1):e.push(void 0);return e},AbstractChosen.prototype.results_toggle=function(){return this.results_showing?this.results_hide():this.results_show()},AbstractChosen.prototype.results_search=function(){return this.results_showing?this.winnow_results():this.results_show()},AbstractChosen.prototype.winnow_results=function(){var a,b,c,d,e,f,g,h,i,j,k,l;for(this.no_results_clear(),d=0,f=this.get_search_text(),a=f.replace(/[-[\]{}()*+?.,\\^$|#\s]/g,"\\$&"),i=new RegExp(a,"i"),c=this.get_search_regex(a),l=this.results_data,j=0,k=l.length;k>j;j++)b=l[j],b.search_match=!1,e=null,this.include_option_in_results(b)&&(b.group&&(b.group_match=!1,b.active_options=0),null!=b.group_array_index&&this.results_data[b.group_array_index]&&(e=this.results_data[b.group_array_index],0===e.active_options&&e.search_match&&(d+=1),e.active_options+=1),(!b.group||this.group_search)&&(b.search_text=b.group?b.label:b.text,b.search_match=this.search_string_match(b.search_text,c),b.search_match&&!b.group&&(d+=1),b.search_match?(f.length&&(g=b.search_text.search(i),h=b.search_text.substr(0,g+f.length)+"</em>"+b.search_text.substr(g+f.length),b.search_text=h.substr(0,g)+"<em>"+h.substr(g)),null!=e&&(e.group_match=!0)):null!=b.group_array_index&&this.results_data[b.group_array_index].search_match&&(b.search_match=!0)));return this.result_clear_highlight(),1>d&&f.length?(this.update_results_content(""),this.no_results(f)):(this.update_results_content(this.results_option_build()),this.winnow_results_set_highlight())},AbstractChosen.prototype.get_search_regex=function(a){var b;return b=this.search_contains?"":"^",new RegExp(b+a,"i")},AbstractChosen.prototype.search_string_match=function(a,b){var c,d,e,f;if(b.test(a))return!0;if(this.enable_split_word_search&&(a.indexOf(" ")>=0||0===a.indexOf("["))&&(d=a.replace(/\[|\]/g,"").split(" "),d.length))for(e=0,f=d.length;f>e;e++)if(c=d[e],b.test(c))return!0},AbstractChosen.prototype.choices_count=function(){var a,b,c,d;if(null!=this.selected_option_count)return this.selected_option_count;for(this.selected_option_count=0,d=this.form_field.options,b=0,c=d.length;c>b;b++)a=d[b],a.selected&&(this.selected_option_count+=1);return this.selected_option_count},AbstractChosen.prototype.choices_click=function(a){return a.preventDefault(),this.results_showing||this.is_disabled?void 0:this.results_show()},AbstractChosen.prototype.keyup_checker=function(a){var b,c;switch(b=null!=(c=a.which)?c:a.keyCode,this.search_field_scale(),b){case 8:if(this.is_multiple&&this.backstroke_length<1&&this.choices_count()>0)return this.keydown_backstroke();if(!this.pending_backstroke)return this.result_clear_highlight(),this.results_search();break;case 13:if(a.preventDefault(),this.results_showing)return this.result_select(a);break;case 27:return this.results_showing&&this.results_hide(),!0;case 9:case 38:case 40:case 16:case 91:case 17:break;default:return this.results_search()}},AbstractChosen.prototype.clipboard_event_checker=function(){var a=this;return setTimeout(function(){return a.results_search()},50)},AbstractChosen.prototype.container_width=function(){return null!=this.options.width?this.options.width:""+this.form_field.offsetWidth+"px"},AbstractChosen.prototype.include_option_in_results=function(a){return this.is_multiple&&!this.display_selected_options&&a.selected?!1:!this.display_disabled_options&&a.disabled?!1:a.empty?!1:!0},AbstractChosen.prototype.search_results_touchstart=function(a){return this.touch_started=!0,this.search_results_mouseover(a)},AbstractChosen.prototype.search_results_touchmove=function(a){return this.touch_started=!1,this.search_results_mouseout(a)},AbstractChosen.prototype.search_results_touchend=function(a){return this.touch_started?this.search_results_mouseup(a):void 0},AbstractChosen.prototype.outerHTML=function(a){var b;return a.outerHTML?a.outerHTML:(b=document.createElement("div"),b.appendChild(a),b.innerHTML)},AbstractChosen.browser_is_supported=function(){return"Microsoft Internet Explorer"===window.navigator.appName?document.documentMode>=8:/iP(od|hone)/i.test(window.navigator.userAgent)?!1:/Android/i.test(window.navigator.userAgent)&&/Mobile/i.test(window.navigator.userAgent)?!1:!0},AbstractChosen.default_multiple_text="Select Some Options",AbstractChosen.default_single_text="Select an Option",AbstractChosen.default_no_result_text="No results match",AbstractChosen}(),a=jQuery,a.fn.extend({chosen:function(b){return AbstractChosen.browser_is_supported()?this.each(function(){var c,d;c=a(this),d=c.data("chosen"),"destroy"===b&&d instanceof Chosen?d.destroy():d instanceof Chosen||c.data("chosen",new Chosen(this,b))}):this}}),Chosen=function(c){function Chosen(){return b=Chosen.__super__.constructor.apply(this,arguments)}return d(Chosen,c),Chosen.prototype.setup=function(){return this.form_field_jq=a(this.form_field),this.current_selectedIndex=this.form_field.selectedIndex,this.is_rtl=this.form_field_jq.hasClass("chosen-rtl")},Chosen.prototype.set_up_html=function(){var b,c;return b=["chosen-container"],b.push("chosen-container-"+(this.is_multiple?"multi":"single")),this.inherit_select_classes&&this.form_field.className&&b.push(this.form_field.className),this.is_rtl&&b.push("chosen-rtl"),c={"class":b.join(" "),style:"width: "+this.container_width()+";",title:this.form_field.title},this.form_field.id.length&&(c.id=this.form_field.id.replace(/[^\w]/g,"_")+"_chosen"),this.container=a("<div />",c),this.is_multiple?this.container.html('<ul class="chosen-choices"><li class="search-field"><input type="text" value="'+this.default_text+'" class="default" autocomplete="off" style="width:25px;" /></li></ul><div class="chosen-drop"><ul class="chosen-results"></ul></div>'):this.container.html('<a class="chosen-single chosen-default" tabindex="-1"><span>'+this.default_text+'</span><div><b></b></div></a><div class="chosen-drop"><div class="chosen-search"><input type="text" autocomplete="off" /></div><ul class="chosen-results"></ul></div>'),this.form_field_jq.hide().after(this.container),this.dropdown=this.container.find("div.chosen-drop").first(),this.search_field=this.container.find("input").first(),this.search_results=this.container.find("ul.chosen-results").first(),this.search_field_scale(),this.search_no_results=this.container.find("li.no-results").first(),this.is_multiple?(this.search_choices=this.container.find("ul.chosen-choices").first(),this.search_container=this.container.find("li.search-field").first()):(this.search_container=this.container.find("div.chosen-search").first(),this.selected_item=this.container.find(".chosen-single").first()),this.results_build(),this.set_tab_index(),this.set_label_behavior(),this.form_field_jq.trigger("chosen:ready",{chosen:this})},Chosen.prototype.register_observers=function(){var a=this;return this.container.bind("touchstart.chosen",function(b){a.container_mousedown(b)}),this.container.bind("touchend.chosen",function(b){a.container_mouseup(b)}),this.container.bind("mousedown.chosen",function(b){a.container_mousedown(b)}),this.container.bind("mouseup.chosen",function(b){a.container_mouseup(b)}),this.container.bind("mouseenter.chosen",function(b){a.mouse_enter(b)}),this.container.bind("mouseleave.chosen",function(b){a.mouse_leave(b)}),this.search_results.bind("mouseup.chosen",function(b){a.search_results_mouseup(b)}),this.search_results.bind("mouseover.chosen",function(b){a.search_results_mouseover(b)}),this.search_results.bind("mouseout.chosen",function(b){a.search_results_mouseout(b)}),this.search_results.bind("mousewheel.chosen DOMMouseScroll.chosen",function(b){a.search_results_mousewheel(b)}),this.search_results.bind("touchstart.chosen",function(b){a.search_results_touchstart(b)}),this.search_results.bind("touchmove.chosen",function(b){a.search_results_touchmove(b)}),this.search_results.bind("touchend.chosen",function(b){a.search_results_touchend(b)}),this.form_field_jq.bind("chosen:updated.chosen",function(b){a.results_update_field(b)}),this.form_field_jq.bind("chosen:activate.chosen",function(b){a.activate_field(b)}),this.form_field_jq.bind("chosen:open.chosen",function(b){a.container_mousedown(b)}),this.form_field_jq.bind("chosen:close.chosen",function(b){a.input_blur(b)}),this.search_field.bind("blur.chosen",function(b){a.input_blur(b)}),this.search_field.bind("keyup.chosen",function(b){a.keyup_checker(b)}),this.search_field.bind("keydown.chosen",function(b){a.keydown_checker(b)}),this.search_field.bind("focus.chosen",function(b){a.input_focus(b)}),this.search_field.bind("cut.chosen",function(b){a.clipboard_event_checker(b)}),this.search_field.bind("paste.chosen",function(b){a.clipboard_event_checker(b)}),this.is_multiple?this.search_choices.bind("click.chosen",function(b){a.choices_click(b)}):this.container.bind("click.chosen",function(a){a.preventDefault()})},Chosen.prototype.destroy=function(){return a(this.container[0].ownerDocument).unbind("click.chosen",this.click_test_action),this.search_field[0].tabIndex&&(this.form_field_jq[0].tabIndex=this.search_field[0].tabIndex),this.container.remove(),this.form_field_jq.removeData("chosen"),this.form_field_jq.show()},Chosen.prototype.search_field_disabled=function(){return this.is_disabled=this.form_field_jq[0].disabled,this.is_disabled?(this.container.addClass("chosen-disabled"),this.search_field[0].disabled=!0,this.is_multiple||this.selected_item.unbind("focus.chosen",this.activate_action),this.close_field()):(this.container.removeClass("chosen-disabled"),this.search_field[0].disabled=!1,this.is_multiple?void 0:this.selected_item.bind("focus.chosen",this.activate_action))},Chosen.prototype.container_mousedown=function(b){return this.is_disabled||(b&&"mousedown"===b.type&&!this.results_showing&&b.preventDefault(),null!=b&&a(b.target).hasClass("search-choice-close"))?void 0:(this.active_field?this.is_multiple||!b||a(b.target)[0]!==this.selected_item[0]&&!a(b.target).parents("a.chosen-single").length||(b.preventDefault(),this.results_toggle()):(this.is_multiple&&this.search_field.val(""),a(this.container[0].ownerDocument).bind("click.chosen",this.click_test_action),this.results_show()),this.activate_field())},Chosen.prototype.container_mouseup=function(a){return"ABBR"!==a.target.nodeName||this.is_disabled?void 0:this.results_reset(a)},Chosen.prototype.search_results_mousewheel=function(a){var b;return a.originalEvent&&(b=a.originalEvent.deltaY||-a.originalEvent.wheelDelta||a.originalEvent.detail),null!=b?(a.preventDefault(),"DOMMouseScroll"===a.type&&(b=40*b),this.search_results.scrollTop(b+this.search_results.scrollTop())):void 0},Chosen.prototype.blur_test=function(){return!this.active_field&&this.container.hasClass("chosen-container-active")?this.close_field():void 0},Chosen.prototype.close_field=function(){return a(this.container[0].ownerDocument).unbind("click.chosen",this.click_test_action),this.active_field=!1,this.results_hide(),this.container.removeClass("chosen-container-active"),this.clear_backstroke(),this.show_search_field_default(),this.search_field_scale()},Chosen.prototype.activate_field=function(){return this.container.addClass("chosen-container-active"),this.active_field=!0,this.search_field.val(this.search_field.val()),this.search_field.focus()},Chosen.prototype.test_active_click=function(b){var c;return c=a(b.target).closest(".chosen-container"),c.length&&this.container[0]===c[0]?this.active_field=!0:this.close_field()},Chosen.prototype.results_build=function(){return this.parsing=!0,this.selected_option_count=null,this.results_data=SelectParser.select_to_array(this.form_field),this.is_multiple?this.search_choices.find("li.search-choice").remove():this.is_multiple||(this.single_set_selected_text(),this.disable_search||this.form_field.options.length<=this.disable_search_threshold?(this.search_field[0].readOnly=!0,this.container.addClass("chosen-container-single-nosearch")):(this.search_field[0].readOnly=!1,this.container.removeClass("chosen-container-single-nosearch"))),this.update_results_content(this.results_option_build({first:!0})),this.search_field_disabled(),this.show_search_field_default(),this.search_field_scale(),this.parsing=!1},Chosen.prototype.result_do_highlight=function(a){var b,c,d,e,f;if(a.length){if(this.result_clear_highlight(),this.result_highlight=a,this.result_highlight.addClass("highlighted"),d=parseInt(this.search_results.css("maxHeight"),10),f=this.search_results.scrollTop(),e=d+f,c=this.result_highlight.position().top+this.search_results.scrollTop(),b=c+this.result_highlight.outerHeight(),b>=e)return this.search_results.scrollTop(b-d>0?b-d:0);if(f>c)return this.search_results.scrollTop(c)}},Chosen.prototype.result_clear_highlight=function(){return this.result_highlight&&this.result_highlight.removeClass("highlighted"),this.result_highlight=null},Chosen.prototype.results_show=function(){return this.is_multiple&&this.max_selected_options<=this.choices_count()?(this.form_field_jq.trigger("chosen:maxselected",{chosen:this}),!1):(this.container.addClass("chosen-with-drop"),this.results_showing=!0,this.search_field.focus(),this.search_field.val(this.search_field.val()),this.winnow_results(),this.form_field_jq.trigger("chosen:showing_dropdown",{chosen:this}))},Chosen.prototype.update_results_content=function(a){return this.search_results.html(a)},Chosen.prototype.results_hide=function(){return this.results_showing&&(this.result_clear_highlight(),this.container.removeClass("chosen-with-drop"),this.form_field_jq.trigger("chosen:hiding_dropdown",{chosen:this})),this.results_showing=!1},Chosen.prototype.set_tab_index=function(){var a;return this.form_field.tabIndex?(a=this.form_field.tabIndex,this.form_field.tabIndex=-1,this.search_field[0].tabIndex=a):void 0},Chosen.prototype.set_label_behavior=function(){var b=this;return this.form_field_label=this.form_field_jq.parents("label"),!this.form_field_label.length&&this.form_field.id.length&&(this.form_field_label=a("label[for='"+this.form_field.id+"']")),this.form_field_label.length>0?this.form_field_label.bind("click.chosen",function(a){return b.is_multiple?b.container_mousedown(a):b.activate_field()}):void 0},Chosen.prototype.show_search_field_default=function(){return this.is_multiple&&this.choices_count()<1&&!this.active_field?(this.search_field.val(this.default_text),this.search_field.addClass("default")):(this.search_field.val(""),this.search_field.removeClass("default"))},Chosen.prototype.search_results_mouseup=function(b){var c;return c=a(b.target).hasClass("active-result")?a(b.target):a(b.target).parents(".active-result").first(),c.length?(this.result_highlight=c,this.result_select(b),this.search_field.focus()):void 0},Chosen.prototype.search_results_mouseover=function(b){var c;return c=a(b.target).hasClass("active-result")?a(b.target):a(b.target).parents(".active-result").first(),c?this.result_do_highlight(c):void 0},Chosen.prototype.search_results_mouseout=function(b){return a(b.target).hasClass("active-result")?this.result_clear_highlight():void 0},Chosen.prototype.choice_build=function(b){var c,d,e=this;return c=a("<li />",{"class":"search-choice"}).html("<span>"+b.html+"</span>"),b.disabled?c.addClass("search-choice-disabled"):(d=a("<a />",{"class":"search-choice-close","data-option-array-index":b.array_index}),d.bind("click.chosen",function(a){return e.choice_destroy_link_click(a)}),c.append(d)),this.search_container.before(c)},Chosen.prototype.choice_destroy_link_click=function(b){return b.preventDefault(),b.stopPropagation(),this.is_disabled?void 0:this.choice_destroy(a(b.target))},Chosen.prototype.choice_destroy=function(a){return this.result_deselect(a[0].getAttribute("data-option-array-index"))?(this.show_search_field_default(),this.is_multiple&&this.choices_count()>0&&this.search_field.val().length<1&&this.results_hide(),a.parents("li").first().remove(),this.search_field_scale()):void 0},Chosen.prototype.results_reset=function(){return this.reset_single_select_options(),this.form_field.options[0].selected=!0,this.single_set_selected_text(),this.show_search_field_default(),this.results_reset_cleanup(),this.form_field_jq.trigger("change"),this.active_field?this.results_hide():void 0},Chosen.prototype.results_reset_cleanup=function(){return this.current_selectedIndex=this.form_field.selectedIndex,this.selected_item.find("abbr").remove()},Chosen.prototype.result_select=function(a){var b,c;return this.result_highlight?(b=this.result_highlight,this.result_clear_highlight(),this.is_multiple&&this.max_selected_options<=this.choices_count()?(this.form_field_jq.trigger("chosen:maxselected",{chosen:this}),!1):(this.is_multiple?b.removeClass("active-result"):this.reset_single_select_options(),c=this.results_data[b[0].getAttribute("data-option-array-index")],c.selected=!0,this.form_field.options[c.options_index].selected=!0,this.selected_option_count=null,this.is_multiple?this.choice_build(c):this.single_set_selected_text(c.text),(a.metaKey||a.ctrlKey)&&this.is_multiple||this.results_hide(),this.search_field.val(""),(this.is_multiple||this.form_field.selectedIndex!==this.current_selectedIndex)&&this.form_field_jq.trigger("change",{selected:this.form_field.options[c.options_index].value}),this.current_selectedIndex=this.form_field.selectedIndex,this.search_field_scale())):void 0},Chosen.prototype.single_set_selected_text=function(a){return null==a&&(a=this.default_text),a===this.default_text?this.selected_item.addClass("chosen-default"):(this.single_deselect_control_build(),this.selected_item.removeClass("chosen-default")),this.selected_item.find("span").text(a)},Chosen.prototype.result_deselect=function(a){var b;return b=this.results_data[a],this.form_field.options[b.options_index].disabled?!1:(b.selected=!1,this.form_field.options[b.options_index].selected=!1,this.selected_option_count=null,this.result_clear_highlight(),this.results_showing&&this.winnow_results(),this.form_field_jq.trigger("change",{deselected:this.form_field.options[b.options_index].value}),this.search_field_scale(),!0)},Chosen.prototype.single_deselect_control_build=function(){return this.allow_single_deselect?(this.selected_item.find("abbr").length||this.selected_item.find("span").first().after('<abbr class="search-choice-close"></abbr>'),this.selected_item.addClass("chosen-single-with-deselect")):void 0},Chosen.prototype.get_search_text=function(){return this.search_field.val()===this.default_text?"":a("<div/>").text(a.trim(this.search_field.val())).html()},Chosen.prototype.winnow_results_set_highlight=function(){var a,b;return b=this.is_multiple?[]:this.search_results.find(".result-selected.active-result"),a=b.length?b.first():this.search_results.find(".active-result").first(),null!=a?this.result_do_highlight(a):void 0},Chosen.prototype.no_results=function(b){var c;return c=a('<li class="no-results">'+this.results_none_found+' "<span></span>"</li>'),c.find("span").first().html(b),this.search_results.append(c),this.form_field_jq.trigger("chosen:no_results",{chosen:this})},Chosen.prototype.no_results_clear=function(){return this.search_results.find(".no-results").remove()},Chosen.prototype.keydown_arrow=function(){var a;return this.results_showing&&this.result_highlight?(a=this.result_highlight.nextAll("li.active-result").first())?this.result_do_highlight(a):void 0:this.results_show()},Chosen.prototype.keyup_arrow=function(){var a;return this.results_showing||this.is_multiple?this.result_highlight?(a=this.result_highlight.prevAll("li.active-result"),a.length?this.result_do_highlight(a.first()):(this.choices_count()>0&&this.results_hide(),this.result_clear_highlight())):void 0:this.results_show()},Chosen.prototype.keydown_backstroke=function(){var a;return this.pending_backstroke?(this.choice_destroy(this.pending_backstroke.find("a").first()),this.clear_backstroke()):(a=this.search_container.siblings("li.search-choice").last(),a.length&&!a.hasClass("search-choice-disabled")?(this.pending_backstroke=a,this.single_backstroke_delete?this.keydown_backstroke():this.pending_backstroke.addClass("search-choice-focus")):void 0)},Chosen.prototype.clear_backstroke=function(){return this.pending_backstroke&&this.pending_backstroke.removeClass("search-choice-focus"),this.pending_backstroke=null},Chosen.prototype.keydown_checker=function(a){var b,c;switch(b=null!=(c=a.which)?c:a.keyCode,this.search_field_scale(),8!==b&&this.pending_backstroke&&this.clear_backstroke(),b){case 8:this.backstroke_length=this.search_field.val().length;break;case 9:this.results_showing&&!this.is_multiple&&this.result_select(a),this.mouse_on_container=!1;break;case 13:this.results_showing&&a.preventDefault();break;case 32:this.disable_search&&a.preventDefault();break;case 38:a.preventDefault(),this.keyup_arrow();break;case 40:a.preventDefault(),this.keydown_arrow()}},Chosen.prototype.search_field_scale=function(){var b,c,d,e,f,g,h,i,j;if(this.is_multiple){for(d=0,h=0,f="position:absolute; left: -1000px; top: -1000px; display:none;",g=["font-size","font-style","font-weight","font-family","line-height","text-transform","letter-spacing"],i=0,j=g.length;j>i;i++)e=g[i],f+=e+":"+this.search_field.css(e)+";";return b=a("<div />",{style:f}),b.text(this.search_field.val()),a("body").append(b),h=b.width()+25,b.remove(),c=this.container.outerWidth(),h>c-10&&(h=c-10),this.search_field.css({width:h+"px"})}},Chosen}(AbstractChosen)}.call(this);
|
trunk/assets/plugin/chosen/chosen.min.css
ADDED
@@ -0,0 +1,3 @@
|
|
|
|
|
|
|
1 |
+
/* Chosen v1.2.0 | (c) 2011-2014 by Harvest | MIT License, https://github.com/harvesthq/chosen/blob/master/LICENSE.md */
|
2 |
+
|
3 |
+
.chosen-container{position:relative;display:inline-block;vertical-align:middle;font-size:13px;zoom:1;*display:inline;-webkit-user-select:none;-moz-user-select:none;user-select:none}.chosen-container *{-webkit-box-sizing:border-box;-moz-box-sizing:border-box;box-sizing:border-box}.chosen-container .chosen-drop{position:absolute;top:100%;left:-9999px;z-index:1010;width:100%;border:1px solid #aaa;border-top:0;background:#fff;box-shadow:0 4px 5px rgba(0,0,0,.15)}.chosen-container.chosen-with-drop .chosen-drop{left:0}.chosen-container a{cursor:pointer}.chosen-container-single .chosen-single{position:relative;display:block;overflow:hidden;padding:0 0 0 8px;height:25px;border:1px solid #aaa;border-radius:5px;background-color:#fff;background:-webkit-gradient(linear,50% 0,50% 100%,color-stop(20%,#fff),color-stop(50%,#f6f6f6),color-stop(52%,#eee),color-stop(100%,#f4f4f4));background:-webkit-linear-gradient(top,#fff 20%,#f6f6f6 50%,#eee 52%,#f4f4f4 100%);background:-moz-linear-gradient(top,#fff 20%,#f6f6f6 50%,#eee 52%,#f4f4f4 100%);background:-o-linear-gradient(top,#fff 20%,#f6f6f6 50%,#eee 52%,#f4f4f4 100%);background:linear-gradient(top,#fff 20%,#f6f6f6 50%,#eee 52%,#f4f4f4 100%);background-clip:padding-box;box-shadow:0 0 3px #fff inset,0 1px 1px rgba(0,0,0,.1);color:#444;text-decoration:none;white-space:nowrap;line-height:24px}.chosen-container-single .chosen-default{color:#999}.chosen-container-single .chosen-single span{display:block;overflow:hidden;margin-right:26px;text-overflow:ellipsis;white-space:nowrap}.chosen-container-single .chosen-single-with-deselect span{margin-right:38px}.chosen-container-single .chosen-single abbr{position:absolute;top:6px;right:26px;display:block;width:12px;height:12px;background:url(chosen-sprite.png) -42px 1px no-repeat;font-size:1px}.chosen-container-single .chosen-single abbr:hover{background-position:-42px -10px}.chosen-container-single.chosen-disabled .chosen-single abbr:hover{background-position:-42px -10px}.chosen-container-single .chosen-single div{position:absolute;top:0;right:0;display:block;width:18px;height:100%}.chosen-container-single .chosen-single div b{display:block;width:100%;height:100%;background:url(chosen-sprite.png) no-repeat 0 2px}.chosen-container-single .chosen-search{position:relative;z-index:1010;margin:0;padding:3px 4px;white-space:nowrap}.chosen-container-single .chosen-search input[type=text]{margin:1px 0;padding:4px 20px 4px 5px;width:100%;height:auto;outline:0;border:1px solid #aaa;background:#fff url(chosen-sprite.png) no-repeat 100% -20px;background:url(chosen-sprite.png) no-repeat 100% -20px;font-size:1em;font-family:sans-serif;line-height:normal;border-radius:0}.chosen-container-single .chosen-drop{margin-top:-1px;border-radius:0 0 4px 4px;background-clip:padding-box}.chosen-container-single.chosen-container-single-nosearch .chosen-search{position:absolute;left:-9999px}.chosen-container .chosen-results{color:#444;position:relative;overflow-x:hidden;overflow-y:auto;margin:0 4px 4px 0;padding:0 0 0 4px;max-height:240px;-webkit-overflow-scrolling:touch}.chosen-container .chosen-results li{display:none;margin:0;padding:5px 6px;list-style:none;line-height:15px;word-wrap:break-word;-webkit-touch-callout:none}.chosen-container .chosen-results li.active-result{display:list-item;cursor:pointer}.chosen-container .chosen-results li.disabled-result{display:list-item;color:#ccc;cursor:default}.chosen-container .chosen-results li.highlighted{background-color:#3875d7;background-image:-webkit-gradient(linear,50% 0,50% 100%,color-stop(20%,#3875d7),color-stop(90%,#2a62bc));background-image:-webkit-linear-gradient(#3875d7 20%,#2a62bc 90%);background-image:-moz-linear-gradient(#3875d7 20%,#2a62bc 90%);background-image:-o-linear-gradient(#3875d7 20%,#2a62bc 90%);background-image:linear-gradient(#3875d7 20%,#2a62bc 90%);color:#fff}.chosen-container .chosen-results li.no-results{color:#777;display:list-item;background:#f4f4f4}.chosen-container .chosen-results li.group-result{display:list-item;font-weight:700;cursor:default}.chosen-container .chosen-results li.group-option{padding-left:15px}.chosen-container .chosen-results li em{font-style:normal;text-decoration:underline}.chosen-container-multi .chosen-choices{position:relative;overflow:hidden;margin:0;padding:0 5px;width:100%;height:auto!important;height:1%;border:1px solid #aaa;background-color:#fff;background-image:-webkit-gradient(linear,50% 0,50% 100%,color-stop(1%,#eee),color-stop(15%,#fff));background-image:-webkit-linear-gradient(#eee 1%,#fff 15%);background-image:-moz-linear-gradient(#eee 1%,#fff 15%);background-image:-o-linear-gradient(#eee 1%,#fff 15%);background-image:linear-gradient(#eee 1%,#fff 15%);cursor:text}.chosen-container-multi .chosen-choices li{float:left;list-style:none}.chosen-container-multi .chosen-choices li.search-field{margin:0;padding:0;white-space:nowrap}.chosen-container-multi .chosen-choices li.search-field input[type=text]{margin:1px 0;padding:0;height:25px;outline:0;border:0!important;background:transparent!important;box-shadow:none;color:#999;font-size:100%;font-family:sans-serif;line-height:normal;border-radius:0}.chosen-container-multi .chosen-choices li.search-choice{position:relative;margin:3px 5px 3px 0;padding:3px 20px 3px 5px;border:1px solid #aaa;max-width:100%;border-radius:3px;background-color:#eee;background-image:-webkit-gradient(linear,50% 0,50% 100%,color-stop(20%,#f4f4f4),color-stop(50%,#f0f0f0),color-stop(52%,#e8e8e8),color-stop(100%,#eee));background-image:-webkit-linear-gradient(#f4f4f4 20%,#f0f0f0 50%,#e8e8e8 52%,#eee 100%);background-image:-moz-linear-gradient(#f4f4f4 20%,#f0f0f0 50%,#e8e8e8 52%,#eee 100%);background-image:-o-linear-gradient(#f4f4f4 20%,#f0f0f0 50%,#e8e8e8 52%,#eee 100%);background-image:linear-gradient(#f4f4f4 20%,#f0f0f0 50%,#e8e8e8 52%,#eee 100%);background-size:100% 19px;background-repeat:repeat-x;background-clip:padding-box;box-shadow:0 0 2px #fff inset,0 1px 0 rgba(0,0,0,.05);color:#333;line-height:13px;cursor:default}.chosen-container-multi .chosen-choices li.search-choice span{word-wrap:break-word}.chosen-container-multi .chosen-choices li.search-choice .search-choice-close{position:absolute;top:4px;right:3px;display:block;width:12px;height:12px;background:url(chosen-sprite.png) -42px 1px no-repeat;font-size:1px}.chosen-container-multi .chosen-choices li.search-choice .search-choice-close:hover{background-position:-42px -10px}.chosen-container-multi .chosen-choices li.search-choice-disabled{padding-right:5px;border:1px solid #ccc;background-color:#e4e4e4;background-image:-webkit-gradient(linear,50% 0,50% 100%,color-stop(20%,#f4f4f4),color-stop(50%,#f0f0f0),color-stop(52%,#e8e8e8),color-stop(100%,#eee));background-image:-webkit-linear-gradient(top,#f4f4f4 20%,#f0f0f0 50%,#e8e8e8 52%,#eee 100%);background-image:-moz-linear-gradient(top,#f4f4f4 20%,#f0f0f0 50%,#e8e8e8 52%,#eee 100%);background-image:-o-linear-gradient(top,#f4f4f4 20%,#f0f0f0 50%,#e8e8e8 52%,#eee 100%);background-image:linear-gradient(top,#f4f4f4 20%,#f0f0f0 50%,#e8e8e8 52%,#eee 100%);color:#666}.chosen-container-multi .chosen-choices li.search-choice-focus{background:#d4d4d4}.chosen-container-multi .chosen-choices li.search-choice-focus .search-choice-close{background-position:-42px -10px}.chosen-container-multi .chosen-results{margin:0;padding:0}.chosen-container-multi .chosen-drop .result-selected{display:list-item;color:#ccc;cursor:default}.chosen-container-active .chosen-single{border:1px solid #5897fb;box-shadow:0 0 5px rgba(0,0,0,.3)}.chosen-container-active.chosen-with-drop .chosen-single{border:1px solid #aaa;-moz-border-radius-bottomright:0;border-bottom-right-radius:0;-moz-border-radius-bottomleft:0;border-bottom-left-radius:0;background-image:-webkit-gradient(linear,50% 0,50% 100%,color-stop(20%,#eee),color-stop(80%,#fff));background-image:-webkit-linear-gradient(#eee 20%,#fff 80%);background-image:-moz-linear-gradient(#eee 20%,#fff 80%);background-image:-o-linear-gradient(#eee 20%,#fff 80%);background-image:linear-gradient(#eee 20%,#fff 80%);box-shadow:0 1px 0 #fff inset}.chosen-container-active.chosen-with-drop .chosen-single div{border-left:0;background:transparent}.chosen-container-active.chosen-with-drop .chosen-single div b{background-position:-18px 2px}.chosen-container-active .chosen-choices{border:1px solid #5897fb;box-shadow:0 0 5px rgba(0,0,0,.3)}.chosen-container-active .chosen-choices li.search-field input[type=text]{color:#222!important}.chosen-disabled{opacity:.5!important;cursor:default}.chosen-disabled .chosen-single{cursor:default}.chosen-disabled .chosen-choices .search-choice .search-choice-close{cursor:default}.chosen-rtl{text-align:right}.chosen-rtl .chosen-single{overflow:visible;padding:0 8px 0 0}.chosen-rtl .chosen-single span{margin-right:0;margin-left:26px;direction:rtl}.chosen-rtl .chosen-single-with-deselect span{margin-left:38px}.chosen-rtl .chosen-single div{right:auto;left:3px}.chosen-rtl .chosen-single abbr{right:auto;left:26px}.chosen-rtl .chosen-choices li{float:right}.chosen-rtl .chosen-choices li.search-field input[type=text]{direction:rtl}.chosen-rtl .chosen-choices li.search-choice{margin:3px 5px 3px 0;padding:3px 5px 3px 19px}.chosen-rtl .chosen-choices li.search-choice .search-choice-close{right:auto;left:4px}.chosen-rtl.chosen-container-single-nosearch .chosen-search,.chosen-rtl .chosen-drop{left:9999px}.chosen-rtl.chosen-container-single .chosen-results{margin:0 0 4px 4px;padding:0 4px 0 0}.chosen-rtl .chosen-results li.group-option{padding-right:15px;padding-left:0}.chosen-rtl.chosen-container-active.chosen-with-drop .chosen-single div{border-right:0}.chosen-rtl .chosen-search input[type=text]{padding:4px 5px 4px 20px;background:#fff url(chosen-sprite.png) no-repeat -30px -20px;background:url(chosen-sprite.png) no-repeat -30px -20px;direction:rtl}.chosen-rtl.chosen-container-single .chosen-single div b{background-position:6px 2px}.chosen-rtl.chosen-container-single.chosen-with-drop .chosen-single div b{background-position:-12px 2px}@media only screen and (-webkit-min-device-pixel-ratio:2),only screen and (min-resolution:144dpi){.chosen-rtl .chosen-search input[type=text],.chosen-container-single .chosen-single abbr,.chosen-container-single .chosen-single div b,.chosen-container-single .chosen-search input[type=text],.chosen-container-multi .chosen-choices .search-choice .search-choice-close,.chosen-container .chosen-results-scroll-down span,.chosen-container .chosen-results-scroll-up span{background-image:url(chosen-sprite@2x.png)!important;background-size:52px 37px!important;background-repeat:no-repeat!important}}
|
trunk/assets/plugin/chosen/chosen.proto.min.js
ADDED
@@ -0,0 +1,2 @@
|
|
|
|
|
1 |
+
/* Chosen v1.2.0 | (c) 2011-2014 by Harvest | MIT License, https://github.com/harvesthq/chosen/blob/master/LICENSE.md */
|
2 |
+
!function(){var AbstractChosen,SelectParser,a,b={}.hasOwnProperty,c=function(a,c){function d(){this.constructor=a}for(var e in c)b.call(c,e)&&(a[e]=c[e]);return d.prototype=c.prototype,a.prototype=new d,a.__super__=c.prototype,a};SelectParser=function(){function SelectParser(){this.options_index=0,this.parsed=[]}return SelectParser.prototype.add_node=function(a){return"OPTGROUP"===a.nodeName.toUpperCase()?this.add_group(a):this.add_option(a)},SelectParser.prototype.add_group=function(a){var b,c,d,e,f,g;for(b=this.parsed.length,this.parsed.push({array_index:b,group:!0,label:this.escapeExpression(a.label),children:0,disabled:a.disabled}),f=a.childNodes,g=[],d=0,e=f.length;e>d;d++)c=f[d],g.push(this.add_option(c,b,a.disabled));return g},SelectParser.prototype.add_option=function(a,b,c){return"OPTION"===a.nodeName.toUpperCase()?(""!==a.text?(null!=b&&(this.parsed[b].children+=1),this.parsed.push({array_index:this.parsed.length,options_index:this.options_index,value:a.value,text:a.text,html:a.innerHTML,selected:a.selected,disabled:c===!0?c:a.disabled,group_array_index:b,classes:a.className,style:a.style.cssText})):this.parsed.push({array_index:this.parsed.length,options_index:this.options_index,empty:!0}),this.options_index+=1):void 0},SelectParser.prototype.escapeExpression=function(a){var b,c;return null==a||a===!1?"":/[\&\<\>\"\'\`]/.test(a)?(b={"<":"<",">":">",'"':""","'":"'","`":"`"},c=/&(?!\w+;)|[\<\>\"\'\`]/g,a.replace(c,function(a){return b[a]||"&"})):a},SelectParser}(),SelectParser.select_to_array=function(a){var b,c,d,e,f;for(c=new SelectParser,f=a.childNodes,d=0,e=f.length;e>d;d++)b=f[d],c.add_node(b);return c.parsed},AbstractChosen=function(){function AbstractChosen(a,b){this.form_field=a,this.options=null!=b?b:{},AbstractChosen.browser_is_supported()&&(this.is_multiple=this.form_field.multiple,this.set_default_text(),this.set_default_values(),this.setup(),this.set_up_html(),this.register_observers())}return AbstractChosen.prototype.set_default_values=function(){var a=this;return this.click_test_action=function(b){return a.test_active_click(b)},this.activate_action=function(b){return a.activate_field(b)},this.active_field=!1,this.mouse_on_container=!1,this.results_showing=!1,this.result_highlighted=null,this.allow_single_deselect=null!=this.options.allow_single_deselect&&null!=this.form_field.options[0]&&""===this.form_field.options[0].text?this.options.allow_single_deselect:!1,this.disable_search_threshold=this.options.disable_search_threshold||0,this.disable_search=this.options.disable_search||!1,this.enable_split_word_search=null!=this.options.enable_split_word_search?this.options.enable_split_word_search:!0,this.group_search=null!=this.options.group_search?this.options.group_search:!0,this.search_contains=this.options.search_contains||!1,this.single_backstroke_delete=null!=this.options.single_backstroke_delete?this.options.single_backstroke_delete:!0,this.max_selected_options=this.options.max_selected_options||1/0,this.inherit_select_classes=this.options.inherit_select_classes||!1,this.display_selected_options=null!=this.options.display_selected_options?this.options.display_selected_options:!0,this.display_disabled_options=null!=this.options.display_disabled_options?this.options.display_disabled_options:!0},AbstractChosen.prototype.set_default_text=function(){return this.default_text=this.form_field.getAttribute("data-placeholder")?this.form_field.getAttribute("data-placeholder"):this.is_multiple?this.options.placeholder_text_multiple||this.options.placeholder_text||AbstractChosen.default_multiple_text:this.options.placeholder_text_single||this.options.placeholder_text||AbstractChosen.default_single_text,this.results_none_found=this.form_field.getAttribute("data-no_results_text")||this.options.no_results_text||AbstractChosen.default_no_result_text},AbstractChosen.prototype.mouse_enter=function(){return this.mouse_on_container=!0},AbstractChosen.prototype.mouse_leave=function(){return this.mouse_on_container=!1},AbstractChosen.prototype.input_focus=function(){var a=this;if(this.is_multiple){if(!this.active_field)return setTimeout(function(){return a.container_mousedown()},50)}else if(!this.active_field)return this.activate_field()},AbstractChosen.prototype.input_blur=function(){var a=this;return this.mouse_on_container?void 0:(this.active_field=!1,setTimeout(function(){return a.blur_test()},100))},AbstractChosen.prototype.results_option_build=function(a){var b,c,d,e,f;for(b="",f=this.results_data,d=0,e=f.length;e>d;d++)c=f[d],b+=c.group?this.result_add_group(c):this.result_add_option(c),(null!=a?a.first:void 0)&&(c.selected&&this.is_multiple?this.choice_build(c):c.selected&&!this.is_multiple&&this.single_set_selected_text(c.text));return b},AbstractChosen.prototype.result_add_option=function(a){var b,c;return a.search_match?this.include_option_in_results(a)?(b=[],a.disabled||a.selected&&this.is_multiple||b.push("active-result"),!a.disabled||a.selected&&this.is_multiple||b.push("disabled-result"),a.selected&&b.push("result-selected"),null!=a.group_array_index&&b.push("group-option"),""!==a.classes&&b.push(a.classes),c=document.createElement("li"),c.className=b.join(" "),c.style.cssText=a.style,c.setAttribute("data-option-array-index",a.array_index),c.innerHTML=a.search_text,this.outerHTML(c)):"":""},AbstractChosen.prototype.result_add_group=function(a){var b;return a.search_match||a.group_match?a.active_options>0?(b=document.createElement("li"),b.className="group-result",b.innerHTML=a.search_text,this.outerHTML(b)):"":""},AbstractChosen.prototype.results_update_field=function(){return this.set_default_text(),this.is_multiple||this.results_reset_cleanup(),this.result_clear_highlight(),this.results_build(),this.results_showing?this.winnow_results():void 0},AbstractChosen.prototype.reset_single_select_options=function(){var a,b,c,d,e;for(d=this.results_data,e=[],b=0,c=d.length;c>b;b++)a=d[b],a.selected?e.push(a.selected=!1):e.push(void 0);return e},AbstractChosen.prototype.results_toggle=function(){return this.results_showing?this.results_hide():this.results_show()},AbstractChosen.prototype.results_search=function(){return this.results_showing?this.winnow_results():this.results_show()},AbstractChosen.prototype.winnow_results=function(){var a,b,c,d,e,f,g,h,i,j,k,l;for(this.no_results_clear(),d=0,f=this.get_search_text(),a=f.replace(/[-[\]{}()*+?.,\\^$|#\s]/g,"\\$&"),i=new RegExp(a,"i"),c=this.get_search_regex(a),l=this.results_data,j=0,k=l.length;k>j;j++)b=l[j],b.search_match=!1,e=null,this.include_option_in_results(b)&&(b.group&&(b.group_match=!1,b.active_options=0),null!=b.group_array_index&&this.results_data[b.group_array_index]&&(e=this.results_data[b.group_array_index],0===e.active_options&&e.search_match&&(d+=1),e.active_options+=1),(!b.group||this.group_search)&&(b.search_text=b.group?b.label:b.text,b.search_match=this.search_string_match(b.search_text,c),b.search_match&&!b.group&&(d+=1),b.search_match?(f.length&&(g=b.search_text.search(i),h=b.search_text.substr(0,g+f.length)+"</em>"+b.search_text.substr(g+f.length),b.search_text=h.substr(0,g)+"<em>"+h.substr(g)),null!=e&&(e.group_match=!0)):null!=b.group_array_index&&this.results_data[b.group_array_index].search_match&&(b.search_match=!0)));return this.result_clear_highlight(),1>d&&f.length?(this.update_results_content(""),this.no_results(f)):(this.update_results_content(this.results_option_build()),this.winnow_results_set_highlight())},AbstractChosen.prototype.get_search_regex=function(a){var b;return b=this.search_contains?"":"^",new RegExp(b+a,"i")},AbstractChosen.prototype.search_string_match=function(a,b){var c,d,e,f;if(b.test(a))return!0;if(this.enable_split_word_search&&(a.indexOf(" ")>=0||0===a.indexOf("["))&&(d=a.replace(/\[|\]/g,"").split(" "),d.length))for(e=0,f=d.length;f>e;e++)if(c=d[e],b.test(c))return!0},AbstractChosen.prototype.choices_count=function(){var a,b,c,d;if(null!=this.selected_option_count)return this.selected_option_count;for(this.selected_option_count=0,d=this.form_field.options,b=0,c=d.length;c>b;b++)a=d[b],a.selected&&(this.selected_option_count+=1);return this.selected_option_count},AbstractChosen.prototype.choices_click=function(a){return a.preventDefault(),this.results_showing||this.is_disabled?void 0:this.results_show()},AbstractChosen.prototype.keyup_checker=function(a){var b,c;switch(b=null!=(c=a.which)?c:a.keyCode,this.search_field_scale(),b){case 8:if(this.is_multiple&&this.backstroke_length<1&&this.choices_count()>0)return this.keydown_backstroke();if(!this.pending_backstroke)return this.result_clear_highlight(),this.results_search();break;case 13:if(a.preventDefault(),this.results_showing)return this.result_select(a);break;case 27:return this.results_showing&&this.results_hide(),!0;case 9:case 38:case 40:case 16:case 91:case 17:break;default:return this.results_search()}},AbstractChosen.prototype.clipboard_event_checker=function(){var a=this;return setTimeout(function(){return a.results_search()},50)},AbstractChosen.prototype.container_width=function(){return null!=this.options.width?this.options.width:""+this.form_field.offsetWidth+"px"},AbstractChosen.prototype.include_option_in_results=function(a){return this.is_multiple&&!this.display_selected_options&&a.selected?!1:!this.display_disabled_options&&a.disabled?!1:a.empty?!1:!0},AbstractChosen.prototype.search_results_touchstart=function(a){return this.touch_started=!0,this.search_results_mouseover(a)},AbstractChosen.prototype.search_results_touchmove=function(a){return this.touch_started=!1,this.search_results_mouseout(a)},AbstractChosen.prototype.search_results_touchend=function(a){return this.touch_started?this.search_results_mouseup(a):void 0},AbstractChosen.prototype.outerHTML=function(a){var b;return a.outerHTML?a.outerHTML:(b=document.createElement("div"),b.appendChild(a),b.innerHTML)},AbstractChosen.browser_is_supported=function(){return"Microsoft Internet Explorer"===window.navigator.appName?document.documentMode>=8:/iP(od|hone)/i.test(window.navigator.userAgent)?!1:/Android/i.test(window.navigator.userAgent)&&/Mobile/i.test(window.navigator.userAgent)?!1:!0},AbstractChosen.default_multiple_text="Select Some Options",AbstractChosen.default_single_text="Select an Option",AbstractChosen.default_no_result_text="No results match",AbstractChosen}(),this.Chosen=function(b){function Chosen(){return a=Chosen.__super__.constructor.apply(this,arguments)}return c(Chosen,b),Chosen.prototype.setup=function(){return this.current_selectedIndex=this.form_field.selectedIndex,this.is_rtl=this.form_field.hasClassName("chosen-rtl")},Chosen.prototype.set_default_values=function(){return Chosen.__super__.set_default_values.call(this),this.single_temp=new Template('<a class="chosen-single chosen-default" tabindex="-1"><span>#{default}</span><div><b></b></div></a><div class="chosen-drop"><div class="chosen-search"><input type="text" autocomplete="off" /></div><ul class="chosen-results"></ul></div>'),this.multi_temp=new Template('<ul class="chosen-choices"><li class="search-field"><input type="text" value="#{default}" class="default" autocomplete="off" style="width:25px;" /></li></ul><div class="chosen-drop"><ul class="chosen-results"></ul></div>'),this.no_results_temp=new Template('<li class="no-results">'+this.results_none_found+' "<span>#{terms}</span>"</li>')},Chosen.prototype.set_up_html=function(){var a,b;return a=["chosen-container"],a.push("chosen-container-"+(this.is_multiple?"multi":"single")),this.inherit_select_classes&&this.form_field.className&&a.push(this.form_field.className),this.is_rtl&&a.push("chosen-rtl"),b={"class":a.join(" "),style:"width: "+this.container_width()+";",title:this.form_field.title},this.form_field.id.length&&(b.id=this.form_field.id.replace(/[^\w]/g,"_")+"_chosen"),this.container=this.is_multiple?new Element("div",b).update(this.multi_temp.evaluate({"default":this.default_text})):new Element("div",b).update(this.single_temp.evaluate({"default":this.default_text})),this.form_field.hide().insert({after:this.container}),this.dropdown=this.container.down("div.chosen-drop"),this.search_field=this.container.down("input"),this.search_results=this.container.down("ul.chosen-results"),this.search_field_scale(),this.search_no_results=this.container.down("li.no-results"),this.is_multiple?(this.search_choices=this.container.down("ul.chosen-choices"),this.search_container=this.container.down("li.search-field")):(this.search_container=this.container.down("div.chosen-search"),this.selected_item=this.container.down(".chosen-single")),this.results_build(),this.set_tab_index(),this.set_label_behavior(),this.form_field.fire("chosen:ready",{chosen:this})},Chosen.prototype.register_observers=function(){var a=this;return this.container.observe("touchstart",function(b){return a.container_mousedown(b)}),this.container.observe("touchend",function(b){return a.container_mouseup(b)}),this.container.observe("mousedown",function(b){return a.container_mousedown(b)}),this.container.observe("mouseup",function(b){return a.container_mouseup(b)}),this.container.observe("mouseenter",function(b){return a.mouse_enter(b)}),this.container.observe("mouseleave",function(b){return a.mouse_leave(b)}),this.search_results.observe("mouseup",function(b){return a.search_results_mouseup(b)}),this.search_results.observe("mouseover",function(b){return a.search_results_mouseover(b)}),this.search_results.observe("mouseout",function(b){return a.search_results_mouseout(b)}),this.search_results.observe("mousewheel",function(b){return a.search_results_mousewheel(b)}),this.search_results.observe("DOMMouseScroll",function(b){return a.search_results_mousewheel(b)}),this.search_results.observe("touchstart",function(b){return a.search_results_touchstart(b)}),this.search_results.observe("touchmove",function(b){return a.search_results_touchmove(b)}),this.search_results.observe("touchend",function(b){return a.search_results_touchend(b)}),this.form_field.observe("chosen:updated",function(b){return a.results_update_field(b)}),this.form_field.observe("chosen:activate",function(b){return a.activate_field(b)}),this.form_field.observe("chosen:open",function(b){return a.container_mousedown(b)}),this.form_field.observe("chosen:close",function(b){return a.input_blur(b)}),this.search_field.observe("blur",function(b){return a.input_blur(b)}),this.search_field.observe("keyup",function(b){return a.keyup_checker(b)}),this.search_field.observe("keydown",function(b){return a.keydown_checker(b)}),this.search_field.observe("focus",function(b){return a.input_focus(b)}),this.search_field.observe("cut",function(b){return a.clipboard_event_checker(b)}),this.search_field.observe("paste",function(b){return a.clipboard_event_checker(b)}),this.is_multiple?this.search_choices.observe("click",function(b){return a.choices_click(b)}):this.container.observe("click",function(a){return a.preventDefault()})},Chosen.prototype.destroy=function(){return this.container.ownerDocument.stopObserving("click",this.click_test_action),this.form_field.stopObserving(),this.container.stopObserving(),this.search_results.stopObserving(),this.search_field.stopObserving(),null!=this.form_field_label&&this.form_field_label.stopObserving(),this.is_multiple?(this.search_choices.stopObserving(),this.container.select(".search-choice-close").each(function(a){return a.stopObserving()})):this.selected_item.stopObserving(),this.search_field.tabIndex&&(this.form_field.tabIndex=this.search_field.tabIndex),this.container.remove(),this.form_field.show()},Chosen.prototype.search_field_disabled=function(){return this.is_disabled=this.form_field.disabled,this.is_disabled?(this.container.addClassName("chosen-disabled"),this.search_field.disabled=!0,this.is_multiple||this.selected_item.stopObserving("focus",this.activate_action),this.close_field()):(this.container.removeClassName("chosen-disabled"),this.search_field.disabled=!1,this.is_multiple?void 0:this.selected_item.observe("focus",this.activate_action))},Chosen.prototype.container_mousedown=function(a){return this.is_disabled||(a&&"mousedown"===a.type&&!this.results_showing&&a.stop(),null!=a&&a.target.hasClassName("search-choice-close"))?void 0:(this.active_field?this.is_multiple||!a||a.target!==this.selected_item&&!a.target.up("a.chosen-single")||this.results_toggle():(this.is_multiple&&this.search_field.clear(),this.container.ownerDocument.observe("click",this.click_test_action),this.results_show()),this.activate_field())},Chosen.prototype.container_mouseup=function(a){return"ABBR"!==a.target.nodeName||this.is_disabled?void 0:this.results_reset(a)},Chosen.prototype.search_results_mousewheel=function(a){var b;return b=a.deltaY||-a.wheelDelta||a.detail,null!=b?(a.preventDefault(),"DOMMouseScroll"===a.type&&(b=40*b),this.search_results.scrollTop=b+this.search_results.scrollTop):void 0},Chosen.prototype.blur_test=function(){return!this.active_field&&this.container.hasClassName("chosen-container-active")?this.close_field():void 0},Chosen.prototype.close_field=function(){return this.container.ownerDocument.stopObserving("click",this.click_test_action),this.active_field=!1,this.results_hide(),this.container.removeClassName("chosen-container-active"),this.clear_backstroke(),this.show_search_field_default(),this.search_field_scale()},Chosen.prototype.activate_field=function(){return this.container.addClassName("chosen-container-active"),this.active_field=!0,this.search_field.value=this.search_field.value,this.search_field.focus()},Chosen.prototype.test_active_click=function(a){return a.target.up(".chosen-container")===this.container?this.active_field=!0:this.close_field()},Chosen.prototype.results_build=function(){return this.parsing=!0,this.selected_option_count=null,this.results_data=SelectParser.select_to_array(this.form_field),this.is_multiple?this.search_choices.select("li.search-choice").invoke("remove"):this.is_multiple||(this.single_set_selected_text(),this.disable_search||this.form_field.options.length<=this.disable_search_threshold?(this.search_field.readOnly=!0,this.container.addClassName("chosen-container-single-nosearch")):(this.search_field.readOnly=!1,this.container.removeClassName("chosen-container-single-nosearch"))),this.update_results_content(this.results_option_build({first:!0})),this.search_field_disabled(),this.show_search_field_default(),this.search_field_scale(),this.parsing=!1},Chosen.prototype.result_do_highlight=function(a){var b,c,d,e,f;return this.result_clear_highlight(),this.result_highlight=a,this.result_highlight.addClassName("highlighted"),d=parseInt(this.search_results.getStyle("maxHeight"),10),f=this.search_results.scrollTop,e=d+f,c=this.result_highlight.positionedOffset().top,b=c+this.result_highlight.getHeight(),b>=e?this.search_results.scrollTop=b-d>0?b-d:0:f>c?this.search_results.scrollTop=c:void 0},Chosen.prototype.result_clear_highlight=function(){return this.result_highlight&&this.result_highlight.removeClassName("highlighted"),this.result_highlight=null},Chosen.prototype.results_show=function(){return this.is_multiple&&this.max_selected_options<=this.choices_count()?(this.form_field.fire("chosen:maxselected",{chosen:this}),!1):(this.container.addClassName("chosen-with-drop"),this.results_showing=!0,this.search_field.focus(),this.search_field.value=this.search_field.value,this.winnow_results(),this.form_field.fire("chosen:showing_dropdown",{chosen:this}))},Chosen.prototype.update_results_content=function(a){return this.search_results.update(a)},Chosen.prototype.results_hide=function(){return this.results_showing&&(this.result_clear_highlight(),this.container.removeClassName("chosen-with-drop"),this.form_field.fire("chosen:hiding_dropdown",{chosen:this})),this.results_showing=!1},Chosen.prototype.set_tab_index=function(){var a;return this.form_field.tabIndex?(a=this.form_field.tabIndex,this.form_field.tabIndex=-1,this.search_field.tabIndex=a):void 0},Chosen.prototype.set_label_behavior=function(){var a=this;return this.form_field_label=this.form_field.up("label"),null==this.form_field_label&&(this.form_field_label=$$("label[for='"+this.form_field.id+"']").first()),null!=this.form_field_label?this.form_field_label.observe("click",function(b){return a.is_multiple?a.container_mousedown(b):a.activate_field()}):void 0},Chosen.prototype.show_search_field_default=function(){return this.is_multiple&&this.choices_count()<1&&!this.active_field?(this.search_field.value=this.default_text,this.search_field.addClassName("default")):(this.search_field.value="",this.search_field.removeClassName("default"))},Chosen.prototype.search_results_mouseup=function(a){var b;return b=a.target.hasClassName("active-result")?a.target:a.target.up(".active-result"),b?(this.result_highlight=b,this.result_select(a),this.search_field.focus()):void 0},Chosen.prototype.search_results_mouseover=function(a){var b;return b=a.target.hasClassName("active-result")?a.target:a.target.up(".active-result"),b?this.result_do_highlight(b):void 0},Chosen.prototype.search_results_mouseout=function(a){return a.target.hasClassName("active-result")||a.target.up(".active-result")?this.result_clear_highlight():void 0},Chosen.prototype.choice_build=function(a){var b,c,d=this;return b=new Element("li",{"class":"search-choice"}).update("<span>"+a.html+"</span>"),a.disabled?b.addClassName("search-choice-disabled"):(c=new Element("a",{href:"#","class":"search-choice-close",rel:a.array_index}),c.observe("click",function(a){return d.choice_destroy_link_click(a)}),b.insert(c)),this.search_container.insert({before:b})},Chosen.prototype.choice_destroy_link_click=function(a){return a.preventDefault(),a.stopPropagation(),this.is_disabled?void 0:this.choice_destroy(a.target)},Chosen.prototype.choice_destroy=function(a){return this.result_deselect(a.readAttribute("rel"))?(this.show_search_field_default(),this.is_multiple&&this.choices_count()>0&&this.search_field.value.length<1&&this.results_hide(),a.up("li").remove(),this.search_field_scale()):void 0},Chosen.prototype.results_reset=function(){return this.reset_single_select_options(),this.form_field.options[0].selected=!0,this.single_set_selected_text(),this.show_search_field_default(),this.results_reset_cleanup(),"function"==typeof Event.simulate&&this.form_field.simulate("change"),this.active_field?this.results_hide():void 0},Chosen.prototype.results_reset_cleanup=function(){var a;return this.current_selectedIndex=this.form_field.selectedIndex,a=this.selected_item.down("abbr"),a?a.remove():void 0},Chosen.prototype.result_select=function(a){var b,c;return this.result_highlight?(b=this.result_highlight,this.result_clear_highlight(),this.is_multiple&&this.max_selected_options<=this.choices_count()?(this.form_field.fire("chosen:maxselected",{chosen:this}),!1):(this.is_multiple?b.removeClassName("active-result"):this.reset_single_select_options(),b.addClassName("result-selected"),c=this.results_data[b.getAttribute("data-option-array-index")],c.selected=!0,this.form_field.options[c.options_index].selected=!0,this.selected_option_count=null,this.is_multiple?this.choice_build(c):this.single_set_selected_text(c.text),(a.metaKey||a.ctrlKey)&&this.is_multiple||this.results_hide(),this.search_field.value="","function"!=typeof Event.simulate||!this.is_multiple&&this.form_field.selectedIndex===this.current_selectedIndex||this.form_field.simulate("change"),this.current_selectedIndex=this.form_field.selectedIndex,this.search_field_scale())):void 0},Chosen.prototype.single_set_selected_text=function(a){return null==a&&(a=this.default_text),a===this.default_text?this.selected_item.addClassName("chosen-default"):(this.single_deselect_control_build(),this.selected_item.removeClassName("chosen-default")),this.selected_item.down("span").update(a)},Chosen.prototype.result_deselect=function(a){var b;return b=this.results_data[a],this.form_field.options[b.options_index].disabled?!1:(b.selected=!1,this.form_field.options[b.options_index].selected=!1,this.selected_option_count=null,this.result_clear_highlight(),this.results_showing&&this.winnow_results(),"function"==typeof Event.simulate&&this.form_field.simulate("change"),this.search_field_scale(),!0)},Chosen.prototype.single_deselect_control_build=function(){return this.allow_single_deselect?(this.selected_item.down("abbr")||this.selected_item.down("span").insert({after:'<abbr class="search-choice-close"></abbr>'}),this.selected_item.addClassName("chosen-single-with-deselect")):void 0},Chosen.prototype.get_search_text=function(){return this.search_field.value===this.default_text?"":this.search_field.value.strip().escapeHTML()},Chosen.prototype.winnow_results_set_highlight=function(){var a;return this.is_multiple||(a=this.search_results.down(".result-selected.active-result")),null==a&&(a=this.search_results.down(".active-result")),null!=a?this.result_do_highlight(a):void 0},Chosen.prototype.no_results=function(a){return this.search_results.insert(this.no_results_temp.evaluate({terms:a})),this.form_field.fire("chosen:no_results",{chosen:this})},Chosen.prototype.no_results_clear=function(){var a,b;for(a=null,b=[];a=this.search_results.down(".no-results");)b.push(a.remove());return b},Chosen.prototype.keydown_arrow=function(){var a;return this.results_showing&&this.result_highlight?(a=this.result_highlight.next(".active-result"))?this.result_do_highlight(a):void 0:this.results_show()},Chosen.prototype.keyup_arrow=function(){var a,b,c;return this.results_showing||this.is_multiple?this.result_highlight?(c=this.result_highlight.previousSiblings(),a=this.search_results.select("li.active-result"),b=c.intersect(a),b.length?this.result_do_highlight(b.first()):(this.choices_count()>0&&this.results_hide(),this.result_clear_highlight())):void 0:this.results_show()},Chosen.prototype.keydown_backstroke=function(){var a;return this.pending_backstroke?(this.choice_destroy(this.pending_backstroke.down("a")),this.clear_backstroke()):(a=this.search_container.siblings().last(),a&&a.hasClassName("search-choice")&&!a.hasClassName("search-choice-disabled")?(this.pending_backstroke=a,this.pending_backstroke&&this.pending_backstroke.addClassName("search-choice-focus"),this.single_backstroke_delete?this.keydown_backstroke():this.pending_backstroke.addClassName("search-choice-focus")):void 0)},Chosen.prototype.clear_backstroke=function(){return this.pending_backstroke&&this.pending_backstroke.removeClassName("search-choice-focus"),this.pending_backstroke=null},Chosen.prototype.keydown_checker=function(a){var b,c;switch(b=null!=(c=a.which)?c:a.keyCode,this.search_field_scale(),8!==b&&this.pending_backstroke&&this.clear_backstroke(),b){case 8:this.backstroke_length=this.search_field.value.length;break;case 9:this.results_showing&&!this.is_multiple&&this.result_select(a),this.mouse_on_container=!1;break;case 13:this.results_showing&&a.preventDefault();break;case 32:this.disable_search&&a.preventDefault();break;case 38:a.preventDefault(),this.keyup_arrow();break;case 40:a.preventDefault(),this.keydown_arrow()}},Chosen.prototype.search_field_scale=function(){var a,b,c,d,e,f,g,h,i;if(this.is_multiple){for(c=0,g=0,e="position:absolute; left: -1000px; top: -1000px; display:none;",f=["font-size","font-style","font-weight","font-family","line-height","text-transform","letter-spacing"],h=0,i=f.length;i>h;h++)d=f[h],e+=d+":"+this.search_field.getStyle(d)+";";return a=new Element("div",{style:e}).update(this.search_field.value.escapeHTML()),document.body.appendChild(a),g=Element.measure(a,"width")+25,a.remove(),b=this.container.getWidth(),g>b-10&&(g=b-10),this.search_field.setStyle({width:g+"px"})}},Chosen}(AbstractChosen)}.call(this);
|
trunk/class-aftership-api.php
ADDED
@@ -0,0 +1,182 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
<?php
|
2 |
+
/**
|
3 |
+
* AfterShip API
|
4 |
+
*
|
5 |
+
* Handles AfterShip-API endpoint requests
|
6 |
+
*
|
7 |
+
* @author AfterShip
|
8 |
+
* @category API
|
9 |
+
* @package AfterShip
|
10 |
+
* @since 1.0
|
11 |
+
*/
|
12 |
+
|
13 |
+
if (!defined('ABSPATH')) exit; // Exit if accessed directly
|
14 |
+
|
15 |
+
class AfterShip_API
|
16 |
+
{
|
17 |
+
|
18 |
+
/** This is the major version for the REST API and takes
|
19 |
+
* first-order position in endpoint URLs
|
20 |
+
*/
|
21 |
+
const VERSION = 1;
|
22 |
+
|
23 |
+
/** @var WC_API_Server the REST API server */
|
24 |
+
public $server;
|
25 |
+
|
26 |
+
/**
|
27 |
+
* Setup class
|
28 |
+
*
|
29 |
+
* @access public
|
30 |
+
* @since 2.0
|
31 |
+
* @return WC_API
|
32 |
+
*/
|
33 |
+
public function __construct()
|
34 |
+
{
|
35 |
+
|
36 |
+
// add query vars
|
37 |
+
add_filter('query_vars', array($this, 'add_query_vars'), 0);
|
38 |
+
|
39 |
+
// register API endpoints
|
40 |
+
add_action('init', array($this, 'add_endpoint'), 0);
|
41 |
+
|
42 |
+
// handle REST/legacy API request
|
43 |
+
add_action('parse_request', array($this, 'handle_api_requests'), 0);
|
44 |
+
}
|
45 |
+
|
46 |
+
/**
|
47 |
+
* add_query_vars function.
|
48 |
+
*
|
49 |
+
* @access public
|
50 |
+
* @since 2.0
|
51 |
+
* @param $vars
|
52 |
+
* @return array
|
53 |
+
*/
|
54 |
+
public function add_query_vars($vars)
|
55 |
+
{
|
56 |
+
$vars[] = 'aftership-api';
|
57 |
+
$vars[] = 'aftership-api-route';
|
58 |
+
return $vars;
|
59 |
+
}
|
60 |
+
|
61 |
+
/**
|
62 |
+
* add_endpoint function.
|
63 |
+
*
|
64 |
+
* @access public
|
65 |
+
* @since 2.0
|
66 |
+
* @return void
|
67 |
+
*/
|
68 |
+
public function add_endpoint()
|
69 |
+
{
|
70 |
+
|
71 |
+
// REST API
|
72 |
+
add_rewrite_rule('^aftership-api\/v' . self::VERSION . '/?$', 'index.php?aftership-api-route=/', 'top');
|
73 |
+
add_rewrite_rule('^aftership-api\/v' . self::VERSION . '(.*)?', 'index.php?aftership-api-route=$matches[1]', 'top');
|
74 |
+
|
75 |
+
// legacy API for payment gateway IPNs
|
76 |
+
add_rewrite_endpoint('aftership-api', EP_ALL);
|
77 |
+
}
|
78 |
+
|
79 |
+
|
80 |
+
/**
|
81 |
+
* API request - Trigger any API requests
|
82 |
+
*
|
83 |
+
* @access public
|
84 |
+
* @since 2.0
|
85 |
+
* @return void
|
86 |
+
*/
|
87 |
+
public function handle_api_requests()
|
88 |
+
{
|
89 |
+
global $wp;
|
90 |
+
|
91 |
+
if (!empty($_GET['aftership-api']))
|
92 |
+
$wp->query_vars['aftership-api'] = $_GET['aftership-api'];
|
93 |
+
|
94 |
+
if (!empty($_GET['aftership-api-route']))
|
95 |
+
$wp->query_vars['aftership-api-route'] = $_GET['aftership-api-route'];
|
96 |
+
|
97 |
+
// REST API request
|
98 |
+
if (!empty($wp->query_vars['aftership-api-route'])) {
|
99 |
+
|
100 |
+
define('AFTERSHIP_API_REQUEST', true);
|
101 |
+
|
102 |
+
// load required files
|
103 |
+
$this->includes();
|
104 |
+
|
105 |
+
$this->server = new AfterShip_API_Server($wp->query_vars['aftership-api-route']);
|
106 |
+
|
107 |
+
// load API resource classes
|
108 |
+
$this->register_resources($this->server);
|
109 |
+
|
110 |
+
// Fire off the request
|
111 |
+
$this->server->serve_request();
|
112 |
+
|
113 |
+
exit;
|
114 |
+
}
|
115 |
+
|
116 |
+
// legacy API requests
|
117 |
+
if (!empty($wp->query_vars['aftership-api'])) {
|
118 |
+
|
119 |
+
// Buffer, we won't want any output here
|
120 |
+
ob_start();
|
121 |
+
|
122 |
+
// Get API trigger
|
123 |
+
$api = strtolower(esc_attr($wp->query_vars['aftership-api']));
|
124 |
+
|
125 |
+
// Load class if exists
|
126 |
+
if (class_exists($api))
|
127 |
+
$api_class = new $api();
|
128 |
+
|
129 |
+
// Trigger actions
|
130 |
+
do_action('woocommerce_api_' . $api);
|
131 |
+
|
132 |
+
// Done, clear buffer and exit
|
133 |
+
ob_end_clean();
|
134 |
+
die('1');
|
135 |
+
}
|
136 |
+
}
|
137 |
+
|
138 |
+
|
139 |
+
/**
|
140 |
+
* Include required files for REST API request
|
141 |
+
*
|
142 |
+
* @since 2.1
|
143 |
+
*/
|
144 |
+
private function includes()
|
145 |
+
{
|
146 |
+
|
147 |
+
// API server / response handlers
|
148 |
+
include_once('api/class-aftership-api-server.php');
|
149 |
+
include_once('api/interface-aftership-api-handler.php');
|
150 |
+
include_once('api/class-aftership-api-json-handler.php');
|
151 |
+
|
152 |
+
// authentication
|
153 |
+
include_once('api/class-aftership-api-authentication.php');
|
154 |
+
$this->authentication = new AfterShip_API_Authentication();
|
155 |
+
|
156 |
+
include_once('api/class-aftership-api-resource.php');
|
157 |
+
|
158 |
+
// self api
|
159 |
+
include_once('api/class-aftership-api-orders.php');
|
160 |
+
}
|
161 |
+
|
162 |
+
/**
|
163 |
+
* Register available API resources
|
164 |
+
*
|
165 |
+
* @since 2.1
|
166 |
+
* @param object $server the REST server
|
167 |
+
*/
|
168 |
+
public function register_resources($server)
|
169 |
+
{
|
170 |
+
|
171 |
+
$api_classes = apply_filters('aftership_api_classes',
|
172 |
+
array(
|
173 |
+
'AfterShip_API_Orders',
|
174 |
+
)
|
175 |
+
);
|
176 |
+
|
177 |
+
foreach ($api_classes as $api_class) {
|
178 |
+
$this->$api_class = new $api_class($server);
|
179 |
+
}
|
180 |
+
}
|
181 |
+
|
182 |
+
}
|
trunk/class-aftership-dependencies.php
ADDED
@@ -0,0 +1,35 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
<?php
|
2 |
+
class AfterShip_Dependencies {
|
3 |
+
|
4 |
+
private static $active_plugins;
|
5 |
+
|
6 |
+
public static function init() {
|
7 |
+
|
8 |
+
self::$active_plugins = (array) get_option( 'active_plugins', array() );
|
9 |
+
|
10 |
+
if ( is_multisite() )
|
11 |
+
self::$active_plugins = array_merge( self::$active_plugins, get_site_option( 'active_sitewide_plugins', array() ) );
|
12 |
+
}
|
13 |
+
|
14 |
+
public static function plugin_active_check($plugin){
|
15 |
+
if ( ! self::$active_plugins ) self::init();
|
16 |
+
if (is_array($plugin)) {
|
17 |
+
foreach ($plugin as $path) {
|
18 |
+
if (in_array( $path, self::$active_plugins ) || array_key_exists( $path, self::$active_plugins )) {
|
19 |
+
return true;
|
20 |
+
}
|
21 |
+
}
|
22 |
+
return false;
|
23 |
+
} else {
|
24 |
+
return in_array( $plugin, self::$active_plugins ) || array_key_exists( $plugin, self::$active_plugins );
|
25 |
+
}
|
26 |
+
|
27 |
+
}
|
28 |
+
|
29 |
+
public static function woocommerce_active_check() {
|
30 |
+
return self::plugin_active_check('woocommerce/woocommerce.php');
|
31 |
+
}
|
32 |
+
|
33 |
+
}
|
34 |
+
|
35 |
+
|
trunk/class-aftership-settings.php
ADDED
@@ -0,0 +1,295 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
<?php
|
2 |
+
/**
|
3 |
+
* AfterShip Admin
|
4 |
+
*
|
5 |
+
* Handles AfterShip-Admin endpoint requests
|
6 |
+
*
|
7 |
+
* @author AfterShip
|
8 |
+
* @category Admin
|
9 |
+
* @package AfterShip
|
10 |
+
* @since 1.0
|
11 |
+
*/
|
12 |
+
|
13 |
+
if (!defined('ABSPATH')) exit; // Exit if accessed directly
|
14 |
+
|
15 |
+
/**
|
16 |
+
* Required functions
|
17 |
+
*/
|
18 |
+
if (!class_exists('AfterShip_Dependencies'))
|
19 |
+
require_once 'class-aftership-dependencies.php';
|
20 |
+
|
21 |
+
class AfterShip_Settings
|
22 |
+
{
|
23 |
+
/**
|
24 |
+
* Holds the values to be used in the fields callbacks
|
25 |
+
*/
|
26 |
+
private $options;
|
27 |
+
|
28 |
+
private $plugins;
|
29 |
+
|
30 |
+
/**
|
31 |
+
* Start up
|
32 |
+
*/
|
33 |
+
public function __construct()
|
34 |
+
{
|
35 |
+
$this->plugins[] = array(
|
36 |
+
'value' => 'aftership',
|
37 |
+
'label' => 'AfterShip',
|
38 |
+
'path' => 'aftership-woocommerce-tracking/aftership.php'
|
39 |
+
);
|
40 |
+
$this->plugins[] = array(
|
41 |
+
'value' => 'wc-shipment-tracking',
|
42 |
+
'label' => 'WooCommerce Shipment Tracking',
|
43 |
+
'path' => array('woocommerce-shipment-tracking/shipment-tracking.php', 'woocommerce-shipment-tracking/woocommerce-shipment-tracking.php')
|
44 |
+
);
|
45 |
+
|
46 |
+
add_action('admin_menu', array($this, 'add_plugin_page'));
|
47 |
+
add_action('admin_init', array($this, 'page_init'));
|
48 |
+
add_action('admin_print_styles', array($this, 'admin_styles'));
|
49 |
+
add_action('admin_print_scripts', array(&$this, 'library_scripts'));
|
50 |
+
}
|
51 |
+
|
52 |
+
|
53 |
+
public function admin_styles()
|
54 |
+
{
|
55 |
+
wp_enqueue_style('aftership_styles_chosen', plugins_url(basename(dirname(__FILE__))) . '/assets/plugin/chosen/chosen.min.css');
|
56 |
+
wp_enqueue_style('aftership_styles', plugins_url(basename(dirname(__FILE__))) . '/assets/css/admin.css');
|
57 |
+
}
|
58 |
+
|
59 |
+
public function library_scripts()
|
60 |
+
{
|
61 |
+
wp_enqueue_script('aftership_styles_chosen_jquery', plugins_url(basename(dirname(__FILE__))) . '/assets/plugin/chosen/chosen.jquery.min.js');
|
62 |
+
wp_enqueue_script('aftership_styles_chosen_proto', plugins_url(basename(dirname(__FILE__))) . '/assets/plugin/chosen/chosen.proto.min.js');
|
63 |
+
wp_enqueue_script('aftership_script_util', plugins_url(basename(dirname(__FILE__))) . '/assets/js/util.js');
|
64 |
+
wp_enqueue_script('aftership_script_couriers', plugins_url(basename(dirname(__FILE__))) . '/assets/js/couriers.js');
|
65 |
+
wp_enqueue_script('aftership_script_setting', plugins_url(basename(dirname(__FILE__))) . '/assets/js/setting.js');
|
66 |
+
}
|
67 |
+
|
68 |
+
/**
|
69 |
+
* Add options page
|
70 |
+
*/
|
71 |
+
public function add_plugin_page()
|
72 |
+
{
|
73 |
+
// This page will be under "Settings"
|
74 |
+
add_options_page(
|
75 |
+
'AfterShip Settings Admin',
|
76 |
+
'AfterShip',
|
77 |
+
'manage_options',
|
78 |
+
'aftership-setting-admin',
|
79 |
+
array($this, 'create_admin_page')
|
80 |
+
);
|
81 |
+
}
|
82 |
+
|
83 |
+
/**
|
84 |
+
* Options page callback
|
85 |
+
*/
|
86 |
+
public function create_admin_page()
|
87 |
+
{
|
88 |
+
// Set class property
|
89 |
+
$this->options = get_option('aftership_option_name');
|
90 |
+
?>
|
91 |
+
<div class="wrap">
|
92 |
+
<?php screen_icon(); ?>
|
93 |
+
<h2>AfterShip Settings</h2>
|
94 |
+
|
95 |
+
<form method="post" action="options.php">
|
96 |
+
<?php
|
97 |
+
// This prints out all hidden setting fields
|
98 |
+
settings_fields('aftership_option_group');
|
99 |
+
do_settings_sections('aftership-setting-admin');
|
100 |
+
submit_button();
|
101 |
+
?>
|
102 |
+
</form>
|
103 |
+
</div>
|
104 |
+
<?php
|
105 |
+
}
|
106 |
+
|
107 |
+
/**
|
108 |
+
* Register and add settings
|
109 |
+
*/
|
110 |
+
public function page_init()
|
111 |
+
{
|
112 |
+
register_setting(
|
113 |
+
'aftership_option_group', // Option group
|
114 |
+
'aftership_option_name', // Option name
|
115 |
+
array($this, 'sanitize') // Sanitize
|
116 |
+
);
|
117 |
+
|
118 |
+
add_settings_section(
|
119 |
+
'aftership_setting_section_id', // ID
|
120 |
+
'', // Title
|
121 |
+
array($this, 'print_section_info'), // Callback
|
122 |
+
'aftership-setting-admin' // Page
|
123 |
+
);
|
124 |
+
|
125 |
+
add_settings_field(
|
126 |
+
'plugin',
|
127 |
+
'Plugin',
|
128 |
+
array($this, 'plugin_callback'),
|
129 |
+
'aftership-setting-admin',
|
130 |
+
'aftership_setting_section_id'
|
131 |
+
);
|
132 |
+
|
133 |
+
add_settings_field(
|
134 |
+
'couriers',
|
135 |
+
'Couriers',
|
136 |
+
array($this, 'couriers_callback'),
|
137 |
+
'aftership-setting-admin',
|
138 |
+
'aftership_setting_section_id'
|
139 |
+
);
|
140 |
+
|
141 |
+
add_settings_field(
|
142 |
+
'use_track_button',
|
143 |
+
'Display Track Button at Order History Page',
|
144 |
+
array($this, 'track_button_callback'),
|
145 |
+
'aftership-setting-admin',
|
146 |
+
'aftership_setting_section_id'
|
147 |
+
);
|
148 |
+
|
149 |
+
add_settings_field(
|
150 |
+
'custom_domain',
|
151 |
+
'Display Tracking Information at Custom Domain',
|
152 |
+
array($this, 'custom_domain_callback'),
|
153 |
+
'aftership-setting-admin',
|
154 |
+
'aftership_setting_section_id'
|
155 |
+
);
|
156 |
+
|
157 |
+
add_settings_field(
|
158 |
+
'track_message',
|
159 |
+
'Content',
|
160 |
+
array($this, 'track_message_callback'),
|
161 |
+
'aftership-setting-admin',
|
162 |
+
'aftership_setting_section_id'
|
163 |
+
);
|
164 |
+
}
|
165 |
+
|
166 |
+
/**
|
167 |
+
* Sanitize each setting field as needed
|
168 |
+
*
|
169 |
+
* @param array $input Contains all settings fields as array keys
|
170 |
+
*/
|
171 |
+
public function sanitize($input)
|
172 |
+
{
|
173 |
+
$new_input = array();
|
174 |
+
|
175 |
+
if (isset($input['couriers'])) {
|
176 |
+
$new_input['couriers'] = sanitize_text_field($input['couriers']);
|
177 |
+
}
|
178 |
+
|
179 |
+
if (isset($input['custom_domain'])) {
|
180 |
+
$new_input['custom_domain'] = sanitize_text_field($input['custom_domain']);
|
181 |
+
}
|
182 |
+
|
183 |
+
if (isset($input['plugin'])) {
|
184 |
+
$new_input['plugin'] = sanitize_text_field($input['plugin']);
|
185 |
+
}
|
186 |
+
|
187 |
+
if (isset($input['track_message_1'])) {
|
188 |
+
$postfix = '';
|
189 |
+
if (substr($input['track_message_1'], -1) == ' ') {
|
190 |
+
$postfix = ' ';
|
191 |
+
}
|
192 |
+
$new_input['track_message_1'] = sanitize_text_field($input['track_message_1']) . $postfix;
|
193 |
+
}
|
194 |
+
|
195 |
+
if (isset($input['track_message_2'])) {
|
196 |
+
$postfix = '';
|
197 |
+
if (substr($input['track_message_2'], -1) == ' ') {
|
198 |
+
$postfix = ' ';
|
199 |
+
}
|
200 |
+
$new_input['track_message_2'] = sanitize_text_field($input['track_message_2']) . $postfix;
|
201 |
+
}
|
202 |
+
|
203 |
+
if (isset($input['use_track_button'])) {
|
204 |
+
$new_input['use_track_button'] = true;
|
205 |
+
}
|
206 |
+
|
207 |
+
return $new_input;
|
208 |
+
}
|
209 |
+
|
210 |
+
/**
|
211 |
+
* Print the Section text
|
212 |
+
*/
|
213 |
+
public function print_section_info()
|
214 |
+
{
|
215 |
+
//print 'Enter your settings below:';
|
216 |
+
}
|
217 |
+
|
218 |
+
public function couriers_callback()
|
219 |
+
{
|
220 |
+
|
221 |
+
$couriers = array();
|
222 |
+
if (isset($this->options['couriers'])) {
|
223 |
+
$couriers = explode(',', $this->options['couriers']);
|
224 |
+
}
|
225 |
+
|
226 |
+
// print_r($couriers);
|
227 |
+
echo '<select data-placeholder="Please select couriers" id="couriers_select" class="chosen-select " multiple style="width:100%">';
|
228 |
+
echo '</select>';
|
229 |
+
// echo '<br><a href="https://www.aftership.com/settings/courier" target="_blank">Update carrier list</a>';
|
230 |
+
echo '<input type="hidden" id="couriers" name="aftership_option_name[couriers]" value="' . implode(",", $couriers) . '"/>';
|
231 |
+
|
232 |
+
}
|
233 |
+
|
234 |
+
public function plugin_callback()
|
235 |
+
{
|
236 |
+
|
237 |
+
$options = "";
|
238 |
+
foreach ($this->plugins as $plugin) {
|
239 |
+
//print_r($plugin);
|
240 |
+
if (AfterShip_Dependencies::plugin_active_check($plugin['path'])) {
|
241 |
+
$option = '<option value="' . $plugin['value'] . '"';
|
242 |
+
|
243 |
+
if (isset($this->options['plugin']) && esc_attr($this->options['plugin']) == $plugin['value']) {
|
244 |
+
$option .= ' selected="selected"';
|
245 |
+
}
|
246 |
+
|
247 |
+
$option .= '>' . $plugin['label'] . '</option>';
|
248 |
+
$options .= $option;
|
249 |
+
}
|
250 |
+
}
|
251 |
+
|
252 |
+
printf(
|
253 |
+
'<select id="plugin" name="aftership_option_name[plugin]" class="aftership_dropdown">' . $options . '</select>'
|
254 |
+
);
|
255 |
+
}
|
256 |
+
|
257 |
+
public function custom_domain_callback()
|
258 |
+
{
|
259 |
+
printf(
|
260 |
+
'<input type="text" id="custom_domain" name="aftership_option_name[custom_domain]" value="%s" style="width:100%%">',
|
261 |
+
isset($this->options['custom_domain']) ? $this->options['custom_domain'] : 'track.aftership.com'
|
262 |
+
);
|
263 |
+
}
|
264 |
+
|
265 |
+
public function track_message_callback()
|
266 |
+
{
|
267 |
+
printf(
|
268 |
+
'<input type="text" id="track_message_1" name="aftership_option_name[track_message_1]" value="%s" style="width:100%%">',
|
269 |
+
isset($this->options['track_message_1']) ? $this->options['track_message_1'] : 'Your order was shipped via '
|
270 |
+
);
|
271 |
+
printf('<br/>');
|
272 |
+
printf(
|
273 |
+
'<input type="text" id="track_message_2" name="aftership_option_name[track_message_2]" value="%s" style="width:100%%">',
|
274 |
+
isset($this->options['track_message_2']) ? $this->options['track_message_2'] : 'Tracking number is '
|
275 |
+
);
|
276 |
+
printf('<br/>');
|
277 |
+
printf('<br/>');
|
278 |
+
printf('<b>Demo:</b>');
|
279 |
+
printf(
|
280 |
+
'<div id="track_message_demo_1" style="width:100%%"></div>'
|
281 |
+
);
|
282 |
+
}
|
283 |
+
|
284 |
+
public function track_button_callback()
|
285 |
+
{
|
286 |
+
printf(
|
287 |
+
'<label><input type="checkbox" id="use_track_button" name="aftership_option_name[use_track_button]" %s>Use Track Button</label>',
|
288 |
+
(isset($this->options['use_track_button']) && $this->options['use_track_button'] === true) ? 'checked="checked"' : ''
|
289 |
+
);
|
290 |
+
}
|
291 |
+
}
|
292 |
+
|
293 |
+
|
294 |
+
if (is_admin())
|
295 |
+
$aftership_settings = new AfterShip_Settings();
|
trunk/readme.txt
ADDED
@@ -0,0 +1,205 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
=== Plugin Name ===
|
2 |
+
Contributors: aftership
|
3 |
+
Donate link: https://www.aftership.com/
|
4 |
+
Tags: shipping, tracking, ups, usps, fedex, dhl, tnt, dpd, post, shipment, woocommerce, tracking number, aftership, package tracking, fulfilment, tracking link, carrier, courier, woo commerce, woocommerce shipment tracking, shipping details plugin, widget, shipstation, track, package
|
5 |
+
Requires at least: 2.9
|
6 |
+
Tested up to: 4.2.2
|
7 |
+
Stable tag: 1.7.7
|
8 |
+
License: GPLv2 or later
|
9 |
+
License URI: http://www.gnu.org/licenses/gpl-2.0.html
|
10 |
+
|
11 |
+
Auto import tracking of all your shipments in one place to WooCommerce (Free), branded tracking page to view order status in one click and ensure great post-purchase experience for your customers, send email / SMS delivery notifications to engage your customers after sales (Premium).
|
12 |
+
AfterShip is free for 100 first shipments, then try Premium.
|
13 |
+
|
14 |
+
== Description ==
|
15 |
+
|
16 |
+
###Top Shipment Tracking Plugin (Free)
|
17 |
+
By installing AfterShip plugin, you can automatically add Tracking Number and Courier fields to your admin panel. After you fulfill an order, simply enter the tracking number and select a courier at WooCommerce, the same info will be displayed at customer's order history page. AfterShip supports over 360+ carriers worldwide, you can select couriers by [signing up a free AfterShip account](https://secure.aftership.com/signup).
|
18 |
+
|
19 |
+
###Display tracking info at order history page (Free)
|
20 |
+
The plugin allows you to insert the AfterShip Track Button to order history page, so that your customers can track the latest order status in one click.
|
21 |
+
|
22 |
+
###Support 360+ International Courier (Free)
|
23 |
+
AfterShip supports UPS tracking, FedEx tracking, USPS tracking, DHL tracking and shipment tracking of over 360+ carriers worldwide. Please scroll down to see the full list of our supported carriers.
|
24 |
+
|
25 |
+
|
26 |
+
###Track all shipments in one place (Free)
|
27 |
+
By setting up an auto import of tracking numbers to AfterShip, you can get the latest tracking info of all your shipments in one place. Each free account comes with a Dashboard to monitor current statuses of all shipments. You can also filter your shipments by dates, statuses, couriers and destination. Find out if all your shipments are delivered on time and discover any exceptions. Support [WooCommerce Shipment Tracking Plugin](http://www.woothemes.com/products/shipment-tracking/) as well.
|
28 |
+
|
29 |
+
###Branded Tracking Page (Free)
|
30 |
+
|
31 |
+
AfterShip automatically generates a tracking page for each shipment. Customize tracking page by adding your brand logo, store URL and Instagram pictures to improve SEO and generate more sales. You can also embed the [AfterShip Track Button](http://support.aftership.com/article/111-how-can-i-add-track-button-to-wordpress-or-woocommerce) to allow tracking at your store. Improve your customer experience on tracking.
|
32 |
+
|
33 |
+
###Notify customers of delivery updates (Premium)
|
34 |
+
Upgrade to [Premium](https://www.aftership.com/pricing) to automatically send out delivery notifications to customers or yourself. Your choice of notification triggers - In transit, Out for delivery, Delivered, Failed delivery attempt or Exceptions. Use your own email to send out notifications, and customize messages to add store logo, URL, a tracking link to get more returned customers after shipping!
|
35 |
+
|
36 |
+
[youtube http://www.youtube.com/watch?v=1zCCx8Ap9ms]
|
37 |
+
|
38 |
+
###Full list of supported carriers (360+):
|
39 |
+
**①. US, Canada & Global Tracking (35)**
|
40 |
+
ABF Freight • APC Postal Logistics • Aramex • Asendia USA • Canada Post • Canpar Courier • Con-way Freight • DACHSER • DHL Express • DHL eCommerce • DHL Express (Piece ID) • DPD • DSV • Echo • Ensenda • Estes • FedEx • FedEx Freight • Globegistics Inc. • Greyhound • i-parcel • LaserShip • Newgistics • Old Dominion Freight Line • OnTrac • Purolator • RL Carriers • RR Donnelley • TNT • TNT Reference • UPS • UPS Freight • UPS Mail Innovations • USPS • YRC
|
41 |
+
|
42 |
+
**②. UK & Ireland Tracking (30)**
|
43 |
+
4Square Group • An Post • APC Overnight • Arrow XL • Asendia UK • Collect+ • Deltec Courier • DPD Ireland • DPD UK • Fastway Ireland • FedEx UK • Hermesworld • Homedirect Logistics • Interlink Express • myHermes UK • Nightline • Norsk Global • Panther • Parcel Force • Royal Mail • SkyNet Worldwide Express • Skynet Worldwide Express UK • TNT UK • TNT UK Reference • Tuffnells Parcels Express • UK Mail • XDP Express • XDP Express Reference • Yodel Domestic • Yodel International
|
44 |
+
|
45 |
+
**③. Europe Tracking (93)**
|
46 |
+
ACS Courier • Asendia Germany • ASM • Austrian Post (Express) • Austrian Post (Registered) • Belpost • Bert Transport • Bulgarian Posts • JP BH Pošta • Belgium Post • bpost international • BRT Bartolini • CBL Logistics • Česká Pošta • Chronopost France • Chronopost Portugal • Colis Privé • Colissimo • Correos Express • Cyprus Post • Post Danmark • DB Schenker Sweden • Deutsche Post Mail • DHL Benelux • DHL 2-Mann-Handling • DHL Spain Domestic • Deutsche Post DHL • DHL Netherlands • DHL Poland Domestic • DHL Parcel NL • Direct Link • DMM Network • DPD Germany • DPD Poland • Easy Mail • ELTA Hellenic Post • Envialia • Exapaq • FERCAM Logistics & Transport • Geodis Calberson France • GLS • GLS Italy • GLS Netherlands • Hermes Germany • Hrvatska Pošta • IMX Mail • InPost Paczkomaty • International Seur • Italy SDA • Kuehne + Nagel • La Poste • Lietuvos Paštas • Magyar Posta • Matkahuolto • Mondial Relay • MRW • NACEX Spain • Nova Poshta • FedEx Poland Domestic • Packlink • Poczta Polska • Portugal CTT • Portugal Seur • Poșta Română • Poste Italiane • Poste Italiane Paccocelere • Posten Norge / Bring • Itella Posti • PostNL Domestic • PostNL International 3S • PostNL International • PostNord Logistics • Iceland Post • PTT Posta • Raben Group • Redur Spain • Russian Post • SGT Corriere Espresso • Teliway SIC Express • Siodemka • Correos de España • Spanish Seur • Speed Couriers • Sweden Posten • Swiss Post • Geniki Taxydromiki • TNT-Click Italy • TNT France • TNT Italy • Nexive (TNT Post Italy) • TrakPak • TransMission • UkrPoshta
|
47 |
+
|
48 |
+
**④. Asia & China Tracking (125)**
|
49 |
+
|
50 |
+
2GO • ABX Express • AIR21 • Airpak Express • Airspeed International Corporation • Bluedart • Cambodia Post • City-Link Express • CJ GLS • Delcart • Delhivery • Delivree King • Detrack • DHL Global Mail Asia • Dotzot • DPEX • DTDC India • Dynamic Logistics • Ecargo • Ecom Express • Fastrak Services • First Flight Couriers • First Logistics • Gati-KWE • GDEX • Giao hà ng nhanh • GoJavas • India Post Domestic • India Post International • Jam Express • Japan Post • Jayon Express (JEX) • Jet-Ship Worldwide • JNE • Kangaroo Worldwide Express • Kerry Express Thailand • Kerry TTC Express • KGM Hub • Korea Post • Lao Post • LBC Express • Lion Parcel • Malaysia Post EMS / Poslaju • Malaysia Post - Registered • Maxcellents Pte Ltd • Mypostonline • Nationwide Express • Nhans Solutions • Ninja Van • Ninja Van Malaysia • NuvoEx • Omni Parcel • Pandu Logistics • Parcel Express • Parcelled.in • Parcel Post Singapore • Pos Indonesia Domestic • Pos Indonesia Int'l • Professional Couriers • Quantium • Qxpress • RAF Philippines • Red Express • Red Express Waybill • RPX Indonesia • RPX Online • RZY Express • Safexpress • Sagawa • Singapore Post • Singapore Speedpost • SingParcel Service • SkyNet Malaysia • Spreadel • SRE Korea • Taiwan Post • Yamato Japan • TAQBIN Malaysia • TAQBIN Singapore • Thailand Thai Post • Tiki • ViettelPost • Vietnam Post • Vietnam Post EMS • Wahana • Xend Express • XpressBees • Zalora 7-Eleven • 17 Post Service • 4PX • Best Express • AuPost China • BOXC • China EMS • China Post • CNE Express • Cuckoo Express • DHL Hong Kong • EC-Firstclass • EC Express • EMPS Express • Equick China • Flyt Express • GoFly • Hua Han Logistics • Hong Kong Post • JCEX • Logistic Worldwide Express • Nanjing Woyuan • One World Express • Post56 • PayPal Package • SEKO Logistics • S.F. Express • S.F International • STO Express • DPEX China • TAQBIN Hong Kong • TGX • WeDo Logistics • WishPost • Yanwen • Yunda Express • Yun Express • ZJS International
|
51 |
+
|
52 |
+
**⑤. Australia & New Zealand Tracking (14)**
|
53 |
+
|
54 |
+
ADSOne • Australia Post • Bonds Couriers • CourierPost • Couriers Please • Fastway Australia • Fastway New Zealand • New Zealand Post • StarTrack • Star Track Express • TNT Australia • Toll IPEC • Toll Priority • UBI Logistics Australia
|
55 |
+
|
56 |
+
**⑥. Latin America, Middle East & Other Tracking (27)**
|
57 |
+
|
58 |
+
4-72 Entregando • Mexico AeroFlash • Brazil Correios • Correo Argentino • Correos Chile • Correos de Mexico • Cosmetics Now • Courier Plus • Courier IT • Dawn Wing • DPE South Africa • Emirates Post • Estafeta • Fastway South Africa • Israel Post • Israel Post Domestic • Mexico Redpack • Mexico Senda Express • NiPost • OCA Argentina • Post Serbia • RAM • South African Post Office • Saudi Post • SMSA Express • Specialised Freight • Speedex Courier
|
59 |
+
|
60 |
+
|
61 |
+
== Installation ==
|
62 |
+
|
63 |
+
1. [Sign up AfterShip account for FREE](https://secure.aftership.com/signup)
|
64 |
+
2. [Download AfterShip plugin](http://downloads.wordpress.org/plugin/aftership-woocommerce-tracking.zip), then install and activate at wordpress.
|
65 |
+
3. Select AfterShip Plugin or [WooCommerce Shipment Tracking Plugin](http://www.woothemes.com/products/shipment-tracking/) for entering tracking number
|
66 |
+
4. Check `Use Track Button` for displaying tracking info at order history page
|
67 |
+
5. Generate [AfterShip's WordPress API Key](http://aftership.uservoice.com/knowledgebase/articles/405909) under `Users` > `Your Profile`
|
68 |
+
6. Input `Store URL` and `AfterShip's WordPress API Key` at [AfterShip WooCommerce page](https://www.aftership.com/apps/woocommerce)
|
69 |
+
|
70 |
+
*** This plugin requires at least PHP 5.2.4
|
71 |
+
*** This plugin requires at least WooCommerce 2.1
|
72 |
+
|
73 |
+
###Further Reading
|
74 |
+
|
75 |
+
* [How to insert AfterShip Track Button to WordPress or WooCommerce](https://aftership.uservoice.com/knowledgebase/articles/268665)
|
76 |
+
* [Premium account pricing](https://www.aftership.com/pricing)
|
77 |
+
* [List of supported couriers](https://www.aftership.com/courier)
|
78 |
+
* [Free vs Premium](https://www.aftership.com/pricing)
|
79 |
+
* [SMS Charges](https://www.aftership.com/pricing)
|
80 |
+
* [Isn’t my store or courier sending notifications already?](https://aftership.uservoice.com/knowledgebase/articles/169634-isn-t-my-store-or-courier-sending-notifications-al)
|
81 |
+
|
82 |
+
|
83 |
+
== Frequently Asked Questions ==
|
84 |
+
|
85 |
+
You'll find the FAQ on [AfterShip.com](https://aftership.uservoice.com/knowledgebase)
|
86 |
+
|
87 |
+
|
88 |
+
== Screenshots ==
|
89 |
+
|
90 |
+
1. Add tracking number and carrier to WooCommerce
|
91 |
+
2. Display tracking info at order history page
|
92 |
+
3. Support tracking of UPS, DHL, FedEx, USPS and 360+ carriers
|
93 |
+
4. AfterShip dashboard
|
94 |
+
5. Track all shipments in one place
|
95 |
+
6. View exception, and filter by status
|
96 |
+
7. Automatically send out delivery notifications
|
97 |
+
|
98 |
+
== Changelog ==
|
99 |
+
|
100 |
+
= 1.7.6 =
|
101 |
+
* Add new couriers
|
102 |
+
|
103 |
+
= 1.7.4 =
|
104 |
+
* Remove deprecated warning on Woocommerce 3
|
105 |
+
|
106 |
+
= 1.7.2 =
|
107 |
+
* Add new couriers
|
108 |
+
|
109 |
+
= 1.6.8 =
|
110 |
+
* Fix compatibility issue with Sendcloud plugin
|
111 |
+
|
112 |
+
= 1.6.7 =
|
113 |
+
* Add support for more couriers
|
114 |
+
|
115 |
+
= 1.6.6 =
|
116 |
+
* Fix courier list is sometimes empty
|
117 |
+
|
118 |
+
= 1.6.5 =
|
119 |
+
* Support new version of Woocommerce Shipment Tracking plugin
|
120 |
+
|
121 |
+
= 1.6.4 =
|
122 |
+
* Add new couriers
|
123 |
+
|
124 |
+
= 1.6.3 =
|
125 |
+
* Improved compatibility with PHP7
|
126 |
+
|
127 |
+
= 1.6.2 =
|
128 |
+
* Handling API key in more reliable way
|
129 |
+
|
130 |
+
= 1.6.1 =
|
131 |
+
* Fixed Woocommerce Tracking plugin provider error
|
132 |
+
|
133 |
+
= 1.6.0 =
|
134 |
+
* Custom tracking URL support
|
135 |
+
|
136 |
+
= 1.5.0 =
|
137 |
+
* Add credentials verification
|
138 |
+
* Enable importing note from customer
|
139 |
+
* Add new couriers
|
140 |
+
|
141 |
+
= 1.4.8 =
|
142 |
+
* Add new couriers
|
143 |
+
|
144 |
+
= 1.4.7 =
|
145 |
+
* Add new couriers
|
146 |
+
|
147 |
+
= 1.4.6 =
|
148 |
+
* Add new couriers
|
149 |
+
|
150 |
+
= 1.4.5 =
|
151 |
+
* Compatible up to WordPress 4.2.2
|
152 |
+
* Add new couriers
|
153 |
+
|
154 |
+
= 1.4.4 =
|
155 |
+
* Add new couriers
|
156 |
+
|
157 |
+
= 1.4.3 =
|
158 |
+
* Add new couriers
|
159 |
+
* Disable unused field for import orders to AfterShip system
|
160 |
+
|
161 |
+
= 1.4.2 =
|
162 |
+
* Fix carrier list data in setting page, to support new dropdown menu in Wordpress 4.1
|
163 |
+
|
164 |
+
= 1.4.1 =
|
165 |
+
* Add order by filter option
|
166 |
+
|
167 |
+
= 1.4.0 =
|
168 |
+
* Remove courier url and telephone no.
|
169 |
+
|
170 |
+
= 1.3.9 =
|
171 |
+
* Disable get_cart_discount() and get_order_discount() as it's deprecated in WooCommerce 2.3
|
172 |
+
|
173 |
+
= 1.3.8 =
|
174 |
+
* Force load the script to display the plugin if the script didn't execute normally after 2 seconds while the page loaded.
|
175 |
+
|
176 |
+
= 1.3.7 =
|
177 |
+
* Add new courier
|
178 |
+
|
179 |
+
= 1.3.6 =
|
180 |
+
* Fix the display problem of required fields in order history page
|
181 |
+
|
182 |
+
= 1.3.5 =
|
183 |
+
* Fix carrier list data, to support new dropdown menu in Wordpress 4.1
|
184 |
+
|
185 |
+
= 1.3.4 =
|
186 |
+
* Fix the custom track message tailing space problem
|
187 |
+
|
188 |
+
= 1.3.3 =
|
189 |
+
* Add the fields config
|
190 |
+
|
191 |
+
= 1.3.2 =
|
192 |
+
* Support new couriers, please check out supported couriers in https://www.aftership.com/courier
|
193 |
+
* Support new required field, `tracking key` and `tracking destination country`
|
194 |
+
* Support custom track message on order history page
|
195 |
+
|
196 |
+
= 1.3.1 =
|
197 |
+
* Support 231 couriers, please check out supported couriers in https://www.aftership.com/courier
|
198 |
+
|
199 |
+
= 1.3.0 =
|
200 |
+
* Fix the redeclare class issues
|
201 |
+
|
202 |
+
|
203 |
+
== Upgrade Notice ==
|
204 |
+
|
205 |
+
No Upgrade Yet
|