Version Description
- Fix installation problem, php array
Download this release
Release Info
Developer | aftership |
Plugin | AfterShip – WooCommerce Tracking |
Version | 1.2.6 |
Comparing to | |
See all releases |
Code changes from version 1.2.5 to 1.2.6
- aftership.php +1 -1
- class-aftership-settings.php +1 -1
- readme.txt +4 -1
- trunk/aftership.php +474 -0
- trunk/api/class-aftership-api-authentication.php +126 -0
- trunk/api/class-aftership-api-json-handler.php +77 -0
- trunk/api/class-aftership-api-orders.php +462 -0
- trunk/api/class-aftership-api-resource.php +410 -0
- trunk/api/class-aftership-api-server.php +766 -0
- trunk/api/interface-aftership-api-handler.php +46 -0
- trunk/assets/css/admin.css +15 -0
- trunk/assets/js/admin.js +99 -0
- trunk/assets/js/couriers.js +1779 -0
- trunk/assets/js/setting.js +46 -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 +186 -0
- trunk/class-aftership-settings.php +231 -0
- trunk/readme.txt +181 -0
- trunk/woo-includes/class-wc-dependencies.php +30 -0
- trunk/woo-includes/woo-functions.php +15 -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.2.
|
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.2.6
|
7 |
Author: AfterShip
|
8 |
Author URI: http://aftership.com
|
9 |
|
class-aftership-settings.php
CHANGED
@@ -181,7 +181,7 @@ class AfterShip_Settings
|
|
181 |
|
182 |
public function couriers_callback(){
|
183 |
|
184 |
-
$couriers =
|
185 |
if (isset($this->options['couriers'])){
|
186 |
$couriers = explode(',', $this->options['couriers']);
|
187 |
}
|
181 |
|
182 |
public function couriers_callback(){
|
183 |
|
184 |
+
$couriers = array();
|
185 |
if (isset($this->options['couriers'])){
|
186 |
$couriers = explode(',', $this->options['couriers']);
|
187 |
}
|
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.0
|
7 |
-
Stable tag: 1.2.
|
8 |
License: GPLv2 or later
|
9 |
License URI: http://www.gnu.org/licenses/gpl-2.0.html
|
10 |
|
@@ -95,6 +95,9 @@ You'll find the FAQ on [AfterShip.com](https://aftership.uservoice.com/knowledge
|
|
95 |
|
96 |
== Changelog ==
|
97 |
|
|
|
|
|
|
|
98 |
= 1.2.5 =
|
99 |
* No longer require to input AfterShip API key at Wordpress
|
100 |
* Allow carrier selection at Wordpress
|
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.0
|
7 |
+
Stable tag: 1.2.6
|
8 |
License: GPLv2 or later
|
9 |
License URI: http://www.gnu.org/licenses/gpl-2.0.html
|
10 |
|
95 |
|
96 |
== Changelog ==
|
97 |
|
98 |
+
= 1.2.6 =
|
99 |
+
* Fix installation problem, php array
|
100 |
+
|
101 |
= 1.2.5 =
|
102 |
* No longer require to input AfterShip API key at Wordpress
|
103 |
* Allow carrier selection at Wordpress
|
trunk/aftership.php
ADDED
@@ -0,0 +1,474 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
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.2.6
|
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('woo-includes/woo-functions.php');
|
23 |
+
|
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('admin_print_styles', array(&$this, 'admin_styles'));
|
67 |
+
add_action('add_meta_boxes', array(&$this, 'add_meta_box'));
|
68 |
+
add_action('woocommerce_process_shop_order_meta', array(&$this, 'save_meta_box'), 0, 2);
|
69 |
+
add_action('plugins_loaded', array($this, 'load_plugin_textdomain'));
|
70 |
+
|
71 |
+
$this->couriers = $options['couriers'];
|
72 |
+
}
|
73 |
+
|
74 |
+
// View Order Page
|
75 |
+
$this->plugin = $plugin;
|
76 |
+
}else{
|
77 |
+
$this->plugin = '';
|
78 |
+
}
|
79 |
+
|
80 |
+
if (isset($options['use_track_button'])) {
|
81 |
+
$this->use_track_button = $options['use_track_button'];
|
82 |
+
}else{
|
83 |
+
$this->use_track_button = false;
|
84 |
+
}
|
85 |
+
|
86 |
+
add_action('woocommerce_view_order', array(&$this, 'display_tracking_info'));
|
87 |
+
add_action('woocommerce_email_before_order_table', array(&$this, 'email_display'));
|
88 |
+
|
89 |
+
}
|
90 |
+
|
91 |
+
// user profile api key
|
92 |
+
add_action('show_user_profile', array($this, 'add_api_key_field'));
|
93 |
+
add_action('edit_user_profile', array($this, 'add_api_key_field'));
|
94 |
+
add_action('personal_options_update', array($this, 'generate_api_key'));
|
95 |
+
add_action('edit_user_profile_update', array($this, 'generate_api_key'));
|
96 |
+
|
97 |
+
register_activation_hook(__FILE__, array($this, 'install'));
|
98 |
+
}
|
99 |
+
|
100 |
+
public function install()
|
101 |
+
{
|
102 |
+
global $wp_roles;
|
103 |
+
|
104 |
+
if (class_exists('WP_Roles')) {
|
105 |
+
if (!isset($wp_roles)) {
|
106 |
+
$wp_roles = new WP_Roles();
|
107 |
+
}
|
108 |
+
}
|
109 |
+
|
110 |
+
if (is_object($wp_roles)) {
|
111 |
+
$wp_roles->add_cap('administrator', 'manage_aftership');
|
112 |
+
}
|
113 |
+
}
|
114 |
+
|
115 |
+
private function includes()
|
116 |
+
{
|
117 |
+
include_once('class-aftership-api.php');
|
118 |
+
include_once('class-aftership-settings.php');
|
119 |
+
}
|
120 |
+
|
121 |
+
/**
|
122 |
+
* Localisation
|
123 |
+
*/
|
124 |
+
public function load_plugin_textdomain()
|
125 |
+
{
|
126 |
+
load_plugin_textdomain('aftership', false, dirname(plugin_basename(__FILE__)) . '/languages/');
|
127 |
+
}
|
128 |
+
|
129 |
+
public function admin_styles()
|
130 |
+
{
|
131 |
+
wp_enqueue_style('aftership_styles_chosen', plugins_url(basename(dirname(__FILE__))) . '/assets/plugin/chosen/chosen.min.css');
|
132 |
+
wp_enqueue_style('aftership_styles', plugins_url(basename(dirname(__FILE__))) . '/assets/css/admin.css');
|
133 |
+
}
|
134 |
+
|
135 |
+
public function library_scripts()
|
136 |
+
{
|
137 |
+
wp_enqueue_script('aftership_styles_chosen_jquery', plugins_url(basename(dirname(__FILE__))) . '/assets/plugin/chosen/chosen.jquery.min.js');
|
138 |
+
wp_enqueue_script('aftership_styles_chosen_proto', plugins_url(basename(dirname(__FILE__))) . '/assets/plugin/chosen/chosen.proto.min.js');
|
139 |
+
wp_enqueue_script('aftership_script_util', plugins_url(basename(dirname(__FILE__))) . '/assets/js/util.js');
|
140 |
+
wp_enqueue_script('aftership_script_couriers', plugins_url(basename(dirname(__FILE__))) . '/assets/js/couriers.js');
|
141 |
+
wp_enqueue_script('aftership_script_admin', plugins_url(basename(dirname(__FILE__))) . '/assets/js/admin.js');
|
142 |
+
}
|
143 |
+
|
144 |
+
/**
|
145 |
+
* Add the meta box for shipment info on the order page
|
146 |
+
*
|
147 |
+
* @access public
|
148 |
+
*/
|
149 |
+
public function add_meta_box()
|
150 |
+
{
|
151 |
+
add_meta_box('woocommerce-aftership', __('AfterShip', 'wc_aftership'), array(&$this, 'meta_box'), 'shop_order', 'side', 'high');
|
152 |
+
}
|
153 |
+
|
154 |
+
/**
|
155 |
+
* Show the meta box for shipment info on the order page
|
156 |
+
*
|
157 |
+
* @access public
|
158 |
+
*/
|
159 |
+
public function meta_box()
|
160 |
+
{
|
161 |
+
|
162 |
+
// just draw the layout, no data
|
163 |
+
global $post;
|
164 |
+
|
165 |
+
$selected_provider = get_post_meta($post->ID, '_aftership_tracking_provider', true);
|
166 |
+
|
167 |
+
echo '<div id="aftership_wrapper">';
|
168 |
+
|
169 |
+
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%">';
|
170 |
+
if ($selected_provider == '') {
|
171 |
+
$selected_text = 'selected="selected"';
|
172 |
+
} else {
|
173 |
+
$selected_text = '';
|
174 |
+
}
|
175 |
+
echo '<option disabled ' . $selected_text . ' value="">Please Select</option>';
|
176 |
+
echo '</select>';
|
177 |
+
echo '<br><a href="options-general.php?page=aftership-setting-admin">Update carrier list</a>';
|
178 |
+
echo '<input type="hidden" id="aftership_tracking_provider_hidden" value="' . $selected_provider . '"/>';
|
179 |
+
echo '<input type="hidden" id="aftership_couriers_selected" value="' . $this->couriers . '"/>';
|
180 |
+
|
181 |
+
|
182 |
+
|
183 |
+
woocommerce_wp_text_input(array(
|
184 |
+
'id' => 'aftership_tracking_provider_name',
|
185 |
+
'label' => __('', 'wc_aftership'),
|
186 |
+
'placeholder' => '',
|
187 |
+
'description' => '',
|
188 |
+
'class' => 'hidden',
|
189 |
+
'value' => get_post_meta($post->ID, '_aftership_tracking_provider_name', true),
|
190 |
+
));
|
191 |
+
|
192 |
+
woocommerce_wp_text_input(array(
|
193 |
+
'id' => 'aftership_tracking_required_fields',
|
194 |
+
'label' => __('', 'wc_aftership'),
|
195 |
+
'placeholder' => '',
|
196 |
+
'description' => '',
|
197 |
+
'class' => 'hidden',
|
198 |
+
'value' => get_post_meta($post->ID, '_aftership_tracking_required_fields', true),
|
199 |
+
));
|
200 |
+
|
201 |
+
woocommerce_wp_text_input(array(
|
202 |
+
'id' => 'aftership_tracking_number',
|
203 |
+
'label' => __('Tracking number:', 'wc_aftership'),
|
204 |
+
'placeholder' => '',
|
205 |
+
'description' => '',
|
206 |
+
'value' => get_post_meta($post->ID, '_aftership_tracking_number', true),
|
207 |
+
));
|
208 |
+
|
209 |
+
woocommerce_wp_text_input(array(
|
210 |
+
'id' => 'aftership_tracking_shipdate',
|
211 |
+
'label' => __('Date shipped:', 'wc_aftership'),
|
212 |
+
'placeholder' => 'YYYY-MM-DD',
|
213 |
+
'description' => '',
|
214 |
+
'class' => 'date-picker-field hidden-field',
|
215 |
+
'value' => ($date = get_post_meta($post->ID, '_aftership_tracking_shipdate', true)) ? date('Y-m-d', $date) : ''
|
216 |
+
));
|
217 |
+
|
218 |
+
woocommerce_wp_text_input(array(
|
219 |
+
'id' => 'aftership_tracking_postal',
|
220 |
+
'label' => __('Postal Code:', 'wc_aftership'),
|
221 |
+
'placeholder' => '',
|
222 |
+
'description' => '',
|
223 |
+
'class' => 'hidden-field',
|
224 |
+
'value' => get_post_meta($post->ID, '_aftership_tracking_postal', true),
|
225 |
+
));
|
226 |
+
|
227 |
+
woocommerce_wp_text_input(array(
|
228 |
+
'id' => 'aftership_tracking_account',
|
229 |
+
'label' => __('Account name:', 'wc_aftership'),
|
230 |
+
'placeholder' => '',
|
231 |
+
'description' => '',
|
232 |
+
'class' => 'hidden-field',
|
233 |
+
'value' => get_post_meta($post->ID, '_aftership_tracking_account', true),
|
234 |
+
));
|
235 |
+
|
236 |
+
echo '</div>';
|
237 |
+
}
|
238 |
+
|
239 |
+
/**
|
240 |
+
* Order Downloads Save
|
241 |
+
*
|
242 |
+
* Function for processing and storing all order downloads.
|
243 |
+
*/
|
244 |
+
public function save_meta_box($post_id, $post)
|
245 |
+
{
|
246 |
+
if (isset($_POST['aftership_tracking_number'])) {
|
247 |
+
|
248 |
+
// Download data
|
249 |
+
$tracking_provider = woocommerce_clean($_POST['aftership_tracking_provider']);
|
250 |
+
$tracking_number = woocommerce_clean($_POST['aftership_tracking_number']);
|
251 |
+
$tracking_provider_name = woocommerce_clean($_POST['aftership_tracking_provider_name']);
|
252 |
+
$tracking_required_fields = woocommerce_clean($_POST['aftership_tracking_required_fields']);
|
253 |
+
$shipdate = woocommerce_clean(strtotime($_POST['aftership_tracking_shipdate']));
|
254 |
+
$postal = woocommerce_clean($_POST['aftership_tracking_postal']);
|
255 |
+
$account = woocommerce_clean($_POST['aftership_tracking_account']);
|
256 |
+
|
257 |
+
// Update order data
|
258 |
+
update_post_meta($post_id, '_aftership_tracking_provider', $tracking_provider);
|
259 |
+
update_post_meta($post_id, '_aftership_tracking_number', $tracking_number);
|
260 |
+
update_post_meta($post_id, '_aftership_tracking_provider_name', $tracking_provider_name);
|
261 |
+
update_post_meta($post_id, '_aftership_tracking_required_fields', $tracking_required_fields);
|
262 |
+
update_post_meta($post_id, '_aftership_tracking_shipdate', $shipdate);
|
263 |
+
update_post_meta($post_id, '_aftership_tracking_postal', $postal);
|
264 |
+
update_post_meta($post_id, '_aftership_tracking_account', $account);
|
265 |
+
}
|
266 |
+
}
|
267 |
+
|
268 |
+
/**
|
269 |
+
* Display the API key info for a user
|
270 |
+
*
|
271 |
+
* @since 2.1
|
272 |
+
* @param WP_User $user
|
273 |
+
*/
|
274 |
+
public function add_api_key_field($user)
|
275 |
+
{
|
276 |
+
|
277 |
+
if (!current_user_can('manage_aftership'))
|
278 |
+
return;
|
279 |
+
|
280 |
+
if (current_user_can('edit_user', $user->ID)) {
|
281 |
+
?>
|
282 |
+
<h3>AfterShip</h3>
|
283 |
+
<table class="form-table">
|
284 |
+
<tbody>
|
285 |
+
<tr>
|
286 |
+
<th><label
|
287 |
+
for="aftership_wp_api_key"><?php _e('AfterShip\'s WordPress API Key', 'aftership'); ?></label>
|
288 |
+
</th>
|
289 |
+
<td>
|
290 |
+
<?php if (empty($user->aftership_wp_api_key)) : ?>
|
291 |
+
<input name="aftership_wp_generate_api_key" type="checkbox"
|
292 |
+
id="aftership_wp_generate_api_key" value="0"/>
|
293 |
+
<span class="description"><?php _e('Generate API Key', 'aftership'); ?></span>
|
294 |
+
<?php else : ?>
|
295 |
+
<code id="aftership_wp_api_key"><?php echo $user->aftership_wp_api_key ?></code>
|
296 |
+
<br/>
|
297 |
+
<input name="aftership_wp_generate_api_key" type="checkbox"
|
298 |
+
id="aftership_wp_generate_api_key" value="0"/>
|
299 |
+
<span class="description"><?php _e('Revoke API Key', 'aftership'); ?></span>
|
300 |
+
<?php endif; ?>
|
301 |
+
</td>
|
302 |
+
</tr>
|
303 |
+
</tbody>
|
304 |
+
</table>
|
305 |
+
<?php
|
306 |
+
}
|
307 |
+
}
|
308 |
+
|
309 |
+
/**
|
310 |
+
* Generate and save (or delete) the API keys for a user
|
311 |
+
*
|
312 |
+
* @since 2.1
|
313 |
+
* @param int $user_id
|
314 |
+
*/
|
315 |
+
public function generate_api_key($user_id)
|
316 |
+
{
|
317 |
+
|
318 |
+
if (current_user_can('edit_user', $user_id)) {
|
319 |
+
|
320 |
+
$user = get_userdata($user_id);
|
321 |
+
|
322 |
+
// creating/deleting key
|
323 |
+
if (isset($_POST['aftership_wp_generate_api_key'])) {
|
324 |
+
|
325 |
+
// consumer key
|
326 |
+
if (empty($user->aftership_wp_api_key)) {
|
327 |
+
|
328 |
+
$api_key = 'ck_' . hash('md5', $user->user_login . date('U') . mt_rand());
|
329 |
+
|
330 |
+
update_user_meta($user_id, 'aftership_wp_api_key', $api_key);
|
331 |
+
|
332 |
+
} else {
|
333 |
+
|
334 |
+
delete_user_meta($user_id, 'aftership_wp_api_key');
|
335 |
+
}
|
336 |
+
|
337 |
+
}
|
338 |
+
}
|
339 |
+
}
|
340 |
+
|
341 |
+
/**
|
342 |
+
* Display Shipment info in the frontend (order view/tracking page).
|
343 |
+
*
|
344 |
+
* @access public
|
345 |
+
*/
|
346 |
+
function display_tracking_info($order_id, $for_email = false)
|
347 |
+
{
|
348 |
+
if ($this->plugin == 'aftership') {
|
349 |
+
$this->display_order_aftership($order_id, $for_email);
|
350 |
+
} else if ($this->plugin == 'wc-shipment-tracking') { //$49
|
351 |
+
$this->display_order_wc_shipment_tracking($order_id, $for_email);
|
352 |
+
}
|
353 |
+
}
|
354 |
+
|
355 |
+
private function display_order_aftership($order_id, $for_email)
|
356 |
+
{
|
357 |
+
$tracking_provider = get_post_meta($order_id, '_aftership_tracking_provider', true);
|
358 |
+
$tracking_number = get_post_meta($order_id, '_aftership_tracking_number', true);
|
359 |
+
$tracking_provider_name = get_post_meta($order_id, '_aftership_tracking_provider_name', true);
|
360 |
+
$tracking_required_fields = get_post_meta($order_id, '_aftership_tracking_required_fields', true);
|
361 |
+
$date_shipped = get_post_meta($order_id, '_aftership_tracking_shipdate', true);
|
362 |
+
$postcode = get_post_meta($order_id, '_aftership_tracking_postal', true);
|
363 |
+
$account = get_post_meta($order_id, '_aftership_tracking_account', true);
|
364 |
+
|
365 |
+
if (!$tracking_provider)
|
366 |
+
return;
|
367 |
+
|
368 |
+
if (!$tracking_number)
|
369 |
+
return;
|
370 |
+
|
371 |
+
$provider_name = $tracking_provider_name;
|
372 |
+
$provider_required_fields = explode(",", $tracking_required_fields);
|
373 |
+
|
374 |
+
$date_shipped_str = '';
|
375 |
+
$postcode_str = '';
|
376 |
+
$account_str = '';
|
377 |
+
|
378 |
+
foreach ($provider_required_fields as $field) {
|
379 |
+
if ($field == 'tracking_ship_date') {
|
380 |
+
if ($date_shipped) {
|
381 |
+
$date_shipped_str = ' ' . sprintf(__('on %s', 'wc_shipment_tracking'), date_i18n(__('l jS F Y', 'wc_shipment_tracking'), $date_shipped));
|
382 |
+
}
|
383 |
+
} else if ($field == 'tracking_postal_code') {
|
384 |
+
if ($postcode) {
|
385 |
+
$postcode_str = ' ' . sprintf('The postal code is %s.', $postcode);
|
386 |
+
}
|
387 |
+
} else if ($field == 'tracking_account_number') {
|
388 |
+
if ($account) {
|
389 |
+
$account_str = ' ' . sprintf('The account is %s.', $account);
|
390 |
+
}
|
391 |
+
}
|
392 |
+
}
|
393 |
+
|
394 |
+
$provider_name = ' ' . __('via', 'wc_shipment_tracking') . ' <strong>' . $provider_name . '</strong>';
|
395 |
+
|
396 |
+
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));
|
397 |
+
|
398 |
+
if (!$for_email && $this->use_track_button) {
|
399 |
+
$this->display_track_button($tracking_provider, $tracking_number);
|
400 |
+
}
|
401 |
+
|
402 |
+
}
|
403 |
+
|
404 |
+
private function display_order_wc_shipment_tracking($order_id, $for_email)
|
405 |
+
{
|
406 |
+
if ($for_email || !$this->use_track_button) {
|
407 |
+
return;
|
408 |
+
}
|
409 |
+
|
410 |
+
$tracking = get_post_meta($order_id, '_tracking_number', true);
|
411 |
+
$sharp = strpos($tracking, '#');
|
412 |
+
$colon = strpos($tracking, ':');
|
413 |
+
if ($sharp && $colon && $sharp >= $colon) {
|
414 |
+
return;
|
415 |
+
} else if (!$sharp && $colon) {
|
416 |
+
return;
|
417 |
+
} else if ($sharp) {
|
418 |
+
$tracking_provider = substr($tracking, 0, $sharp);
|
419 |
+
if ($colon) {
|
420 |
+
$tracking_number = substr($tracking, $sharp + 1, $colon - $sharp - 1);
|
421 |
+
} else {
|
422 |
+
$tracking_number = substr($tracking, $sharp + 1, strlen($tracking));
|
423 |
+
}
|
424 |
+
} else {
|
425 |
+
$tracking_provider = '';
|
426 |
+
$tracking_number = $tracking;
|
427 |
+
}
|
428 |
+
if ($tracking_number) {
|
429 |
+
$this->display_track_button($tracking_provider, $tracking_number);
|
430 |
+
}
|
431 |
+
}
|
432 |
+
|
433 |
+
/**
|
434 |
+
* Display shipment info in customer emails.
|
435 |
+
*
|
436 |
+
* @access public
|
437 |
+
* @return void
|
438 |
+
*/
|
439 |
+
function email_display($order)
|
440 |
+
{
|
441 |
+
$this->display_tracking_info($order->id, true);
|
442 |
+
}
|
443 |
+
|
444 |
+
private function display_track_button($tracking_provider, $tracking_number)
|
445 |
+
{
|
446 |
+
|
447 |
+
$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")';
|
448 |
+
if (function_exists('wc_enqueue_js')) {
|
449 |
+
wc_enqueue_js($js);
|
450 |
+
} else {
|
451 |
+
global $woocommerce;
|
452 |
+
$woocommerce->add_inline_js($js);
|
453 |
+
}
|
454 |
+
|
455 |
+
$track_button = '<div id="as-root"></div><div class="as-track-button" data-slug="' . $tracking_provider . '" data-tracking-number="' . $tracking_number . '" data-support="true" data-width="400" data-size="normal" data-hide-tracking-number="true"></div>';
|
456 |
+
echo wpautop(sprintf('%s', $track_button));
|
457 |
+
echo "<br><br>";
|
458 |
+
}
|
459 |
+
}
|
460 |
+
|
461 |
+
if (!function_exists('getAfterShipInstance')) {
|
462 |
+
function getAfterShipInstance()
|
463 |
+
{
|
464 |
+
return AfterShip::Instance();
|
465 |
+
}
|
466 |
+
}
|
467 |
+
}
|
468 |
+
|
469 |
+
/**
|
470 |
+
* Register this class globally
|
471 |
+
*/
|
472 |
+
$GLOBALS['aftership'] = getAfterShipInstance();
|
473 |
+
|
474 |
+
}
|
trunk/api/class-aftership-api-authentication.php
ADDED
@@ -0,0 +1,126 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
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 |
+
|
80 |
+
// get aftership wp key
|
81 |
+
if (!empty($headers[$key])) {
|
82 |
+
$api_key = $headers[$key];
|
83 |
+
} else if (!empty($headers[$key1])){
|
84 |
+
$api_key = $headers[$key1];
|
85 |
+
} else if (!empty($headers[$key2])){
|
86 |
+
$api_key = $headers[$key2];
|
87 |
+
} else {
|
88 |
+
throw new Exception(__('AfterShip\'s WordPress Key is missing', 'aftership'), 404);
|
89 |
+
}
|
90 |
+
|
91 |
+
$user = $this->get_user_by_api_key($api_key);
|
92 |
+
|
93 |
+
return $user;
|
94 |
+
|
95 |
+
}
|
96 |
+
|
97 |
+
/**
|
98 |
+
* Return the user for the given consumer key
|
99 |
+
*
|
100 |
+
* @since 2.1
|
101 |
+
* @param string $consumer_key
|
102 |
+
* @return WP_User
|
103 |
+
* @throws Exception
|
104 |
+
*/
|
105 |
+
private function get_user_by_api_key($api_key)
|
106 |
+
{
|
107 |
+
|
108 |
+
$user_query = new WP_User_Query(
|
109 |
+
array(
|
110 |
+
//'meta_key' => 'woocommerce_api_consumer_key',
|
111 |
+
'meta_key' => 'aftership_wp_api_key',
|
112 |
+
'meta_value' => $api_key,
|
113 |
+
)
|
114 |
+
);
|
115 |
+
|
116 |
+
$users = $user_query->get_results();
|
117 |
+
|
118 |
+
if (empty($users[0]))
|
119 |
+
throw new Exception(__('AfterShip\'s WordPress API Key is invalid', 'aftership'), 401);
|
120 |
+
|
121 |
+
return $users[0];
|
122 |
+
|
123 |
+
|
124 |
+
}
|
125 |
+
|
126 |
+
}
|
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,462 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
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 |
+
return $routes;
|
58 |
+
}
|
59 |
+
|
60 |
+
/**
|
61 |
+
* Get all orders
|
62 |
+
*
|
63 |
+
* @since 2.1
|
64 |
+
* @param string $fields
|
65 |
+
* @param array $filter
|
66 |
+
* @param string $status
|
67 |
+
* @param int $page
|
68 |
+
* @return array
|
69 |
+
*/
|
70 |
+
public function get_orders($fields = null, $filter = array(), $status = null, $page = 1)
|
71 |
+
{
|
72 |
+
|
73 |
+
if (!empty($status))
|
74 |
+
$filter['status'] = $status;
|
75 |
+
|
76 |
+
$filter['page'] = $page;
|
77 |
+
|
78 |
+
$query = $this->query_orders($filter);
|
79 |
+
|
80 |
+
$orders = array();
|
81 |
+
|
82 |
+
foreach ($query->posts as $order_id) {
|
83 |
+
|
84 |
+
if (!$this->is_readable($order_id))
|
85 |
+
continue;
|
86 |
+
|
87 |
+
$orders[] = current($this->get_order($order_id, $fields));
|
88 |
+
}
|
89 |
+
|
90 |
+
$this->server->add_pagination_headers($query);
|
91 |
+
|
92 |
+
return array('orders' => $orders);
|
93 |
+
}
|
94 |
+
|
95 |
+
|
96 |
+
/**
|
97 |
+
* Get the order for the given ID
|
98 |
+
*
|
99 |
+
* @since 2.1
|
100 |
+
* @param int $id the order ID
|
101 |
+
* @param array $fields
|
102 |
+
* @return array
|
103 |
+
*/
|
104 |
+
public function get_order($id, $fields = null)
|
105 |
+
{
|
106 |
+
|
107 |
+
// ensure order ID is valid & user has permission to read
|
108 |
+
$id = $this->validate_request($id, 'shop_order', 'read');
|
109 |
+
|
110 |
+
if (is_wp_error($id))
|
111 |
+
return $id;
|
112 |
+
|
113 |
+
$order = new WC_Order($id);
|
114 |
+
|
115 |
+
$order_post = get_post($id);
|
116 |
+
|
117 |
+
$order_data = array(
|
118 |
+
'id' => $order->id,
|
119 |
+
'order_number' => $order->get_order_number(),
|
120 |
+
'created_at' => $this->server->format_datetime($order_post->post_date_gmt),
|
121 |
+
'updated_at' => $this->server->format_datetime($order_post->post_modified_gmt),
|
122 |
+
'completed_at' => $this->server->format_datetime($order->completed_date, true),
|
123 |
+
'status' => $order->status,
|
124 |
+
'currency' => $order->order_currency,
|
125 |
+
'total' => wc_format_decimal($order->get_total(), 2),
|
126 |
+
'subtotal' => wc_format_decimal($this->get_order_subtotal($order), 2),
|
127 |
+
'total_line_items_quantity' => $order->get_item_count(),
|
128 |
+
'total_tax' => wc_format_decimal($order->get_total_tax(), 2),
|
129 |
+
'total_shipping' => wc_format_decimal($order->get_total_shipping(), 2),
|
130 |
+
'cart_tax' => wc_format_decimal($order->get_cart_tax(), 2),
|
131 |
+
'shipping_tax' => wc_format_decimal($order->get_shipping_tax(), 2),
|
132 |
+
'total_discount' => wc_format_decimal($order->get_total_discount(), 2),
|
133 |
+
'cart_discount' => wc_format_decimal($order->get_cart_discount(), 2),
|
134 |
+
'order_discount' => wc_format_decimal($order->get_order_discount(), 2),
|
135 |
+
'shipping_methods' => $order->get_shipping_method(),
|
136 |
+
'payment_details' => array(
|
137 |
+
'method_id' => $order->payment_method,
|
138 |
+
'method_title' => $order->payment_method_title,
|
139 |
+
'paid' => isset($order->paid_date),
|
140 |
+
),
|
141 |
+
'billing_address' => array(
|
142 |
+
'first_name' => $order->billing_first_name,
|
143 |
+
'last_name' => $order->billing_last_name,
|
144 |
+
'company' => $order->billing_company,
|
145 |
+
'address_1' => $order->billing_address_1,
|
146 |
+
'address_2' => $order->billing_address_2,
|
147 |
+
'city' => $order->billing_city,
|
148 |
+
'state' => $order->billing_state,
|
149 |
+
'postcode' => $order->billing_postcode,
|
150 |
+
'country' => $order->billing_country,
|
151 |
+
'email' => $order->billing_email,
|
152 |
+
'phone' => $order->billing_phone,
|
153 |
+
),
|
154 |
+
'shipping_address' => array(
|
155 |
+
'first_name' => $order->shipping_first_name,
|
156 |
+
'last_name' => $order->shipping_last_name,
|
157 |
+
'company' => $order->shipping_company,
|
158 |
+
'address_1' => $order->shipping_address_1,
|
159 |
+
'address_2' => $order->shipping_address_2,
|
160 |
+
'city' => $order->shipping_city,
|
161 |
+
'state' => $order->shipping_state,
|
162 |
+
'postcode' => $order->shipping_postcode,
|
163 |
+
'country' => $order->shipping_country,
|
164 |
+
),
|
165 |
+
'note' => $order->customer_note,
|
166 |
+
'customer_ip' => $order->customer_ip_address,
|
167 |
+
'customer_user_agent' => $order->customer_user_agent,
|
168 |
+
'customer_id' => $order->customer_user,
|
169 |
+
'view_order_url' => $order->get_view_order_url(),
|
170 |
+
'line_items' => array(),
|
171 |
+
'shipping_lines' => array(),
|
172 |
+
'tax_lines' => array(),
|
173 |
+
'fee_lines' => array(),
|
174 |
+
'coupon_lines' => array(),
|
175 |
+
);
|
176 |
+
|
177 |
+
// add line items
|
178 |
+
foreach ($order->get_items() as $item_id => $item) {
|
179 |
+
|
180 |
+
$product = $order->get_product_from_item($item);
|
181 |
+
|
182 |
+
$order_data['line_items'][] = array(
|
183 |
+
'id' => $item_id,
|
184 |
+
'subtotal' => wc_format_decimal($order->get_line_subtotal($item), 2),
|
185 |
+
'total' => wc_format_decimal($order->get_line_total($item), 2),
|
186 |
+
'total_tax' => wc_format_decimal($order->get_line_tax($item), 2),
|
187 |
+
'price' => wc_format_decimal($order->get_item_total($item), 2),
|
188 |
+
'quantity' => (int)$item['qty'],
|
189 |
+
'tax_class' => (!empty($item['tax_class'])) ? $item['tax_class'] : null,
|
190 |
+
'name' => $item['name'],
|
191 |
+
'product_id' => (isset($product->variation_id)) ? $product->variation_id : $product->id,
|
192 |
+
'sku' => is_object($product) ? $product->get_sku() : null,
|
193 |
+
);
|
194 |
+
}
|
195 |
+
|
196 |
+
// add shipping
|
197 |
+
foreach ($order->get_shipping_methods() as $shipping_item_id => $shipping_item) {
|
198 |
+
|
199 |
+
$order_data['shipping_lines'][] = array(
|
200 |
+
'id' => $shipping_item_id,
|
201 |
+
'method_id' => $shipping_item['method_id'],
|
202 |
+
'method_title' => $shipping_item['name'],
|
203 |
+
'total' => wc_format_decimal($shipping_item['cost'], 2),
|
204 |
+
);
|
205 |
+
}
|
206 |
+
|
207 |
+
// add taxes
|
208 |
+
foreach ($order->get_tax_totals() as $tax_code => $tax) {
|
209 |
+
|
210 |
+
$order_data['tax_lines'][] = array(
|
211 |
+
'code' => $tax_code,
|
212 |
+
'title' => $tax->label,
|
213 |
+
'total' => wc_format_decimal($tax->amount, 2),
|
214 |
+
'compound' => (bool)$tax->is_compound,
|
215 |
+
);
|
216 |
+
}
|
217 |
+
|
218 |
+
// add fees
|
219 |
+
foreach ($order->get_fees() as $fee_item_id => $fee_item) {
|
220 |
+
|
221 |
+
$order_data['fee_lines'][] = array(
|
222 |
+
'id' => $fee_item_id,
|
223 |
+
'title' => $fee_item['name'],
|
224 |
+
'tax_class' => (!empty($fee_item['tax_class'])) ? $fee_item['tax_class'] : null,
|
225 |
+
'total' => wc_format_decimal($order->get_line_total($fee_item), 2),
|
226 |
+
'total_tax' => wc_format_decimal($order->get_line_tax($fee_item), 2),
|
227 |
+
);
|
228 |
+
}
|
229 |
+
|
230 |
+
// add coupons
|
231 |
+
foreach ($order->get_items('coupon') as $coupon_item_id => $coupon_item) {
|
232 |
+
|
233 |
+
$order_data['coupon_lines'][] = array(
|
234 |
+
'id' => $coupon_item_id,
|
235 |
+
'code' => $coupon_item['name'],
|
236 |
+
'amount' => wc_format_decimal($coupon_item['discount_amount'], 2),
|
237 |
+
);
|
238 |
+
}
|
239 |
+
|
240 |
+
// aftership add
|
241 |
+
$options = get_option('aftership_option_name');
|
242 |
+
$plugin = $options['plugin'];
|
243 |
+
if ($plugin == 'aftership') {
|
244 |
+
$order_data['aftership']['woocommerce']['trackings'][] = array(
|
245 |
+
'tracking_provider' => get_post_meta($order->id, '_aftership_tracking_provider', true),
|
246 |
+
'tracking_number' => get_post_meta($order->id, '_aftership_tracking_number', true),
|
247 |
+
'tracking_shipdate' => get_post_meta($order->id, '_aftership_tracking_shipdate', true),
|
248 |
+
'tracking_postal' => get_post_meta($order->id, '_aftership_tracking_postal', true),
|
249 |
+
'tracking_account' => get_post_meta($order->id, '_aftership_tracking_account', true),
|
250 |
+
);
|
251 |
+
} else if ($plugin == 'wc-shipment-tracking') { //$49
|
252 |
+
$order_data['aftership']['woocommerce']['trackings'][] = array(
|
253 |
+
'tracking_number' => get_post_meta($order->id, '_tracking_number', true),
|
254 |
+
);
|
255 |
+
}
|
256 |
+
// aftership add finish
|
257 |
+
|
258 |
+
return array('order' => apply_filters('aftership_api_order_response', $order_data, $order, $fields, $this->server));
|
259 |
+
}
|
260 |
+
|
261 |
+
/**
|
262 |
+
* Get the total number of orders
|
263 |
+
*
|
264 |
+
* @since 2.1
|
265 |
+
* @param string $status
|
266 |
+
* @param array $filter
|
267 |
+
* @return array
|
268 |
+
*/
|
269 |
+
public function get_orders_count($status = null, $filter = array())
|
270 |
+
{
|
271 |
+
|
272 |
+
if (!empty($status))
|
273 |
+
$filter['status'] = $status;
|
274 |
+
|
275 |
+
$query = $this->query_orders($filter);
|
276 |
+
|
277 |
+
if (!current_user_can('read_private_shop_orders'))
|
278 |
+
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));
|
279 |
+
|
280 |
+
return array('count' => (int)$query->found_posts);
|
281 |
+
}
|
282 |
+
|
283 |
+
/**
|
284 |
+
* Edit an order
|
285 |
+
*
|
286 |
+
* API v1 only allows updating the status of an order
|
287 |
+
*
|
288 |
+
* @since 2.1
|
289 |
+
* @param int $id the order ID
|
290 |
+
* @param array $data
|
291 |
+
* @return array
|
292 |
+
*/
|
293 |
+
public function edit_order($id, $data)
|
294 |
+
{
|
295 |
+
|
296 |
+
$id = $this->validate_request($id, 'shop_order', 'edit');
|
297 |
+
|
298 |
+
if (is_wp_error($id))
|
299 |
+
return $id;
|
300 |
+
|
301 |
+
$order = new WC_Order($id);
|
302 |
+
|
303 |
+
if (!empty($data['status'])) {
|
304 |
+
|
305 |
+
$order->update_status($data['status'], isset($data['note']) ? $data['note'] : '');
|
306 |
+
}
|
307 |
+
|
308 |
+
return $this->get_order($id);
|
309 |
+
}
|
310 |
+
|
311 |
+
/**
|
312 |
+
* Delete an order
|
313 |
+
*
|
314 |
+
* @TODO enable along with POST in 2.2
|
315 |
+
* @param int $id the order ID
|
316 |
+
* @param bool $force true to permanently delete order, false to move to trash
|
317 |
+
* @return array
|
318 |
+
*/
|
319 |
+
public function delete_order($id, $force = false)
|
320 |
+
{
|
321 |
+
|
322 |
+
$id = $this->validate_request($id, 'shop_order', 'delete');
|
323 |
+
|
324 |
+
return $this->delete($id, 'order', ('true' === $force));
|
325 |
+
}
|
326 |
+
|
327 |
+
/**
|
328 |
+
* Get the admin order notes for an order
|
329 |
+
*
|
330 |
+
* @since 2.1
|
331 |
+
* @param int $id the order ID
|
332 |
+
* @param string $fields fields to include in response
|
333 |
+
* @return array
|
334 |
+
*/
|
335 |
+
public function get_order_notes($id, $fields = null)
|
336 |
+
{
|
337 |
+
|
338 |
+
// ensure ID is valid order ID
|
339 |
+
$id = $this->validate_request($id, 'shop_order', 'read');
|
340 |
+
|
341 |
+
if (is_wp_error($id))
|
342 |
+
return $id;
|
343 |
+
|
344 |
+
$args = array(
|
345 |
+
'post_id' => $id,
|
346 |
+
'approve' => 'approve',
|
347 |
+
'type' => 'order_note'
|
348 |
+
);
|
349 |
+
|
350 |
+
remove_filter('comments_clauses', array('WC_Comments', 'exclude_order_comments'), 10, 1);
|
351 |
+
|
352 |
+
$notes = get_comments($args);
|
353 |
+
|
354 |
+
add_filter('comments_clauses', array('WC_Comments', 'exclude_order_comments'), 10, 1);
|
355 |
+
|
356 |
+
$order_notes = array();
|
357 |
+
|
358 |
+
foreach ($notes as $note) {
|
359 |
+
|
360 |
+
$order_notes[] = array(
|
361 |
+
'id' => $note->comment_ID,
|
362 |
+
'created_at' => $this->server->format_datetime($note->comment_date_gmt),
|
363 |
+
'note' => $note->comment_content,
|
364 |
+
'customer_note' => get_comment_meta($note->comment_ID, 'is_customer_note', true) ? true : false,
|
365 |
+
);
|
366 |
+
}
|
367 |
+
|
368 |
+
return array('order_notes' => apply_filters('aftership_api_order_notes_response', $order_notes, $id, $fields, $notes, $this->server));
|
369 |
+
}
|
370 |
+
|
371 |
+
/**
|
372 |
+
* Helper method to get order post objects
|
373 |
+
*
|
374 |
+
* @since 2.1
|
375 |
+
* @param array $args request arguments for filtering query
|
376 |
+
* @return WP_Query
|
377 |
+
*/
|
378 |
+
private function query_orders($args)
|
379 |
+
{
|
380 |
+
|
381 |
+
function wpbo_get_woo_version_number()
|
382 |
+
{
|
383 |
+
// If get_plugins() isn't available, require it
|
384 |
+
if (!function_exists('get_plugins'))
|
385 |
+
require_once(ABSPATH . 'wp-admin/includes/plugin.php');
|
386 |
+
|
387 |
+
// Create the plugins folder and file variables
|
388 |
+
$plugin_folder = get_plugins('/' . 'woocommerce');
|
389 |
+
$plugin_file = 'woocommerce.php';
|
390 |
+
|
391 |
+
// If the plugin version number is set, return it
|
392 |
+
if (isset($plugin_folder[$plugin_file]['Version'])) {
|
393 |
+
return $plugin_folder[$plugin_file]['Version'];
|
394 |
+
|
395 |
+
} else {
|
396 |
+
// Otherwise return null
|
397 |
+
return NULL;
|
398 |
+
}
|
399 |
+
}
|
400 |
+
|
401 |
+
$woo_version = wpbo_get_woo_version_number();
|
402 |
+
|
403 |
+
if ($woo_version >= 2.2) {
|
404 |
+
// set base query arguments
|
405 |
+
$query_args = array(
|
406 |
+
'fields' => 'ids',
|
407 |
+
'post_type' => 'shop_order',
|
408 |
+
// 'post_status' => 'publish',
|
409 |
+
'post_status' => array_keys(wc_get_order_statuses())
|
410 |
+
);
|
411 |
+
} else {
|
412 |
+
// set base query arguments
|
413 |
+
$query_args = array(
|
414 |
+
'fields' => 'ids',
|
415 |
+
'post_type' => 'shop_order',
|
416 |
+
'post_status' => 'publish',
|
417 |
+
);
|
418 |
+
}
|
419 |
+
|
420 |
+
// add status argument
|
421 |
+
if (!empty($args['status'])) {
|
422 |
+
|
423 |
+
$statuses = explode(',', $args['status']);
|
424 |
+
|
425 |
+
$query_args['tax_query'] = array(
|
426 |
+
array(
|
427 |
+
'taxonomy' => 'shop_order_status',
|
428 |
+
'field' => 'slug',
|
429 |
+
'terms' => $statuses,
|
430 |
+
),
|
431 |
+
);
|
432 |
+
|
433 |
+
unset($args['status']);
|
434 |
+
}
|
435 |
+
|
436 |
+
$query_args = $this->merge_query_args($query_args, $args);
|
437 |
+
|
438 |
+
return new WP_Query($query_args);
|
439 |
+
}
|
440 |
+
|
441 |
+
/**
|
442 |
+
* Helper method to get the order subtotal
|
443 |
+
*
|
444 |
+
* @since 2.1
|
445 |
+
* @param WC_Order $order
|
446 |
+
* @return float
|
447 |
+
*/
|
448 |
+
private function get_order_subtotal($order)
|
449 |
+
{
|
450 |
+
|
451 |
+
$subtotal = 0;
|
452 |
+
|
453 |
+
// subtotal
|
454 |
+
foreach ($order->get_items() as $item) {
|
455 |
+
|
456 |
+
$subtotal += (isset($item['line_subtotal'])) ? $item['line_subtotal'] : 0;
|
457 |
+
}
|
458 |
+
|
459 |
+
return $subtotal;
|
460 |
+
}
|
461 |
+
|
462 |
+
}
|
trunk/api/class-aftership-api-resource.php
ADDED
@@ -0,0 +1,410 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
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 |
+
return array_merge($base_args, $args);
|
162 |
+
}
|
163 |
+
|
164 |
+
/**
|
165 |
+
* Add meta to resources when requested by the client. Meta is added as a top-level
|
166 |
+
* `<resource_name>_meta` attribute (e.g. `order_meta`) as a list of key/value pairs
|
167 |
+
*
|
168 |
+
* @since 2.1
|
169 |
+
* @param array $data the resource data
|
170 |
+
* @param object $resource the resource object (e.g WC_Order)
|
171 |
+
* @return mixed
|
172 |
+
*/
|
173 |
+
public function maybe_add_meta($data, $resource)
|
174 |
+
{
|
175 |
+
|
176 |
+
if (isset($this->server->params['GET']['filter']['meta']) && 'true' === $this->server->params['GET']['filter']['meta'] && is_object($resource)) {
|
177 |
+
|
178 |
+
// don't attempt to add meta more than once
|
179 |
+
if (preg_grep('/[a-z]+_meta/', array_keys($data)))
|
180 |
+
return $data;
|
181 |
+
|
182 |
+
// define the top-level property name for the meta
|
183 |
+
switch (get_class($resource)) {
|
184 |
+
|
185 |
+
case 'WC_Order':
|
186 |
+
$meta_name = 'order_meta';
|
187 |
+
break;
|
188 |
+
|
189 |
+
case 'WC_Coupon':
|
190 |
+
$meta_name = 'coupon_meta';
|
191 |
+
break;
|
192 |
+
|
193 |
+
case 'WP_User':
|
194 |
+
$meta_name = 'customer_meta';
|
195 |
+
break;
|
196 |
+
|
197 |
+
default:
|
198 |
+
$meta_name = 'product_meta';
|
199 |
+
break;
|
200 |
+
}
|
201 |
+
|
202 |
+
if (is_a($resource, 'WP_User')) {
|
203 |
+
|
204 |
+
// customer meta
|
205 |
+
$meta = (array)get_user_meta($resource->ID);
|
206 |
+
|
207 |
+
} elseif (is_a($resource, 'WC_Product_Variation')) {
|
208 |
+
|
209 |
+
// product variation meta
|
210 |
+
$meta = (array)get_post_meta($resource->get_variation_id());
|
211 |
+
|
212 |
+
} else {
|
213 |
+
|
214 |
+
// coupon/order/product meta
|
215 |
+
$meta = (array)get_post_meta($resource->id);
|
216 |
+
}
|
217 |
+
|
218 |
+
foreach ($meta as $meta_key => $meta_value) {
|
219 |
+
|
220 |
+
// don't add hidden meta by default
|
221 |
+
if (!is_protected_meta($meta_key)) {
|
222 |
+
$data[$meta_name][$meta_key] = maybe_unserialize($meta_value[0]);
|
223 |
+
}
|
224 |
+
}
|
225 |
+
|
226 |
+
}
|
227 |
+
|
228 |
+
return $data;
|
229 |
+
}
|
230 |
+
|
231 |
+
/**
|
232 |
+
* Restrict the fields included in the response if the request specified certain only certain fields should be returned
|
233 |
+
*
|
234 |
+
* @since 2.1
|
235 |
+
* @param array $data the response data
|
236 |
+
* @param object $resource the object that provided the response data, e.g. WC_Coupon or WC_Order
|
237 |
+
* @param array|string the requested list of fields to include in the response
|
238 |
+
* @return array response data
|
239 |
+
*/
|
240 |
+
public function filter_response_fields($data, $resource, $fields)
|
241 |
+
{
|
242 |
+
|
243 |
+
if (!is_array($data) || empty($fields))
|
244 |
+
return $data;
|
245 |
+
|
246 |
+
$fields = explode(',', $fields);
|
247 |
+
$sub_fields = array();
|
248 |
+
|
249 |
+
// get sub fields
|
250 |
+
foreach ($fields as $field) {
|
251 |
+
|
252 |
+
if (false !== strpos($field, '.')) {
|
253 |
+
|
254 |
+
list($name, $value) = explode('.', $field);
|
255 |
+
|
256 |
+
$sub_fields[$name] = $value;
|
257 |
+
}
|
258 |
+
}
|
259 |
+
|
260 |
+
// iterate through top-level fields
|
261 |
+
foreach ($data as $data_field => $data_value) {
|
262 |
+
|
263 |
+
// if a field has sub-fields and the top-level field has sub-fields to filter
|
264 |
+
if (is_array($data_value) && in_array($data_field, array_keys($sub_fields))) {
|
265 |
+
|
266 |
+
// iterate through each sub-field
|
267 |
+
foreach ($data_value as $sub_field => $sub_field_value) {
|
268 |
+
|
269 |
+
// remove non-matching sub-fields
|
270 |
+
if (!in_array($sub_field, $sub_fields)) {
|
271 |
+
unset($data[$data_field][$sub_field]);
|
272 |
+
}
|
273 |
+
}
|
274 |
+
|
275 |
+
} else {
|
276 |
+
|
277 |
+
// remove non-matching top-level fields
|
278 |
+
if (!in_array($data_field, $fields)) {
|
279 |
+
unset($data[$data_field]);
|
280 |
+
}
|
281 |
+
}
|
282 |
+
}
|
283 |
+
|
284 |
+
return $data;
|
285 |
+
}
|
286 |
+
|
287 |
+
/**
|
288 |
+
* Delete a given resource
|
289 |
+
*
|
290 |
+
* @since 2.1
|
291 |
+
* @param int $id the resource ID
|
292 |
+
* @param string $type the resource post type, or `customer`
|
293 |
+
* @param bool $force true to permanently delete resource, false to move to trash (not supported for `customer`)
|
294 |
+
* @return array|WP_Error
|
295 |
+
*/
|
296 |
+
protected function delete($id, $type, $force = false)
|
297 |
+
{
|
298 |
+
|
299 |
+
if ('shop_order' === $type || 'shop_coupon' === $type)
|
300 |
+
$resource_name = str_replace('shop_', '', $type);
|
301 |
+
else
|
302 |
+
$resource_name = $type;
|
303 |
+
|
304 |
+
if ('customer' === $type) {
|
305 |
+
|
306 |
+
$result = wp_delete_user($id);
|
307 |
+
|
308 |
+
if ($result)
|
309 |
+
return array('message' => __('Permanently deleted customer', 'aftership'));
|
310 |
+
else
|
311 |
+
return new WP_Error('aftership_api_cannot_delete_customer', __('The customer cannot be deleted', 'aftership'), array('status' => 500));
|
312 |
+
|
313 |
+
} else {
|
314 |
+
|
315 |
+
// delete order/coupon/product
|
316 |
+
|
317 |
+
$result = ($force) ? wp_delete_post($id, true) : wp_trash_post($id);
|
318 |
+
|
319 |
+
if (!$result)
|
320 |
+
return new WP_Error("aftership_api_cannot_delete_{$resource_name}", sprintf(__('This %s cannot be deleted', 'aftership'), $resource_name), array('status' => 500));
|
321 |
+
|
322 |
+
if ($force) {
|
323 |
+
return array('message' => sprintf(__('Permanently deleted %s', 'aftership'), $resource_name));
|
324 |
+
|
325 |
+
} else {
|
326 |
+
|
327 |
+
$this->server->send_status('202');
|
328 |
+
|
329 |
+
return array('message' => sprintf(__('Deleted %s', 'aftership'), $resource_name));
|
330 |
+
}
|
331 |
+
}
|
332 |
+
}
|
333 |
+
|
334 |
+
|
335 |
+
/**
|
336 |
+
* Checks if the given post is readable by the current user
|
337 |
+
*
|
338 |
+
* @since 2.1
|
339 |
+
* @see WC_API_Resource::check_permission()
|
340 |
+
* @param WP_Post|int $post
|
341 |
+
* @return bool
|
342 |
+
*/
|
343 |
+
protected function is_readable($post)
|
344 |
+
{
|
345 |
+
|
346 |
+
return $this->check_permission($post, 'read');
|
347 |
+
}
|
348 |
+
|
349 |
+
/**
|
350 |
+
* Checks if the given post is editable by the current user
|
351 |
+
*
|
352 |
+
* @since 2.1
|
353 |
+
* @see WC_API_Resource::check_permission()
|
354 |
+
* @param WP_Post|int $post
|
355 |
+
* @return bool
|
356 |
+
*/
|
357 |
+
protected function is_editable($post)
|
358 |
+
{
|
359 |
+
|
360 |
+
return $this->check_permission($post, 'edit');
|
361 |
+
|
362 |
+
}
|
363 |
+
|
364 |
+
/**
|
365 |
+
* Checks if the given post is deletable by the current user
|
366 |
+
*
|
367 |
+
* @since 2.1
|
368 |
+
* @see WC_API_Resource::check_permission()
|
369 |
+
* @param WP_Post|int $post
|
370 |
+
* @return bool
|
371 |
+
*/
|
372 |
+
protected function is_deletable($post)
|
373 |
+
{
|
374 |
+
|
375 |
+
return $this->check_permission($post, 'delete');
|
376 |
+
}
|
377 |
+
|
378 |
+
/**
|
379 |
+
* Checks the permissions for the current user given a post and context
|
380 |
+
*
|
381 |
+
* @since 2.1
|
382 |
+
* @param WP_Post|int $post
|
383 |
+
* @param string $context the type of permission to check, either `read`, `write`, or `delete`
|
384 |
+
* @return bool true if the current user has the permissions to perform the context on the post
|
385 |
+
*/
|
386 |
+
private function check_permission($post, $context)
|
387 |
+
{
|
388 |
+
|
389 |
+
if (!is_a($post, 'WP_Post'))
|
390 |
+
$post = get_post($post);
|
391 |
+
|
392 |
+
if (is_null($post))
|
393 |
+
return false;
|
394 |
+
|
395 |
+
$post_type = get_post_type_object($post->post_type);
|
396 |
+
|
397 |
+
if ('read' === $context)
|
398 |
+
return current_user_can($post_type->cap->read_private_posts, $post->ID);
|
399 |
+
|
400 |
+
elseif ('edit' === $context)
|
401 |
+
return current_user_can($post_type->cap->edit_post, $post->ID);
|
402 |
+
|
403 |
+
elseif ('delete' === $context)
|
404 |
+
return current_user_can($post_type->cap->delete_post, $post->ID);
|
405 |
+
|
406 |
+
else
|
407 |
+
return false;
|
408 |
+
}
|
409 |
+
|
410 |
+
}
|
trunk/api/class-aftership-api-server.php
ADDED
@@ -0,0 +1,766 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
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 |
+
global $HTTP_RAW_POST_DATA;
|
620 |
+
|
621 |
+
// A bug in PHP < 5.2.2 makes $HTTP_RAW_POST_DATA not set by default,
|
622 |
+
// but we can do it ourself.
|
623 |
+
if (!isset($HTTP_RAW_POST_DATA)) {
|
624 |
+
$HTTP_RAW_POST_DATA = file_get_contents('php://input');
|
625 |
+
}
|
626 |
+
|
627 |
+
return $HTTP_RAW_POST_DATA;
|
628 |
+
}
|
629 |
+
|
630 |
+
/**
|
631 |
+
* Parse an RFC3339 datetime into a MySQl datetime
|
632 |
+
*
|
633 |
+
* Invalid dates default to unix epoch
|
634 |
+
*
|
635 |
+
* @since 2.1
|
636 |
+
* @param string $datetime RFC3339 datetime
|
637 |
+
* @return string MySQl datetime (YYYY-MM-DD HH:MM:SS)
|
638 |
+
*/
|
639 |
+
public function parse_datetime($datetime)
|
640 |
+
{
|
641 |
+
|
642 |
+
// Strip millisecond precision (a full stop followed by one or more digits)
|
643 |
+
if (strpos($datetime, '.') !== false) {
|
644 |
+
$datetime = preg_replace('/\.\d+/', '', $datetime);
|
645 |
+
}
|
646 |
+
|
647 |
+
// default timezone to UTC
|
648 |
+
$datetime = preg_replace('/[+-]\d+:+\d+$/', '+00:00', $datetime);
|
649 |
+
|
650 |
+
try {
|
651 |
+
|
652 |
+
$datetime = new DateTime($datetime, new DateTimeZone('UTC'));
|
653 |
+
|
654 |
+
} catch (Exception $e) {
|
655 |
+
|
656 |
+
$datetime = new DateTime('@0');
|
657 |
+
|
658 |
+
}
|
659 |
+
|
660 |
+
return $datetime->format('Y-m-d H:i:s');
|
661 |
+
}
|
662 |
+
|
663 |
+
/**
|
664 |
+
* Format a unix timestamp or MySQL datetime into an RFC3339 datetime
|
665 |
+
*
|
666 |
+
* @since 2.1
|
667 |
+
* @param int|string $timestamp unix timestamp or MySQL datetime
|
668 |
+
* @param bool $convert_to_utc
|
669 |
+
* @return string RFC3339 datetime
|
670 |
+
*/
|
671 |
+
public function format_datetime($timestamp, $convert_to_utc = false)
|
672 |
+
{
|
673 |
+
|
674 |
+
if ($convert_to_utc) {
|
675 |
+
$timezone = new DateTimeZone(wc_timezone_string());
|
676 |
+
} else {
|
677 |
+
$timezone = new DateTimeZone('UTC');
|
678 |
+
}
|
679 |
+
|
680 |
+
try {
|
681 |
+
|
682 |
+
if (is_numeric($timestamp)) {
|
683 |
+
$date = new DateTime("@{$timestamp}");
|
684 |
+
} else {
|
685 |
+
$date = new DateTime($timestamp, $timezone);
|
686 |
+
}
|
687 |
+
|
688 |
+
// convert to UTC by adjusting the time based on the offset of the site's timezone
|
689 |
+
if ($convert_to_utc) {
|
690 |
+
$date->modify(-1 * $date->getOffset() . ' seconds');
|
691 |
+
}
|
692 |
+
|
693 |
+
} catch (Exception $e) {
|
694 |
+
|
695 |
+
$date = new DateTime('@0');
|
696 |
+
}
|
697 |
+
|
698 |
+
return $date->format('Y-m-d\TH:i:s\Z');
|
699 |
+
}
|
700 |
+
|
701 |
+
/**
|
702 |
+
* Extract headers from a PHP-style $_SERVER array
|
703 |
+
*
|
704 |
+
* @since 2.1
|
705 |
+
* @param array $server Associative array similar to $_SERVER
|
706 |
+
* @return array Headers extracted from the input
|
707 |
+
*/
|
708 |
+
public function get_headers($server)
|
709 |
+
{
|
710 |
+
$headers = array();
|
711 |
+
// CONTENT_* headers are not prefixed with HTTP_
|
712 |
+
$additional = array('CONTENT_LENGTH' => true, 'CONTENT_MD5' => true, 'CONTENT_TYPE' => true);
|
713 |
+
|
714 |
+
foreach ($server as $key => $value) {
|
715 |
+
if (strpos($key, 'HTTP_') === 0) {
|
716 |
+
$headers[substr($key, 5)] = $value;
|
717 |
+
} elseif (isset($additional[$key])) {
|
718 |
+
$headers[$key] = $value;
|
719 |
+
}
|
720 |
+
}
|
721 |
+
|
722 |
+
return $headers;
|
723 |
+
}
|
724 |
+
|
725 |
+
/**
|
726 |
+
* Check if the current request accepts a JSON response by checking the endpoint suffix (.json) or
|
727 |
+
* the HTTP ACCEPT header
|
728 |
+
*
|
729 |
+
* @since 2.1
|
730 |
+
* @return bool
|
731 |
+
*/
|
732 |
+
private function is_json_request()
|
733 |
+
{
|
734 |
+
|
735 |
+
// check path
|
736 |
+
if (false !== stripos($this->path, '.json'))
|
737 |
+
return true;
|
738 |
+
|
739 |
+
// check ACCEPT header, only 'application/json' is acceptable, see RFC 4627
|
740 |
+
if (isset($this->headers['ACCEPT']) && 'application/json' == $this->headers['ACCEPT'])
|
741 |
+
return true;
|
742 |
+
|
743 |
+
return false;
|
744 |
+
}
|
745 |
+
|
746 |
+
/**
|
747 |
+
* Check if the current request accepts an XML response by checking the endpoint suffix (.xml) or
|
748 |
+
* the HTTP ACCEPT header
|
749 |
+
*
|
750 |
+
* @since 2.1
|
751 |
+
* @return bool
|
752 |
+
*/
|
753 |
+
private function is_xml_request()
|
754 |
+
{
|
755 |
+
|
756 |
+
// check path
|
757 |
+
if (false !== stripos($this->path, '.xml'))
|
758 |
+
return true;
|
759 |
+
|
760 |
+
// check headers, 'application/xml' or 'text/xml' are acceptable, see RFC 2376
|
761 |
+
if (isset($this->headers['ACCEPT']) && ('application/xml' == $this->headers['ACCEPT'] || 'text/xml' == $this->headers['ACCEPT']))
|
762 |
+
return true;
|
763 |
+
|
764 |
+
return false;
|
765 |
+
}
|
766 |
+
}
|
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,99 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
jQuery(function() {
|
2 |
+
|
3 |
+
|
4 |
+
var providers;
|
5 |
+
|
6 |
+
|
7 |
+
function set_aftership_tracking_provider() {
|
8 |
+
function hide_input_and_label(id) {
|
9 |
+
jQuery('#' + id).hide();
|
10 |
+
jQuery('label[for=' + id + ']').hide();
|
11 |
+
}
|
12 |
+
|
13 |
+
function show_input_and_label(id) {
|
14 |
+
jQuery('#' + id).show();
|
15 |
+
jQuery('label[for=' + id + ']').show();
|
16 |
+
}
|
17 |
+
|
18 |
+
jQuery('#aftership_tracking_provider').change(function() {
|
19 |
+
hide_input_and_label('aftership_tracking_shipdate');
|
20 |
+
hide_input_and_label('aftership_tracking_postal');
|
21 |
+
hide_input_and_label('aftership_tracking_account');
|
22 |
+
|
23 |
+
var slug = jQuery(this).val();
|
24 |
+
if (slug) {
|
25 |
+
var provider = providers[slug];
|
26 |
+
var fields = [];
|
27 |
+
if (jQuery.isArray(provider.required_fields)) {
|
28 |
+
fields = provider.required_fields;
|
29 |
+
} else {
|
30 |
+
fields.push(provider.required_fields);
|
31 |
+
}
|
32 |
+
jQuery.each(fields, function(index, item) {
|
33 |
+
if (item == 'tracking_ship_date') {
|
34 |
+
show_input_and_label('aftership_tracking_shipdate');
|
35 |
+
} else if (item == 'tracking_postal_code') {
|
36 |
+
show_input_and_label('aftership_tracking_postal');
|
37 |
+
} else if (item == 'tracking_account_number') {
|
38 |
+
show_input_and_label('aftership_tracking_account');
|
39 |
+
}
|
40 |
+
});
|
41 |
+
jQuery('#aftership_tracking_provider_name').val(provider.name);
|
42 |
+
jQuery('#aftership_tracking_required_fields').val(fields.join());
|
43 |
+
}
|
44 |
+
});
|
45 |
+
}
|
46 |
+
|
47 |
+
|
48 |
+
function fill_meta_box(couriers_selected) {
|
49 |
+
var response = get_couriers();
|
50 |
+
var couriers = [];
|
51 |
+
jQuery.each(response, function(index, courier) {
|
52 |
+
if (couriers_selected.indexOf(courier.slug) != -1) {
|
53 |
+
couriers.push(courier);
|
54 |
+
}
|
55 |
+
});
|
56 |
+
|
57 |
+
var selected_provider = jQuery('#aftership_tracking_provider_hidden').val();
|
58 |
+
var find_selected_provider = couriers_selected.indexOf(selected_provider) != -1;
|
59 |
+
if (!find_selected_provider) {
|
60 |
+
couriers.push({
|
61 |
+
slug: selected_provider,
|
62 |
+
name: jQuery("#aftership_tracking_provider_name").val(),
|
63 |
+
required_fields: jQuery("#aftership_tracking_required_fields").val()
|
64 |
+
});
|
65 |
+
}
|
66 |
+
// console.log(couriers);
|
67 |
+
|
68 |
+
couriers = sort_couriers(couriers);
|
69 |
+
|
70 |
+
jQuery.each(couriers, function(key, courier) {
|
71 |
+
var str = '<option ';
|
72 |
+
if (!find_selected_provider && courier['slug'] == selected_provider) {
|
73 |
+
str += 'style="display:none;" ';
|
74 |
+
}
|
75 |
+
str += 'value="' + courier['slug'] + '" ';
|
76 |
+
if (courier['slug'] == selected_provider) {
|
77 |
+
str += 'selected="selected"';
|
78 |
+
}
|
79 |
+
str += '>' + courier['name'] + '</option>';
|
80 |
+
jQuery('#aftership_tracking_provider').append(str);
|
81 |
+
});
|
82 |
+
// jQuery('#aftership_tracking_provider').val(selected_provider);
|
83 |
+
jQuery('#aftership_tracking_provider').trigger("chosen:updated");
|
84 |
+
jQuery('#aftership_tracking_provider_chosen').css({width: '100%'});
|
85 |
+
|
86 |
+
providers = {};
|
87 |
+
jQuery.each(couriers, function(index,courier){
|
88 |
+
providers[courier.slug] = courier;
|
89 |
+
});
|
90 |
+
set_aftership_tracking_provider();
|
91 |
+
jQuery('#aftership_tracking_provider').trigger('change');
|
92 |
+
}
|
93 |
+
|
94 |
+
if (jQuery('#aftership_tracking_provider')) {
|
95 |
+
var couriers_selected = jQuery('#aftership_couriers_selected').val();
|
96 |
+
var couriers_selected_arr = (couriers_selected) ? couriers_selected.split(',') : [];
|
97 |
+
fill_meta_box(couriers_selected_arr);
|
98 |
+
}
|
99 |
+
});
|
trunk/assets/js/couriers.js
ADDED
@@ -0,0 +1,1779 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
function get_couriers() {
|
2 |
+
var data = [
|
3 |
+
{
|
4 |
+
"slug": "india-post-int",
|
5 |
+
"name": "India Post International",
|
6 |
+
"phone": "+91 1800 11 2011",
|
7 |
+
"other_name": "भारतीय डाक, Speed Post & eMO, EMS, IPS Web",
|
8 |
+
"web_url": "http://www.indiapost.gov.in/",
|
9 |
+
"required_fields": []
|
10 |
+
},
|
11 |
+
{
|
12 |
+
"slug": "couriers-please",
|
13 |
+
"name": "Couriers Please",
|
14 |
+
"phone": "+61 1300 361 000",
|
15 |
+
"other_name": "CouriersPlease",
|
16 |
+
"web_url": "http://www.couriersplease.com.au/",
|
17 |
+
"required_fields": []
|
18 |
+
},
|
19 |
+
{
|
20 |
+
"slug": "italy-sda",
|
21 |
+
"name": "Italy SDA",
|
22 |
+
"phone": "+39 199 113366",
|
23 |
+
"other_name": "SDA Express Courier",
|
24 |
+
"web_url": "http://www.sda.it/",
|
25 |
+
"required_fields": []
|
26 |
+
},
|
27 |
+
{
|
28 |
+
"slug": "chronopost-portugal",
|
29 |
+
"name": "Chronopost Portugal",
|
30 |
+
"phone": "+351 707 20 28 28",
|
31 |
+
"other_name": "Chronopost pt",
|
32 |
+
"web_url": "http://chronopost.pt/",
|
33 |
+
"required_fields": []
|
34 |
+
},
|
35 |
+
{
|
36 |
+
"slug": "ptt-posta",
|
37 |
+
"name": "PTT Posta",
|
38 |
+
"phone": "+90 444 1 788",
|
39 |
+
"other_name": "Turkish Post",
|
40 |
+
"web_url": "http://www.ptt.gov.tr/",
|
41 |
+
"required_fields": []
|
42 |
+
},
|
43 |
+
{
|
44 |
+
"slug": "fastway-za",
|
45 |
+
"name": "Fastway South Africa",
|
46 |
+
"phone": "+27 0861 222 882",
|
47 |
+
"other_name": "Fastway Couriers",
|
48 |
+
"web_url": "http://www.fastway.co.za/",
|
49 |
+
"required_fields": []
|
50 |
+
},
|
51 |
+
{
|
52 |
+
"slug": "russian-post",
|
53 |
+
"name": "Russian Post",
|
54 |
+
"phone": "+7 (495) 956-20-67",
|
55 |
+
"other_name": "Почта России, EMS Post RU",
|
56 |
+
"web_url": "http://www.russianpost.ru/",
|
57 |
+
"required_fields": []
|
58 |
+
},
|
59 |
+
{
|
60 |
+
"slug": "spain-correos-es",
|
61 |
+
"name": "Correos de España",
|
62 |
+
"phone": "+34 902197197",
|
63 |
+
"other_name": "Spain Post, ChronoExpress",
|
64 |
+
"web_url": "http://www.correos.es",
|
65 |
+
"required_fields": []
|
66 |
+
},
|
67 |
+
{
|
68 |
+
"slug": "saudi-post",
|
69 |
+
"name": "Saudi Post",
|
70 |
+
"phone": "+966 9200 05700",
|
71 |
+
"other_name": "البريد السعودي",
|
72 |
+
"web_url": "http://www.sp.com.sa/",
|
73 |
+
"required_fields": []
|
74 |
+
},
|
75 |
+
{
|
76 |
+
"slug": "dpd-ireland",
|
77 |
+
"name": "DPD Ireland",
|
78 |
+
"phone": "+353 (0)90 64 20500",
|
79 |
+
"other_name": "DPD ie",
|
80 |
+
"web_url": "http://www.dpd.ie/",
|
81 |
+
"required_fields": []
|
82 |
+
},
|
83 |
+
{
|
84 |
+
"slug": "austrian-post-registered",
|
85 |
+
"name": "Austrian Post (Registered)",
|
86 |
+
"phone": "+43 810 010 100",
|
87 |
+
"other_name": "Österreichische Post AG",
|
88 |
+
"web_url": "http://www.post.at",
|
89 |
+
"required_fields": []
|
90 |
+
},
|
91 |
+
{
|
92 |
+
"slug": "kerry-logistics",
|
93 |
+
"name": "Kerry Express Thailand",
|
94 |
+
"phone": "+66 02-6868999",
|
95 |
+
"other_name": "嘉里物流, Kerry Logistics",
|
96 |
+
"web_url": "http://www.kerrylogistics.com/",
|
97 |
+
"required_fields": []
|
98 |
+
},
|
99 |
+
{
|
100 |
+
"slug": "posten-norge",
|
101 |
+
"name": "Posten Norge / Bring",
|
102 |
+
"phone": "+47 21316260",
|
103 |
+
"other_name": "Norway Post, Norska Posten",
|
104 |
+
"web_url": "http://www.posten.no/en/",
|
105 |
+
"required_fields": []
|
106 |
+
},
|
107 |
+
{
|
108 |
+
"slug": "hong-kong-post",
|
109 |
+
"name": "Hong Kong Post",
|
110 |
+
"phone": "+852 2921 2222",
|
111 |
+
"other_name": "香港郵政",
|
112 |
+
"web_url": "http://hongkongpost.com",
|
113 |
+
"required_fields": []
|
114 |
+
},
|
115 |
+
{
|
116 |
+
"slug": "portugal-seur",
|
117 |
+
"name": "Portugal Seur",
|
118 |
+
"phone": "+351 707 50 10 10",
|
119 |
+
"other_name": "SEUR",
|
120 |
+
"web_url": "http://www.seur.com/",
|
121 |
+
"required_fields": []
|
122 |
+
},
|
123 |
+
{
|
124 |
+
"slug": "international-seur",
|
125 |
+
"name": "International Seur",
|
126 |
+
"phone": "+34 902101010",
|
127 |
+
"other_name": "SEUR Internacional",
|
128 |
+
"web_url": "http://www.seur.com/",
|
129 |
+
"required_fields": []
|
130 |
+
},
|
131 |
+
{
|
132 |
+
"slug": "4px",
|
133 |
+
"name": "4PX",
|
134 |
+
"phone": "+86 755-33936349",
|
135 |
+
"other_name": "递四方",
|
136 |
+
"web_url": "http://express.4px.com/",
|
137 |
+
"required_fields": []
|
138 |
+
},
|
139 |
+
{
|
140 |
+
"slug": "yrc",
|
141 |
+
"name": "YRC",
|
142 |
+
"phone": "+1 800-468-5739",
|
143 |
+
"other_name": "YRC Freight",
|
144 |
+
"web_url": "http://www.yrc.com/",
|
145 |
+
"required_fields": []
|
146 |
+
},
|
147 |
+
{
|
148 |
+
"slug": "dpd-de",
|
149 |
+
"name": "DPD Germany",
|
150 |
+
"phone": "+49 01806 373 200",
|
151 |
+
"other_name": "DPD Germany",
|
152 |
+
"web_url": "https://www.dpd.com/",
|
153 |
+
"required_fields": []
|
154 |
+
},
|
155 |
+
{
|
156 |
+
"slug": "delhivery",
|
157 |
+
"name": "Delhivery",
|
158 |
+
"phone": "+91 (124) 4718900",
|
159 |
+
"other_name": "Gharpay",
|
160 |
+
"web_url": "http://www.delhivery.com/",
|
161 |
+
"required_fields": []
|
162 |
+
},
|
163 |
+
{
|
164 |
+
"slug": "canada-post",
|
165 |
+
"name": "Canada Post",
|
166 |
+
"phone": "+1 866 607 6301",
|
167 |
+
"other_name": "Postes Canada",
|
168 |
+
"web_url": "https://www.canadapost.ca/",
|
169 |
+
"required_fields": []
|
170 |
+
},
|
171 |
+
{
|
172 |
+
"slug": "aramex",
|
173 |
+
"name": "Aramex",
|
174 |
+
"phone": "+1 (718) 5538740",
|
175 |
+
"other_name": "ارامكس",
|
176 |
+
"web_url": "http://www.aramex.com/",
|
177 |
+
"required_fields": []
|
178 |
+
},
|
179 |
+
{
|
180 |
+
"slug": "gati-kwe",
|
181 |
+
"name": "Gati-KWE",
|
182 |
+
"phone": "+91 1800-180-4284",
|
183 |
+
"other_name": "Gati-Kintetsu Express",
|
184 |
+
"web_url": "http://www.gatikwe.com/",
|
185 |
+
"required_fields": []
|
186 |
+
},
|
187 |
+
{
|
188 |
+
"slug": "dhl-global-mail-asia",
|
189 |
+
"name": "DHL Global Mail Asia",
|
190 |
+
"phone": "+65 6883 0771",
|
191 |
+
"other_name": "DGM Asia",
|
192 |
+
"web_url": "http://www.dhlglobalmail.com/",
|
193 |
+
"required_fields": []
|
194 |
+
},
|
195 |
+
{
|
196 |
+
"slug": "dhl-poland",
|
197 |
+
"name": "DHL Poland",
|
198 |
+
"phone": "+48 42 6 345 345",
|
199 |
+
"other_name": "DHL Polska",
|
200 |
+
"web_url": "http://www.dhl.com.pl/",
|
201 |
+
"required_fields": []
|
202 |
+
},
|
203 |
+
{
|
204 |
+
"slug": "tnt-uk",
|
205 |
+
"name": "TNT UK",
|
206 |
+
"phone": "+44 0800 100 600",
|
207 |
+
"other_name": "TNT United Kingdom",
|
208 |
+
"web_url": "http://www.tnt.com/",
|
209 |
+
"required_fields": []
|
210 |
+
},
|
211 |
+
{
|
212 |
+
"slug": "asendia-usa",
|
213 |
+
"name": "Asendia USA",
|
214 |
+
"phone": "+1 610 461 3661",
|
215 |
+
"other_name": "Brokers Worldwide",
|
216 |
+
"web_url": "http://www.brokersworldwide.com/",
|
217 |
+
"required_fields": []
|
218 |
+
},
|
219 |
+
{
|
220 |
+
"slug": "posti",
|
221 |
+
"name": "Itella Posti",
|
222 |
+
"phone": "+358 200 71000",
|
223 |
+
"other_name": "Finland Post",
|
224 |
+
"web_url": "http://www.posti.fi/",
|
225 |
+
"required_fields": []
|
226 |
+
},
|
227 |
+
{
|
228 |
+
"slug": "tnt-it",
|
229 |
+
"name": "TNT Italy",
|
230 |
+
"phone": "+39 199 803 868",
|
231 |
+
"other_name": "TNT Express IT",
|
232 |
+
"web_url": "http://www.tnt.it/",
|
233 |
+
"required_fields": []
|
234 |
+
},
|
235 |
+
{
|
236 |
+
"slug": "nova-poshta",
|
237 |
+
"name": "Nova Poshta",
|
238 |
+
"phone": "+7 (0) 800 500 609",
|
239 |
+
"other_name": "Новая Почта",
|
240 |
+
"web_url": "http://novaposhta.ua/",
|
241 |
+
"required_fields": []
|
242 |
+
},
|
243 |
+
{
|
244 |
+
"slug": "cambodia-post",
|
245 |
+
"name": "Cambodia Post",
|
246 |
+
"phone": "+855 23 723 51",
|
247 |
+
"other_name": "Cambodia Post",
|
248 |
+
"web_url": "http://www.ems.com.kh/",
|
249 |
+
"required_fields": []
|
250 |
+
},
|
251 |
+
{
|
252 |
+
"slug": "fedex-uk",
|
253 |
+
"name": "FedEx UK",
|
254 |
+
"phone": "+ 44 2476 706 660",
|
255 |
+
"other_name": "FedEx United Kingdom",
|
256 |
+
"web_url": "http://www.fedex.com/ukservices",
|
257 |
+
"required_fields": []
|
258 |
+
},
|
259 |
+
{
|
260 |
+
"slug": "xend",
|
261 |
+
"name": "Xend",
|
262 |
+
"phone": "+63 2 806 9363",
|
263 |
+
"other_name": "Xend Business Solutions",
|
264 |
+
"web_url": "http://xendexpress.com/",
|
265 |
+
"required_fields": []
|
266 |
+
},
|
267 |
+
{
|
268 |
+
"slug": "2go",
|
269 |
+
"name": "2GO",
|
270 |
+
"phone": "+63 2 77-99-222",
|
271 |
+
"other_name": "Negros Navigation",
|
272 |
+
"web_url": "http://supplychain.2go.com.ph/",
|
273 |
+
"required_fields": []
|
274 |
+
},
|
275 |
+
{
|
276 |
+
"slug": "chronopost-france",
|
277 |
+
"name": "Chronopost France",
|
278 |
+
"phone": "+33 (0) 969 391 391",
|
279 |
+
"other_name": "La Poste EMS",
|
280 |
+
"web_url": "http://www.chronopost.fr/",
|
281 |
+
"required_fields": []
|
282 |
+
},
|
283 |
+
{
|
284 |
+
"slug": "tnt-au",
|
285 |
+
"name": "TNT Australia",
|
286 |
+
"phone": "+61 13 11 50",
|
287 |
+
"other_name": "TNT AU",
|
288 |
+
"web_url": "http://www.tntexpress.com.au/",
|
289 |
+
"required_fields": []
|
290 |
+
},
|
291 |
+
{
|
292 |
+
"slug": "acscourier",
|
293 |
+
"name": "ACS Courier",
|
294 |
+
"phone": "+30 210 81 90 000",
|
295 |
+
"other_name": "Αναζήτηση Καταστημάτων",
|
296 |
+
"web_url": "https://www.acscourier.net/",
|
297 |
+
"required_fields": []
|
298 |
+
},
|
299 |
+
{
|
300 |
+
"slug": "uk-mail",
|
301 |
+
"name": "UK Mail",
|
302 |
+
"phone": "+44 8451 554 455",
|
303 |
+
"other_name": "Business Post Group",
|
304 |
+
"web_url": "https://www.ukmail.com",
|
305 |
+
"required_fields": []
|
306 |
+
},
|
307 |
+
{
|
308 |
+
"slug": "siodemka",
|
309 |
+
"name": "Siodemka",
|
310 |
+
"phone": "+48 22 777 77 77 ext. 3",
|
311 |
+
"other_name": "Siodemka Kurier",
|
312 |
+
"web_url": "http://www.siodemka.com/",
|
313 |
+
"required_fields": []
|
314 |
+
},
|
315 |
+
{
|
316 |
+
"slug": "kn",
|
317 |
+
"name": "Kuehne + Nagel",
|
318 |
+
"phone": "+41-44-7869511",
|
319 |
+
"other_name": "KN",
|
320 |
+
"web_url": "http://www.kn-portal.com/",
|
321 |
+
"required_fields": []
|
322 |
+
},
|
323 |
+
{
|
324 |
+
"slug": "safexpress",
|
325 |
+
"name": "Safexpress",
|
326 |
+
"phone": "+91 1800 113 113",
|
327 |
+
"other_name": "Safexpress",
|
328 |
+
"web_url": "http://www.safexpress.com/",
|
329 |
+
"required_fields": []
|
330 |
+
},
|
331 |
+
{
|
332 |
+
"slug": "skynet",
|
333 |
+
"name": "SkyNet Malaysia",
|
334 |
+
"phone": "+60 3- 56239090",
|
335 |
+
"other_name": "SkyNet MY",
|
336 |
+
"web_url": "http://www.skynet.com.my/",
|
337 |
+
"required_fields": []
|
338 |
+
},
|
339 |
+
{
|
340 |
+
"slug": "nipost",
|
341 |
+
"name": "NiPost",
|
342 |
+
"phone": "+234 09-3149531",
|
343 |
+
"other_name": "Nigerian Postal Service",
|
344 |
+
"web_url": "http://www.emsng.com/",
|
345 |
+
"required_fields": []
|
346 |
+
},
|
347 |
+
{
|
348 |
+
"slug": "oca-ar",
|
349 |
+
"name": "OCA Argentina",
|
350 |
+
"phone": "+34 800-999-7700",
|
351 |
+
"other_name": "OCA e-Pak",
|
352 |
+
"web_url": "http://www.oca.com.ar/",
|
353 |
+
"required_fields": []
|
354 |
+
},
|
355 |
+
{
|
356 |
+
"slug": "aeroflash",
|
357 |
+
"name": "Mexico AeroFlash",
|
358 |
+
"phone": "+52 55 5445 2100",
|
359 |
+
"other_name": "AeroFlash",
|
360 |
+
"web_url": "http://www.aeroflash.com.mx/",
|
361 |
+
"required_fields": []
|
362 |
+
},
|
363 |
+
{
|
364 |
+
"slug": "sapo",
|
365 |
+
"name": "South African Post Office",
|
366 |
+
"phone": "+27 0860 111 502",
|
367 |
+
"other_name": "South African Post Office",
|
368 |
+
"web_url": "http://www.postoffice.co.za/",
|
369 |
+
"required_fields": []
|
370 |
+
},
|
371 |
+
{
|
372 |
+
"slug": "taqbin-hk",
|
373 |
+
"name": "TAQBIN Hong Kong",
|
374 |
+
"phone": "+852 2829 2222",
|
375 |
+
"other_name": "Yamat, 雅瑪多運輸- 宅急便",
|
376 |
+
"web_url": "http://hk.ta-q-bin.com/",
|
377 |
+
"required_fields": []
|
378 |
+
},
|
379 |
+
{
|
380 |
+
"slug": "deltec-courier",
|
381 |
+
"name": "Deltec Courier",
|
382 |
+
"phone": "+44 (0) 20 8569 6767",
|
383 |
+
"other_name": "Deltec Interntional Courier",
|
384 |
+
"web_url": "https://www.deltec-courier.com/",
|
385 |
+
"required_fields": []
|
386 |
+
},
|
387 |
+
{
|
388 |
+
"slug": "mexico-senda-express",
|
389 |
+
"name": "Mexico Senda Express",
|
390 |
+
"phone": "+52 1800 833 93 00",
|
391 |
+
"other_name": "Mexico Senda Express",
|
392 |
+
"web_url": "http://www.sendaexpress.com.mx/",
|
393 |
+
"required_fields": []
|
394 |
+
},
|
395 |
+
{
|
396 |
+
"slug": "mexico-redpack",
|
397 |
+
"name": "Mexico Redpack",
|
398 |
+
"phone": "+52 1800-013-3333",
|
399 |
+
"other_name": "TNT Mexico",
|
400 |
+
"web_url": "http://www.redpack.com.mx/",
|
401 |
+
"required_fields": []
|
402 |
+
},
|
403 |
+
{
|
404 |
+
"slug": "mexico-multipack",
|
405 |
+
"name": "Mexico Multipack",
|
406 |
+
"phone": "+52 1800 7023200",
|
407 |
+
"other_name": "Fedex Mexico",
|
408 |
+
"web_url": "http://www.multipack.com.mx/",
|
409 |
+
"required_fields": []
|
410 |
+
},
|
411 |
+
{
|
412 |
+
"slug": "japan-post",
|
413 |
+
"name": "Japan Post",
|
414 |
+
"phone": "+81 0570-046111",
|
415 |
+
"other_name": "日本郵便",
|
416 |
+
"web_url": "http://www.post.japanpost.jp/top.html",
|
417 |
+
"required_fields": []
|
418 |
+
},
|
419 |
+
{
|
420 |
+
"slug": "sagawa",
|
421 |
+
"name": "Sagawa",
|
422 |
+
"phone": "+81 0120-18-9595",
|
423 |
+
"other_name": "佐川急便",
|
424 |
+
"web_url": "http://www.sagawa-exp.co.jp/",
|
425 |
+
"required_fields": []
|
426 |
+
},
|
427 |
+
{
|
428 |
+
"slug": "tgx",
|
429 |
+
"name": "TGX",
|
430 |
+
"phone": "+852 3513 0888",
|
431 |
+
"other_name": "Top Gun Express, 精英速運",
|
432 |
+
"web_url": "http://www.tgxpress.com/",
|
433 |
+
"required_fields": []
|
434 |
+
},
|
435 |
+
{
|
436 |
+
"slug": "vnpost-ems",
|
437 |
+
"name": "Vietnam Post EMS",
|
438 |
+
"phone": "+84 1900 54 54 81",
|
439 |
+
"other_name": "VNPost EMS",
|
440 |
+
"web_url": "http://www.vnpost.vn/",
|
441 |
+
"required_fields": []
|
442 |
+
},
|
443 |
+
{
|
444 |
+
"slug": "viettelpost",
|
445 |
+
"name": "ViettelPost",
|
446 |
+
"phone": "+84-4 6266 2200",
|
447 |
+
"other_name": "Bưu chính Viettel",
|
448 |
+
"web_url": "http://www.viettelpost.com.vn/",
|
449 |
+
"required_fields": []
|
450 |
+
},
|
451 |
+
{
|
452 |
+
"slug": "postnl-3s",
|
453 |
+
"name": "PostNL International 3S",
|
454 |
+
"phone": "+31 (0)900 0990",
|
455 |
+
"other_name": "TNT Post parcel service United Kingdom",
|
456 |
+
"web_url": "http://www.postnl.nl/voorthuis/",
|
457 |
+
"required_fields": []
|
458 |
+
},
|
459 |
+
{
|
460 |
+
"slug": "tiki",
|
461 |
+
"name": "Tiki",
|
462 |
+
"phone": "+62 500 125",
|
463 |
+
"other_name": "Citra Van Titipan Kilat",
|
464 |
+
"web_url": "http://www.tiki-online.com/",
|
465 |
+
"required_fields": []
|
466 |
+
},
|
467 |
+
{
|
468 |
+
"slug": "opek",
|
469 |
+
"name": "OPEK",
|
470 |
+
"phone": "+48 22 732 79 99",
|
471 |
+
"other_name": "OPEK Sp. z oo",
|
472 |
+
"web_url": "http://www.opek.com.pl/",
|
473 |
+
"required_fields": []
|
474 |
+
},
|
475 |
+
{
|
476 |
+
"slug": "dpd-poland",
|
477 |
+
"name": "DPD Poland",
|
478 |
+
"phone": "+48 801 400 373",
|
479 |
+
"other_name": "Dynamic Parcel Distribution Poland",
|
480 |
+
"web_url": "http://www.dpd.com.pl/",
|
481 |
+
"required_fields": []
|
482 |
+
},
|
483 |
+
{
|
484 |
+
"slug": "ceska-posta",
|
485 |
+
"name": "Česká Pošta",
|
486 |
+
"phone": "+420 840 111 244",
|
487 |
+
"other_name": "Czech Post",
|
488 |
+
"web_url": "http://www.ceskaposta.cz/",
|
489 |
+
"required_fields": []
|
490 |
+
},
|
491 |
+
{
|
492 |
+
"slug": "geodis-calberson-fr",
|
493 |
+
"name": "Geodis Calberson France",
|
494 |
+
"phone": "+33 (0)1 70 15 16 17",
|
495 |
+
"other_name": "Geodiscalberson",
|
496 |
+
"web_url": "http://www.espacedestinataire.mobi/client/42228/mobile/index.html",
|
497 |
+
"required_fields": [
|
498 |
+
"tracking_postal_code"
|
499 |
+
]
|
500 |
+
},
|
501 |
+
{
|
502 |
+
"slug": "ppbyb",
|
503 |
+
"name": "PayPal Package",
|
504 |
+
"phone": "+86 20 11185",
|
505 |
+
"other_name": "贝邮宝",
|
506 |
+
"web_url": "http://www.ppbyb.com/",
|
507 |
+
"required_fields": []
|
508 |
+
},
|
509 |
+
{
|
510 |
+
"slug": "apc",
|
511 |
+
"name": "APC Postal Logistics",
|
512 |
+
"phone": "+1 (888) 413-7300",
|
513 |
+
"other_name": "APC-PLI",
|
514 |
+
"web_url": "http://www.apc-pli.com/",
|
515 |
+
"required_fields": []
|
516 |
+
},
|
517 |
+
{
|
518 |
+
"slug": "red-express-wb",
|
519 |
+
"name": "Red Express Waybill",
|
520 |
+
"phone": "+91 1800-123-2400",
|
521 |
+
"other_name": "Red Express WayBill",
|
522 |
+
"web_url": "https://www.getsetred.net",
|
523 |
+
"required_fields": []
|
524 |
+
},
|
525 |
+
{
|
526 |
+
"slug": "professional-couriers",
|
527 |
+
"name": "Professional Couriers",
|
528 |
+
"phone": "+91 0124-4405730",
|
529 |
+
"other_name": "TPC India",
|
530 |
+
"web_url": "http://www.tpcindia.com/",
|
531 |
+
"required_fields": []
|
532 |
+
},
|
533 |
+
{
|
534 |
+
"slug": "gojavas",
|
535 |
+
"name": "GoJaVAS",
|
536 |
+
"phone": "+91 0124-4405730",
|
537 |
+
"other_name": "JaVAS",
|
538 |
+
"web_url": "http://gojavas.com/",
|
539 |
+
"required_fields": []
|
540 |
+
},
|
541 |
+
{
|
542 |
+
"slug": "cj-gls",
|
543 |
+
"name": "CJ GLS",
|
544 |
+
"phone": "+63-567-1320",
|
545 |
+
"other_name": "CJ Korea Express, 씨제이지엘에스주식회사",
|
546 |
+
"web_url": "http://www.cjgls.com/eng/",
|
547 |
+
"required_fields": []
|
548 |
+
},
|
549 |
+
{
|
550 |
+
"slug": "estafeta",
|
551 |
+
"name": "Estafeta",
|
552 |
+
"phone": "+52 1-800-378-2338",
|
553 |
+
"other_name": "Estafeta Mexicana",
|
554 |
+
"web_url": "http://www.estafeta.com/default.aspx",
|
555 |
+
"required_fields": []
|
556 |
+
},
|
557 |
+
{
|
558 |
+
"slug": "ups-freight",
|
559 |
+
"name": "UPS Freight",
|
560 |
+
"phone": "+1 800-333-7400",
|
561 |
+
"other_name": "UPS LTL and Truckload",
|
562 |
+
"web_url": "http://ltl.upsfreight.com/",
|
563 |
+
"required_fields": []
|
564 |
+
},
|
565 |
+
{
|
566 |
+
"slug": "singapore-speedpost",
|
567 |
+
"name": "Singapore Speedpost",
|
568 |
+
"phone": "+65 6222 5777",
|
569 |
+
"other_name": "Singapore EMS",
|
570 |
+
"web_url": "http://www.speedpost.com.sg/",
|
571 |
+
"required_fields": []
|
572 |
+
},
|
573 |
+
{
|
574 |
+
"slug": "purolator",
|
575 |
+
"name": "Purolator",
|
576 |
+
"phone": "+1-888-744-7123",
|
577 |
+
"other_name": "Purolator Freight",
|
578 |
+
"web_url": "http://www.purolator.com/",
|
579 |
+
"required_fields": []
|
580 |
+
},
|
581 |
+
{
|
582 |
+
"slug": "toll-global-express",
|
583 |
+
"name": "Toll Global Express",
|
584 |
+
"phone": "+61 13 15 31",
|
585 |
+
"other_name": "DPEX",
|
586 |
+
"web_url": "http://www.dpex.com/",
|
587 |
+
"required_fields": []
|
588 |
+
},
|
589 |
+
{
|
590 |
+
"slug": "ontrac",
|
591 |
+
"name": "OnTrac",
|
592 |
+
"phone": "+1 800 334 5000",
|
593 |
+
"other_name": "OnTrac Shipping",
|
594 |
+
"web_url": "https://www.ontrac.com",
|
595 |
+
"required_fields": []
|
596 |
+
},
|
597 |
+
{
|
598 |
+
"slug": "evergreen",
|
599 |
+
"name": "Evergreen",
|
600 |
+
"phone": "+1 201-7613000",
|
601 |
+
"other_name": "Evergreen Marine Corp",
|
602 |
+
"web_url": "http://www.evergreen-marine.com/",
|
603 |
+
"required_fields": []
|
604 |
+
},
|
605 |
+
{
|
606 |
+
"slug": "korea-post",
|
607 |
+
"name": "Korea Post",
|
608 |
+
"phone": "+82 2 2195 1114",
|
609 |
+
"other_name": "우정사업본부",
|
610 |
+
"web_url": "http://www.koreapost.go.kr",
|
611 |
+
"required_fields": []
|
612 |
+
},
|
613 |
+
{
|
614 |
+
"slug": "nacex-spain",
|
615 |
+
"name": "NACEX Spain",
|
616 |
+
"phone": "+34 900 100 000",
|
617 |
+
"other_name": "NACEX Logista",
|
618 |
+
"web_url": "http://nacex.es/",
|
619 |
+
"required_fields": [
|
620 |
+
"tracking_postal_code"
|
621 |
+
]
|
622 |
+
},
|
623 |
+
{
|
624 |
+
"slug": "lasership",
|
625 |
+
"name": "LaserShip",
|
626 |
+
"phone": "+1 (800) 527-3764",
|
627 |
+
"other_name": "LaserShip",
|
628 |
+
"web_url": "http://www.lasership.com/",
|
629 |
+
"required_fields": []
|
630 |
+
},
|
631 |
+
{
|
632 |
+
"slug": "china-ems",
|
633 |
+
"name": "China EMS",
|
634 |
+
"phone": "+86 20 11183",
|
635 |
+
"other_name": "中国邮政速递物流",
|
636 |
+
"web_url": "http://www.11183.com.cn/english.html",
|
637 |
+
"required_fields": []
|
638 |
+
},
|
639 |
+
{
|
640 |
+
"slug": "china-post",
|
641 |
+
"name": "China Post",
|
642 |
+
"phone": "+86 20 11185",
|
643 |
+
"other_name": "中国邮政, ePacket, e-Packet",
|
644 |
+
"web_url": "http://www.chinapost.com.cn/",
|
645 |
+
"required_fields": []
|
646 |
+
},
|
647 |
+
{
|
648 |
+
"slug": "taqbin-sg",
|
649 |
+
"name": "TAQBIN Singapore",
|
650 |
+
"phone": "+65 6595 4640",
|
651 |
+
"other_name": "Yamato Singapore",
|
652 |
+
"web_url": "http://sg.ta-q-bin.com/",
|
653 |
+
"required_fields": []
|
654 |
+
},
|
655 |
+
{
|
656 |
+
"slug": "bgpost",
|
657 |
+
"name": "Bulgarian Posts",
|
658 |
+
"phone": "+3592/949 3280",
|
659 |
+
"other_name": "Български пощи",
|
660 |
+
"web_url": "http://www.bgpost.bg/",
|
661 |
+
"required_fields": []
|
662 |
+
},
|
663 |
+
{
|
664 |
+
"slug": "brazil-correios",
|
665 |
+
"name": "Brazil Correios",
|
666 |
+
"phone": "+55 61 3003 0100",
|
667 |
+
"other_name": "Brazilian Post",
|
668 |
+
"web_url": "http://correios.com.br/",
|
669 |
+
"required_fields": []
|
670 |
+
},
|
671 |
+
{
|
672 |
+
"slug": "fedex",
|
673 |
+
"name": "FedEx",
|
674 |
+
"phone": "+1 800 247 4747",
|
675 |
+
"other_name": "Federal Express",
|
676 |
+
"web_url": "http://www.fedex.com/",
|
677 |
+
"required_fields": []
|
678 |
+
},
|
679 |
+
{
|
680 |
+
"slug": "ukrposhta",
|
681 |
+
"name": "UkrPoshta",
|
682 |
+
"phone": "+380 (0) 800-500-440",
|
683 |
+
"other_name": "Укрпошта",
|
684 |
+
"web_url": "http://www.ukrposhta.com/",
|
685 |
+
"required_fields": []
|
686 |
+
},
|
687 |
+
{
|
688 |
+
"slug": "toll-priority",
|
689 |
+
"name": "Toll Priority",
|
690 |
+
"phone": "+61 13 15 31",
|
691 |
+
"other_name": "Toll Group, Toll Priority",
|
692 |
+
"web_url": "https://www.tollpriority.com.au/portal/page/portal/TOLL_PRIORITY/Home",
|
693 |
+
"required_fields": []
|
694 |
+
},
|
695 |
+
{
|
696 |
+
"slug": "jam-express",
|
697 |
+
"name": "Jam Express",
|
698 |
+
"phone": "+63 239 7502",
|
699 |
+
"other_name": "JAM Global Express",
|
700 |
+
"web_url": "http://www.myjamexpress.com/",
|
701 |
+
"required_fields": []
|
702 |
+
},
|
703 |
+
{
|
704 |
+
"slug": "estes",
|
705 |
+
"name": "Estes",
|
706 |
+
"phone": "+1-886-378-3748",
|
707 |
+
"other_name": "Estes Express Lines",
|
708 |
+
"web_url": "http://www.estes-express.com",
|
709 |
+
"required_fields": []
|
710 |
+
},
|
711 |
+
{
|
712 |
+
"slug": "flytexpress",
|
713 |
+
"name": "Flyt Express",
|
714 |
+
"phone": "+1 400-888-4003",
|
715 |
+
"other_name": "飞特物流",
|
716 |
+
"web_url": "http://www.flytexpress.com/",
|
717 |
+
"required_fields": []
|
718 |
+
},
|
719 |
+
{
|
720 |
+
"slug": "rpxonline",
|
721 |
+
"name": "RPX Online",
|
722 |
+
"phone": "+852 2620 0289",
|
723 |
+
"other_name": "Cathay Pacific",
|
724 |
+
"web_url": "http://www.rpxonline.com/",
|
725 |
+
"required_fields": []
|
726 |
+
},
|
727 |
+
{
|
728 |
+
"slug": "17postservice",
|
729 |
+
"name": "17 Post Service",
|
730 |
+
"phone": "+852 2620 0289",
|
731 |
+
"other_name": "17PostService",
|
732 |
+
"web_url": "http://17postservice.com/",
|
733 |
+
"required_fields": []
|
734 |
+
},
|
735 |
+
{
|
736 |
+
"slug": "ghn",
|
737 |
+
"name": "Giao hàng nhanh",
|
738 |
+
"phone": "+84 19006491",
|
739 |
+
"other_name": "Giaohangnhanh.vn, GHN",
|
740 |
+
"web_url": "http://giaohangnhanh.vn/",
|
741 |
+
"required_fields": []
|
742 |
+
},
|
743 |
+
{
|
744 |
+
"slug": "raf",
|
745 |
+
"name": "RAF Philippines",
|
746 |
+
"phone": "+632 820-2920 to 25",
|
747 |
+
"other_name": "RAF Int'l. Forwarding",
|
748 |
+
"web_url": "http://www.raf.ph/",
|
749 |
+
"required_fields": []
|
750 |
+
},
|
751 |
+
{
|
752 |
+
"slug": "trakpak",
|
753 |
+
"name": "TrakPak",
|
754 |
+
"phone": "+27 21 528 1000",
|
755 |
+
"other_name": "bpost international P2P Mailing Trak Pak",
|
756 |
+
"web_url": "http://www.trackmytrakpak.com/",
|
757 |
+
"required_fields": []
|
758 |
+
},
|
759 |
+
{
|
760 |
+
"slug": "lietuvos-pastas",
|
761 |
+
"name": "Lietuvos paštas",
|
762 |
+
"phone": "+370 8 700 55 400",
|
763 |
+
"other_name": "Lithuania Post, LP Express",
|
764 |
+
"web_url": "http://www.post.lt/",
|
765 |
+
"required_fields": []
|
766 |
+
},
|
767 |
+
{
|
768 |
+
"slug": "equick-cn",
|
769 |
+
"name": "Equick China",
|
770 |
+
"phone": "+1 400 706 6078",
|
771 |
+
"other_name": "北京网易速达",
|
772 |
+
"web_url": "http://www.equick.cn/",
|
773 |
+
"required_fields": []
|
774 |
+
},
|
775 |
+
{
|
776 |
+
"slug": "taqbin-jp",
|
777 |
+
"name": "Yamato Japan",
|
778 |
+
"phone": "+81 0120-17-9625",
|
779 |
+
"other_name": "ヤマト運輸, TAQBIN",
|
780 |
+
"web_url": "http://www.kuronekoyamato.co.jp/en/",
|
781 |
+
"required_fields": []
|
782 |
+
},
|
783 |
+
{
|
784 |
+
"slug": "courierit",
|
785 |
+
"name": "Courier IT",
|
786 |
+
"phone": "+27 21 555 6777",
|
787 |
+
"other_name": "Courierit",
|
788 |
+
"web_url": "http://www.courierit.co.za/",
|
789 |
+
"required_fields": []
|
790 |
+
},
|
791 |
+
{
|
792 |
+
"slug": "city-link-international",
|
793 |
+
"name": "City Link International",
|
794 |
+
"phone": "+44 (0) 8444 930 930",
|
795 |
+
"other_name": "citylink.norsknet.com",
|
796 |
+
"web_url": "http://citylink.norsknet.com/",
|
797 |
+
"required_fields": []
|
798 |
+
},
|
799 |
+
{
|
800 |
+
"slug": "red-express",
|
801 |
+
"name": "Red Express",
|
802 |
+
"phone": "+91 1800-123-2400",
|
803 |
+
"other_name": "Red Express",
|
804 |
+
"web_url": "https://www.getsetred.net",
|
805 |
+
"required_fields": []
|
806 |
+
},
|
807 |
+
{
|
808 |
+
"slug": "dtdc",
|
809 |
+
"name": "DTDC India",
|
810 |
+
"phone": "+91 33004444",
|
811 |
+
"other_name": "DTDC Courier & Cargo",
|
812 |
+
"web_url": "http://dtdc.com/",
|
813 |
+
"required_fields": []
|
814 |
+
},
|
815 |
+
{
|
816 |
+
"slug": "interlink-express",
|
817 |
+
"name": "Interlink Express",
|
818 |
+
"phone": "+44 8702 200 300",
|
819 |
+
"other_name": "Interlink UK",
|
820 |
+
"web_url": "http://www.interlinkexpress.com/",
|
821 |
+
"required_fields": []
|
822 |
+
},
|
823 |
+
{
|
824 |
+
"slug": "flash-courier",
|
825 |
+
"name": "Flash Courier",
|
826 |
+
"phone": "+55 011 5033 3260",
|
827 |
+
"other_name": "Flash Courier Brazil",
|
828 |
+
"web_url": "http://www.jall.com.br/",
|
829 |
+
"required_fields": []
|
830 |
+
},
|
831 |
+
{
|
832 |
+
"slug": "austrian-post",
|
833 |
+
"name": "Austrian Post (Express)",
|
834 |
+
"phone": "+43 810 010 100",
|
835 |
+
"other_name": "Österreichische Post AG",
|
836 |
+
"web_url": "http://www.post.at",
|
837 |
+
"required_fields": []
|
838 |
+
},
|
839 |
+
{
|
840 |
+
"slug": "star-track",
|
841 |
+
"name": "StarTrack",
|
842 |
+
"phone": "+61 13 2345",
|
843 |
+
"other_name": "Star Track",
|
844 |
+
"web_url": "http://startrack.com.au/",
|
845 |
+
"required_fields": []
|
846 |
+
},
|
847 |
+
{
|
848 |
+
"slug": "star-track-express",
|
849 |
+
"name": "Star Track Express",
|
850 |
+
"phone": "+61 13 2345",
|
851 |
+
"other_name": "AaE Australian air Express",
|
852 |
+
"web_url": "http://www.star-track.com.au/",
|
853 |
+
"required_fields": []
|
854 |
+
},
|
855 |
+
{
|
856 |
+
"slug": "jne",
|
857 |
+
"name": "JNE",
|
858 |
+
"phone": "+62 021-29278888",
|
859 |
+
"other_name": "Express Across Nation, Tiki Jalur Nugraha Ekakurir",
|
860 |
+
"web_url": "http://www.jne.co.id/",
|
861 |
+
"required_fields": []
|
862 |
+
},
|
863 |
+
{
|
864 |
+
"slug": "rpx",
|
865 |
+
"name": "RPX Indonesia",
|
866 |
+
"phone": "+62 0-800-1-888-900",
|
867 |
+
"other_name": "Repex Perdana International",
|
868 |
+
"web_url": "http://www.rpxholding.com/",
|
869 |
+
"required_fields": []
|
870 |
+
},
|
871 |
+
{
|
872 |
+
"slug": "first-logistics",
|
873 |
+
"name": "First Logistics",
|
874 |
+
"phone": "+62 021 - 73880707",
|
875 |
+
"other_name": "PT Synergy First Logistics",
|
876 |
+
"web_url": "http://www.jne.co.id/",
|
877 |
+
"required_fields": []
|
878 |
+
},
|
879 |
+
{
|
880 |
+
"slug": "brt-it",
|
881 |
+
"name": "BRT Bartolini",
|
882 |
+
"phone": "+39 011 397 411 1",
|
883 |
+
"other_name": "BRT Corriere Espresso, DPD Italy",
|
884 |
+
"web_url": "http://www.brt.it/",
|
885 |
+
"required_fields": []
|
886 |
+
},
|
887 |
+
{
|
888 |
+
"slug": "postnord",
|
889 |
+
"name": "PostNord Logistics",
|
890 |
+
"phone": "+46 771 33 33 10",
|
891 |
+
"other_name": "Posten Norden",
|
892 |
+
"web_url": "http://www.postnordlogistics.com/",
|
893 |
+
"required_fields": []
|
894 |
+
},
|
895 |
+
{
|
896 |
+
"slug": "belpost",
|
897 |
+
"name": "Belpost",
|
898 |
+
"phone": "+375 17 293 59 10",
|
899 |
+
"other_name": "Belposhta, Белпочта",
|
900 |
+
"web_url": "http://www.belpost.by",
|
901 |
+
"required_fields": []
|
902 |
+
},
|
903 |
+
{
|
904 |
+
"slug": "cyprus-post",
|
905 |
+
"name": "Cyprus Post",
|
906 |
+
"phone": "+357 22805802",
|
907 |
+
"other_name": "ΚΥΠΡΙΑΚΑ ΤΑΧΥΔΡΟΜΕΙΑ",
|
908 |
+
"web_url": "http://www.mcw.gov.cy/mcw/postal/dps.nsf/index_en/index_en",
|
909 |
+
"required_fields": []
|
910 |
+
},
|
911 |
+
{
|
912 |
+
"slug": "spanish-seur",
|
913 |
+
"name": "Spanish Seur",
|
914 |
+
"phone": "+34 902101010",
|
915 |
+
"other_name": "SEUR",
|
916 |
+
"web_url": "http://www.seur.com/",
|
917 |
+
"required_fields": []
|
918 |
+
},
|
919 |
+
{
|
920 |
+
"slug": "air21",
|
921 |
+
"name": "AIR21",
|
922 |
+
"phone": "+63 (02) 854-2100",
|
923 |
+
"other_name": "AIR 21 PH",
|
924 |
+
"web_url": "http://www.air21.com.ph",
|
925 |
+
"required_fields": []
|
926 |
+
},
|
927 |
+
{
|
928 |
+
"slug": "lbcexpress",
|
929 |
+
"name": "LBC Express",
|
930 |
+
"phone": "+63 800-10-8585999",
|
931 |
+
"other_name": "LBC Express",
|
932 |
+
"web_url": "http://www.lbcexpress.com/",
|
933 |
+
"required_fields": []
|
934 |
+
},
|
935 |
+
{
|
936 |
+
"slug": "israel-post",
|
937 |
+
"name": "Israel Post",
|
938 |
+
"phone": "+972 2 629 0691",
|
939 |
+
"other_name": "חברת דואר ישראל",
|
940 |
+
"web_url": "http://www.israelpost.co.il",
|
941 |
+
"required_fields": []
|
942 |
+
},
|
943 |
+
{
|
944 |
+
"slug": "vnpost",
|
945 |
+
"name": "Vietnam Post",
|
946 |
+
"phone": "+84 1900 54 54 81",
|
947 |
+
"other_name": "VNPost",
|
948 |
+
"web_url": "http://www.vnpost.vn/",
|
949 |
+
"required_fields": []
|
950 |
+
},
|
951 |
+
{
|
952 |
+
"slug": "rl-carriers",
|
953 |
+
"name": "RL Carriers",
|
954 |
+
"phone": "+1 800-543-5589",
|
955 |
+
"other_name": "R+L Carriers",
|
956 |
+
"web_url": "http://www.rlcarriers.com/",
|
957 |
+
"required_fields": []
|
958 |
+
},
|
959 |
+
{
|
960 |
+
"slug": "sf-express",
|
961 |
+
"name": "S.F. Express",
|
962 |
+
"phone": "+852 273 00 273 / +86 4008-111-111",
|
963 |
+
"other_name": "順豊快遞",
|
964 |
+
"web_url": "http://www.sf-express.com",
|
965 |
+
"required_fields": []
|
966 |
+
},
|
967 |
+
{
|
968 |
+
"slug": "selektvracht",
|
969 |
+
"name": "Selektvracht",
|
970 |
+
"phone": "+31 0900-2222120",
|
971 |
+
"other_name": "Selektvracht NL",
|
972 |
+
"web_url": "http://www.selektvracht.nl/",
|
973 |
+
"required_fields": []
|
974 |
+
},
|
975 |
+
{
|
976 |
+
"slug": "ec-firstclass",
|
977 |
+
"name": "EC-Firstclass",
|
978 |
+
"phone": "+86 4006 988 223",
|
979 |
+
"other_name": "ChuKou1, CK1",
|
980 |
+
"web_url": "http://www.ec-firstclass.org/",
|
981 |
+
"required_fields": []
|
982 |
+
},
|
983 |
+
{
|
984 |
+
"slug": "an-post",
|
985 |
+
"name": "An Post",
|
986 |
+
"phone": "+353 1850 57 58 59",
|
987 |
+
"other_name": "Ireland Post",
|
988 |
+
"web_url": "http://www.anpost.ie/AnPost/",
|
989 |
+
"required_fields": []
|
990 |
+
},
|
991 |
+
{
|
992 |
+
"slug": "usps",
|
993 |
+
"name": "USPS",
|
994 |
+
"phone": "+1 800-275-8777",
|
995 |
+
"other_name": "United States Postal Service",
|
996 |
+
"web_url": "https://www.usps.com",
|
997 |
+
"required_fields": []
|
998 |
+
},
|
999 |
+
{
|
1000 |
+
"slug": "swiss-post",
|
1001 |
+
"name": "Swiss Post",
|
1002 |
+
"phone": "+41 848 888 888",
|
1003 |
+
"other_name": "La Poste Suisse, Die Schweizerische Post, Die Post",
|
1004 |
+
"web_url": "https://www.post.ch/",
|
1005 |
+
"required_fields": []
|
1006 |
+
},
|
1007 |
+
{
|
1008 |
+
"slug": "india-post",
|
1009 |
+
"name": "India Post Domestic",
|
1010 |
+
"phone": "+91 1800 11 2011",
|
1011 |
+
"other_name": "भारतीय डाक",
|
1012 |
+
"web_url": "http://www.indiapost.gov.in/",
|
1013 |
+
"required_fields": []
|
1014 |
+
},
|
1015 |
+
{
|
1016 |
+
"slug": "correos-de-mexico",
|
1017 |
+
"name": "Correos de Mexico",
|
1018 |
+
"phone": "+52 01 800 701 7000",
|
1019 |
+
"other_name": "Mexico Post",
|
1020 |
+
"web_url": "http://www.sepomex.gob.mx/Paginas/Home.aspx",
|
1021 |
+
"required_fields": []
|
1022 |
+
},
|
1023 |
+
{
|
1024 |
+
"slug": "correos-chile",
|
1025 |
+
"name": "Correos Chile",
|
1026 |
+
"phone": "+562 600 950 2020",
|
1027 |
+
"other_name": "Chile Post",
|
1028 |
+
"web_url": "http://www.correos.cl",
|
1029 |
+
"required_fields": []
|
1030 |
+
},
|
1031 |
+
{
|
1032 |
+
"slug": "asm",
|
1033 |
+
"name": "ASM",
|
1034 |
+
"phone": "+34 902 11 33 00",
|
1035 |
+
"other_name": "Asm-Red",
|
1036 |
+
"web_url": "http://www.asmred.com/en/",
|
1037 |
+
"required_fields": [
|
1038 |
+
"tracking_postal_code"
|
1039 |
+
]
|
1040 |
+
},
|
1041 |
+
{
|
1042 |
+
"slug": "aupost-china",
|
1043 |
+
"name": "AuPost China",
|
1044 |
+
"phone": "+86 4007005618",
|
1045 |
+
"other_name": "澳邮宝",
|
1046 |
+
"web_url": "http://www.aupost.org/",
|
1047 |
+
"required_fields": []
|
1048 |
+
},
|
1049 |
+
{
|
1050 |
+
"slug": "danmark-post",
|
1051 |
+
"name": "Post Danmark",
|
1052 |
+
"phone": "+45 80 20 70 30",
|
1053 |
+
"other_name": "Danske Post",
|
1054 |
+
"web_url": "http://www.postdanmark.dk/",
|
1055 |
+
"required_fields": []
|
1056 |
+
},
|
1057 |
+
{
|
1058 |
+
"slug": "gls-netherlands",
|
1059 |
+
"name": "GLS Netherlands",
|
1060 |
+
"phone": "+31 0900-1116660",
|
1061 |
+
"other_name": "GLS NL",
|
1062 |
+
"web_url": "http://www.gls-netherlands.com/",
|
1063 |
+
"required_fields": [
|
1064 |
+
"tracking_postal_code"
|
1065 |
+
]
|
1066 |
+
},
|
1067 |
+
{
|
1068 |
+
"slug": "dpd-uk",
|
1069 |
+
"name": "DPD UK",
|
1070 |
+
"phone": "+44 845 9 300 350",
|
1071 |
+
"other_name": "Dynamic Parcel Distribution UK",
|
1072 |
+
"web_url": "http://www.dpd.co.uk/",
|
1073 |
+
"required_fields": []
|
1074 |
+
},
|
1075 |
+
{
|
1076 |
+
"slug": "mrw-spain",
|
1077 |
+
"name": "MRW",
|
1078 |
+
"phone": "+34 902 300 403",
|
1079 |
+
"other_name": "MRW Spain",
|
1080 |
+
"web_url": "http://www.mrw.es/",
|
1081 |
+
"required_fields": []
|
1082 |
+
},
|
1083 |
+
{
|
1084 |
+
"slug": "correo-argentino",
|
1085 |
+
"name": "Correo Argentino",
|
1086 |
+
"phone": "+54 11 4891-9191",
|
1087 |
+
"other_name": "Argentina Post",
|
1088 |
+
"web_url": "http://www.correoargentino.com.ar",
|
1089 |
+
"required_fields": []
|
1090 |
+
},
|
1091 |
+
{
|
1092 |
+
"slug": "hrvatska-posta",
|
1093 |
+
"name": "Hrvatska Pošta",
|
1094 |
+
"phone": "+385 0800 303 304",
|
1095 |
+
"other_name": "Croatia Post",
|
1096 |
+
"web_url": "http://www.posta.hr/",
|
1097 |
+
"required_fields": []
|
1098 |
+
},
|
1099 |
+
{
|
1100 |
+
"slug": "posta-romana",
|
1101 |
+
"name": "Poșta Română",
|
1102 |
+
"phone": "+40 021 9393 111",
|
1103 |
+
"other_name": "Romania Post",
|
1104 |
+
"web_url": "http://www.posta-romana.ro/",
|
1105 |
+
"required_fields": []
|
1106 |
+
},
|
1107 |
+
{
|
1108 |
+
"slug": "courierpost",
|
1109 |
+
"name": "CourierPost",
|
1110 |
+
"phone": "+64 0800 268 743",
|
1111 |
+
"other_name": "Express Couriers",
|
1112 |
+
"web_url": "http://www.courierpost.co.nz/",
|
1113 |
+
"required_fields": []
|
1114 |
+
},
|
1115 |
+
{
|
1116 |
+
"slug": "gdex",
|
1117 |
+
"name": "GDEX",
|
1118 |
+
"phone": "+60 03-77872222",
|
1119 |
+
"other_name": "GD Express",
|
1120 |
+
"web_url": "http://www.gdexpress.com",
|
1121 |
+
"required_fields": []
|
1122 |
+
},
|
1123 |
+
{
|
1124 |
+
"slug": "singapore-post",
|
1125 |
+
"name": "Singapore Post",
|
1126 |
+
"phone": "+65 6841 2000",
|
1127 |
+
"other_name": "SingPost",
|
1128 |
+
"web_url": "http://www.singpost.com",
|
1129 |
+
"required_fields": []
|
1130 |
+
},
|
1131 |
+
{
|
1132 |
+
"slug": "arrowxl",
|
1133 |
+
"name": "Arrow XL",
|
1134 |
+
"phone": "+44 0800 015 1509",
|
1135 |
+
"other_name": "Yodel XL",
|
1136 |
+
"web_url": "http://www.arrowxl.co.uk/",
|
1137 |
+
"required_fields": [
|
1138 |
+
"tracking_postal_code"
|
1139 |
+
]
|
1140 |
+
},
|
1141 |
+
{
|
1142 |
+
"slug": "tnt-fr",
|
1143 |
+
"name": "TNT France",
|
1144 |
+
"phone": "+33 4 72 80 77 77",
|
1145 |
+
"other_name": "TNT Express FR",
|
1146 |
+
"web_url": "http://www.tnt.fr/",
|
1147 |
+
"required_fields": []
|
1148 |
+
},
|
1149 |
+
{
|
1150 |
+
"slug": "fastway-au",
|
1151 |
+
"name": "Fastway Australia",
|
1152 |
+
"phone": "+61 (0) 2 9737 8288",
|
1153 |
+
"other_name": "Fastway Couriers",
|
1154 |
+
"web_url": "http://www.fastway.com.au/",
|
1155 |
+
"required_fields": []
|
1156 |
+
},
|
1157 |
+
{
|
1158 |
+
"slug": "new-zealand-post",
|
1159 |
+
"name": "New Zealand Post",
|
1160 |
+
"phone": "+64 9 367 9710",
|
1161 |
+
"other_name": "NZ Post",
|
1162 |
+
"web_url": "http://www.nzpost.co.nz/",
|
1163 |
+
"required_fields": []
|
1164 |
+
},
|
1165 |
+
{
|
1166 |
+
"slug": "poste-italiane-paccocelere",
|
1167 |
+
"name": "Poste Italiane Paccocelere",
|
1168 |
+
"phone": "+39 803 160",
|
1169 |
+
"other_name": "Italian Post EMS / Express",
|
1170 |
+
"web_url": "http://www.poste.it/",
|
1171 |
+
"required_fields": []
|
1172 |
+
},
|
1173 |
+
{
|
1174 |
+
"slug": "poste-italiane",
|
1175 |
+
"name": "Poste Italiane",
|
1176 |
+
"phone": "+39 803 160",
|
1177 |
+
"other_name": "Italian Post",
|
1178 |
+
"web_url": "http://www.poste.it/",
|
1179 |
+
"required_fields": []
|
1180 |
+
},
|
1181 |
+
{
|
1182 |
+
"slug": "hermes-de",
|
1183 |
+
"name": "Hermes Germany",
|
1184 |
+
"phone": "+49 1806-311211",
|
1185 |
+
"other_name": "myhermes.de, Hermes Logistik Gruppe Deutschland",
|
1186 |
+
"web_url": "https://www.myhermes.de/wps/portal/paket/Home/privatkunden/home",
|
1187 |
+
"required_fields": []
|
1188 |
+
},
|
1189 |
+
{
|
1190 |
+
"slug": "wahana",
|
1191 |
+
"name": "Wahana",
|
1192 |
+
"phone": "+62 2171355152",
|
1193 |
+
"other_name": "Wahana Indonesia",
|
1194 |
+
"web_url": "http://www.wahana.com/",
|
1195 |
+
"required_fields": []
|
1196 |
+
},
|
1197 |
+
{
|
1198 |
+
"slug": "collectplus",
|
1199 |
+
"name": "Collect+",
|
1200 |
+
"phone": "+44 01923 601616",
|
1201 |
+
"other_name": "Collect Plus UK",
|
1202 |
+
"web_url": "https://www.collectplus.co.uk/",
|
1203 |
+
"required_fields": []
|
1204 |
+
},
|
1205 |
+
{
|
1206 |
+
"slug": "dynamic-logistics",
|
1207 |
+
"name": "Dynamic Logistics",
|
1208 |
+
"phone": "+66 02-688-6688",
|
1209 |
+
"other_name": "Dynamic Logistics Thailand",
|
1210 |
+
"web_url": "http://www.dynamic-logistics.com/",
|
1211 |
+
"required_fields": [
|
1212 |
+
"tracking_account_number"
|
1213 |
+
]
|
1214 |
+
},
|
1215 |
+
{
|
1216 |
+
"slug": "dx",
|
1217 |
+
"name": "DX",
|
1218 |
+
"phone": "+44 0844 826 1178",
|
1219 |
+
"other_name": "DX Freight",
|
1220 |
+
"web_url": "https://www.thedx.co.uk/",
|
1221 |
+
"required_fields": [
|
1222 |
+
"tracking_postal_code"
|
1223 |
+
]
|
1224 |
+
},
|
1225 |
+
{
|
1226 |
+
"slug": "taqbin-my",
|
1227 |
+
"name": "TAQBIN Malaysia",
|
1228 |
+
"phone": "+60 1800-8-827246",
|
1229 |
+
"other_name": "TAQBIN Malaysia",
|
1230 |
+
"web_url": "http://my.ta-q-bin.com/",
|
1231 |
+
"required_fields": []
|
1232 |
+
},
|
1233 |
+
{
|
1234 |
+
"slug": "dhl",
|
1235 |
+
"name": "DHL Express",
|
1236 |
+
"phone": "+1 800 225 5345",
|
1237 |
+
"other_name": "DHL International",
|
1238 |
+
"web_url": "http://www.dhl.com/",
|
1239 |
+
"required_fields": []
|
1240 |
+
},
|
1241 |
+
{
|
1242 |
+
"slug": "citylinkexpress",
|
1243 |
+
"name": "City-Link Express",
|
1244 |
+
"phone": "+60 603-5565 8399",
|
1245 |
+
"other_name": "Citylink Malaysia",
|
1246 |
+
"web_url": "http://www.citylinkexpress.com/",
|
1247 |
+
"required_fields": []
|
1248 |
+
},
|
1249 |
+
{
|
1250 |
+
"slug": "wedo",
|
1251 |
+
"name": "WeDo Logistics",
|
1252 |
+
"phone": "+86 (0779)2050300",
|
1253 |
+
"other_name": "運德物流",
|
1254 |
+
"web_url": "http://www.wedoexpress.com/",
|
1255 |
+
"required_fields": []
|
1256 |
+
},
|
1257 |
+
{
|
1258 |
+
"slug": "tntpost-it",
|
1259 |
+
"name": "Nexive (TNT Post Italy)",
|
1260 |
+
"phone": "+39 02 50720011",
|
1261 |
+
"other_name": "Postnl TNT",
|
1262 |
+
"web_url": "http://www.tntpost.it/",
|
1263 |
+
"required_fields": []
|
1264 |
+
},
|
1265 |
+
{
|
1266 |
+
"slug": "malaysia-post-posdaftar",
|
1267 |
+
"name": "Malaysia Post - Registered",
|
1268 |
+
"phone": "+603 27279100",
|
1269 |
+
"other_name": "PosDaftar",
|
1270 |
+
"web_url": "http://www.pos.com.my",
|
1271 |
+
"required_fields": []
|
1272 |
+
},
|
1273 |
+
{
|
1274 |
+
"slug": "pos-indonesia",
|
1275 |
+
"name": "Pos Indonesia Domestic",
|
1276 |
+
"phone": "+62 21 161",
|
1277 |
+
"other_name": "Indonesian Post Domestic",
|
1278 |
+
"web_url": "http://www.posindonesia.co.id",
|
1279 |
+
"required_fields": []
|
1280 |
+
},
|
1281 |
+
{
|
1282 |
+
"slug": "pos-indonesia-int",
|
1283 |
+
"name": "Pos Indonesia Int'l",
|
1284 |
+
"phone": "+62 21 161",
|
1285 |
+
"other_name": "Indonesian Post International EMS",
|
1286 |
+
"web_url": "http://www.posindonesia.co.id",
|
1287 |
+
"required_fields": []
|
1288 |
+
},
|
1289 |
+
{
|
1290 |
+
"slug": "xdp-uk",
|
1291 |
+
"name": "XDP Express",
|
1292 |
+
"phone": "+44 0843 1782222",
|
1293 |
+
"other_name": "XDP UK",
|
1294 |
+
"web_url": "http://www.xdp.co.uk/",
|
1295 |
+
"required_fields": [
|
1296 |
+
"tracking_postal_code"
|
1297 |
+
]
|
1298 |
+
},
|
1299 |
+
{
|
1300 |
+
"slug": "portugal-ctt",
|
1301 |
+
"name": "Portugal CTT",
|
1302 |
+
"phone": "+351 707 26 26 26",
|
1303 |
+
"other_name": "Correios de Portugal",
|
1304 |
+
"web_url": "http://www.ctt.pt/",
|
1305 |
+
"required_fields": []
|
1306 |
+
},
|
1307 |
+
{
|
1308 |
+
"slug": "hermes",
|
1309 |
+
"name": "myHermes UK",
|
1310 |
+
"phone": "+44 844 543 7000",
|
1311 |
+
"other_name": "Hermes UK",
|
1312 |
+
"web_url": "https://www.myhermes.co.uk",
|
1313 |
+
"required_fields": []
|
1314 |
+
},
|
1315 |
+
{
|
1316 |
+
"slug": "colis-prive",
|
1317 |
+
"name": "Colis Privé",
|
1318 |
+
"phone": "+33 0826 82 83 84",
|
1319 |
+
"other_name": "ColisPrivé",
|
1320 |
+
"web_url": "https://www.colisprive.com/moncolis/",
|
1321 |
+
"required_fields": []
|
1322 |
+
},
|
1323 |
+
{
|
1324 |
+
"slug": "la-poste-colissimo",
|
1325 |
+
"name": "La Poste",
|
1326 |
+
"phone": "+33 3631",
|
1327 |
+
"other_name": "Coliposte",
|
1328 |
+
"web_url": "http://www.csuivi.courrier.laposte.fr",
|
1329 |
+
"required_fields": []
|
1330 |
+
},
|
1331 |
+
{
|
1332 |
+
"slug": "fastway-ireland",
|
1333 |
+
"name": "Fastway Ireland",
|
1334 |
+
"phone": "+353 1 4242 900",
|
1335 |
+
"other_name": "Fastway Couriers",
|
1336 |
+
"web_url": "http://www.fastway.ie/",
|
1337 |
+
"required_fields": []
|
1338 |
+
},
|
1339 |
+
{
|
1340 |
+
"slug": "malaysia-post",
|
1341 |
+
"name": "Malaysia Post EMS / Poslaju",
|
1342 |
+
"phone": "+603 27279100",
|
1343 |
+
"other_name": "Pos Ekspres, Pos Malaysia Express",
|
1344 |
+
"web_url": "http://www.pos.com.my",
|
1345 |
+
"required_fields": []
|
1346 |
+
},
|
1347 |
+
{
|
1348 |
+
"slug": "sto",
|
1349 |
+
"name": "STO Express",
|
1350 |
+
"phone": "+86 95543",
|
1351 |
+
"other_name": "申通快递, Shentong Express",
|
1352 |
+
"web_url": "http://www.sto.cn/",
|
1353 |
+
"required_fields": []
|
1354 |
+
},
|
1355 |
+
{
|
1356 |
+
"slug": "ups",
|
1357 |
+
"name": "UPS",
|
1358 |
+
"phone": "+1 800 742 5877",
|
1359 |
+
"other_name": "United Parcel Service",
|
1360 |
+
"web_url": "http://www.ups.com",
|
1361 |
+
"required_fields": []
|
1362 |
+
},
|
1363 |
+
{
|
1364 |
+
"slug": "postnl",
|
1365 |
+
"name": "PostNL Domestic",
|
1366 |
+
"phone": "+31 (0)900 0990",
|
1367 |
+
"other_name": "PostNL Pakketten, TNT Post Netherlands",
|
1368 |
+
"web_url": "http://www.postnl.nl/voorthuis/",
|
1369 |
+
"required_fields": [
|
1370 |
+
"tracking_postal_code"
|
1371 |
+
]
|
1372 |
+
},
|
1373 |
+
{
|
1374 |
+
"slug": "deutsch-post",
|
1375 |
+
"name": "Deutsche Post Mail",
|
1376 |
+
"phone": "+49 (0) 180 2 000221",
|
1377 |
+
"other_name": "dpdhl",
|
1378 |
+
"web_url": "http://www.deutschepost.de/",
|
1379 |
+
"required_fields": [
|
1380 |
+
"tracking_ship_date"
|
1381 |
+
]
|
1382 |
+
},
|
1383 |
+
{
|
1384 |
+
"slug": "elta-courier",
|
1385 |
+
"name": "ELTA Hellenic Post",
|
1386 |
+
"phone": "+30 801 11 83000",
|
1387 |
+
"other_name": "Greece Post, Ελληνικά Ταχυδρομεία, ELTA Courier, Ταχυμεταφορές ΕΛΤΑ",
|
1388 |
+
"web_url": "http://www.elta-courier.gr/",
|
1389 |
+
"required_fields": []
|
1390 |
+
},
|
1391 |
+
{
|
1392 |
+
"slug": "postnl-international",
|
1393 |
+
"name": "PostNL International",
|
1394 |
+
"phone": "+31 (0)900 0990",
|
1395 |
+
"other_name": "Netherlands Post, Spring Global Mail",
|
1396 |
+
"web_url": "http://www.postnl.nl/voorthuis/",
|
1397 |
+
"required_fields": []
|
1398 |
+
},
|
1399 |
+
{
|
1400 |
+
"slug": "toll-ipec",
|
1401 |
+
"name": "Toll IPEC",
|
1402 |
+
"phone": "+61 13 15 31",
|
1403 |
+
"other_name": "Toll Express",
|
1404 |
+
"web_url": "http://www.tollgroup.com/tollipec",
|
1405 |
+
"required_fields": []
|
1406 |
+
},
|
1407 |
+
{
|
1408 |
+
"slug": "jcex",
|
1409 |
+
"name": "JCEX",
|
1410 |
+
"phone": "+86 571-86436777",
|
1411 |
+
"other_name": "JiaCheng, 杭州佳成",
|
1412 |
+
"web_url": "http://www.jcex.com",
|
1413 |
+
"required_fields": []
|
1414 |
+
},
|
1415 |
+
{
|
1416 |
+
"slug": "israel-post-domestic",
|
1417 |
+
"name": "Israel Post Domestic",
|
1418 |
+
"phone": "+972 2 629 0691",
|
1419 |
+
"other_name": "חברת דואר ישראל מקומית",
|
1420 |
+
"web_url": "http://www.israelpost.co.il/",
|
1421 |
+
"required_fields": []
|
1422 |
+
},
|
1423 |
+
{
|
1424 |
+
"slug": "skynetworldwide",
|
1425 |
+
"name": "SkyNet Worldwide Express",
|
1426 |
+
"phone": "+44 (0) 20 8538 1988",
|
1427 |
+
"other_name": "Skynetwwe",
|
1428 |
+
"web_url": "http://www.skynetwwe.com/",
|
1429 |
+
"required_fields": []
|
1430 |
+
},
|
1431 |
+
{
|
1432 |
+
"slug": "tnt",
|
1433 |
+
"name": "TNT",
|
1434 |
+
"phone": "+1 800 558 5555",
|
1435 |
+
"other_name": "TNT Express",
|
1436 |
+
"web_url": "http://www.tnt.com/",
|
1437 |
+
"required_fields": []
|
1438 |
+
},
|
1439 |
+
{
|
1440 |
+
"slug": "royal-mail",
|
1441 |
+
"name": "Royal Mail",
|
1442 |
+
"phone": "+44 1752387112",
|
1443 |
+
"other_name": "Royal Mail United Kingdom",
|
1444 |
+
"web_url": "http://www.royalmail.com/",
|
1445 |
+
"required_fields": []
|
1446 |
+
},
|
1447 |
+
{
|
1448 |
+
"slug": "parcel-force",
|
1449 |
+
"name": "Parcel Force",
|
1450 |
+
"phone": "+44 844 800 44 66",
|
1451 |
+
"other_name": "Parcelforce UK",
|
1452 |
+
"web_url": "http://www.parcelforce.com",
|
1453 |
+
"required_fields": []
|
1454 |
+
},
|
1455 |
+
{
|
1456 |
+
"slug": "abf",
|
1457 |
+
"name": "ABF Freight",
|
1458 |
+
"phone": "+1 (800) 610-5544",
|
1459 |
+
"other_name": "Arkansas Best Corporation",
|
1460 |
+
"web_url": "http://www.abfs.com/",
|
1461 |
+
"required_fields": []
|
1462 |
+
},
|
1463 |
+
{
|
1464 |
+
"slug": "directlink",
|
1465 |
+
"name": "Direct Link",
|
1466 |
+
"phone": "+852 28504183",
|
1467 |
+
"other_name": "Direct Link",
|
1468 |
+
"web_url": "http://www.directlink.com/",
|
1469 |
+
"required_fields": []
|
1470 |
+
},
|
1471 |
+
{
|
1472 |
+
"slug": "dhlparcel-nl",
|
1473 |
+
"name": "DHL Parcel NL",
|
1474 |
+
"phone": "+31 0900 - 222 21 20",
|
1475 |
+
"other_name": "Selektvracht, dhlparcel.nl",
|
1476 |
+
"web_url": "https://www.dhlparcel.nl/",
|
1477 |
+
"required_fields": []
|
1478 |
+
},
|
1479 |
+
{
|
1480 |
+
"slug": "greyhound",
|
1481 |
+
"name": "Greyhound",
|
1482 |
+
"phone": "+1 800-739-5020",
|
1483 |
+
"other_name": "Greyhound Package Express",
|
1484 |
+
"web_url": "http://www.shipgreyhound.com/",
|
1485 |
+
"required_fields": []
|
1486 |
+
},
|
1487 |
+
{
|
1488 |
+
"slug": "dhl-germany",
|
1489 |
+
"name": "Deutsche Post DHL",
|
1490 |
+
"phone": "+49 228 28609898",
|
1491 |
+
"other_name": "DHL Germany",
|
1492 |
+
"web_url": "http://www.dhl.de/",
|
1493 |
+
"required_fields": []
|
1494 |
+
},
|
1495 |
+
{
|
1496 |
+
"slug": "gls",
|
1497 |
+
"name": "GLS",
|
1498 |
+
"phone": "+44 247 621 3455",
|
1499 |
+
"other_name": "General Logistics Systems",
|
1500 |
+
"web_url": "https://gls-group.eu/EU/en/home",
|
1501 |
+
"required_fields": []
|
1502 |
+
},
|
1503 |
+
{
|
1504 |
+
"slug": "i-parcel",
|
1505 |
+
"name": "i-parcel",
|
1506 |
+
"phone": "+44 (0) 1342 315 455",
|
1507 |
+
"other_name": "iparcel",
|
1508 |
+
"web_url": "https://www.i-parcel.com/",
|
1509 |
+
"required_fields": []
|
1510 |
+
},
|
1511 |
+
{
|
1512 |
+
"slug": "colissimo",
|
1513 |
+
"name": "Colissimo",
|
1514 |
+
"phone": "+33 3631",
|
1515 |
+
"other_name": "Colissimo fr",
|
1516 |
+
"web_url": "http://www.colissimo.fr",
|
1517 |
+
"required_fields": []
|
1518 |
+
},
|
1519 |
+
{
|
1520 |
+
"slug": "yanwen",
|
1521 |
+
"name": "Yanwen",
|
1522 |
+
"phone": "+86 10-64621881/64669779",
|
1523 |
+
"other_name": "燕文物流",
|
1524 |
+
"web_url": "http://www.yw56.com.cn/",
|
1525 |
+
"required_fields": []
|
1526 |
+
},
|
1527 |
+
{
|
1528 |
+
"slug": "poczta-polska",
|
1529 |
+
"name": "Poczta Polska",
|
1530 |
+
"phone": "+48 43-842-06-00",
|
1531 |
+
"other_name": "Poland Post",
|
1532 |
+
"web_url": "http://www.poczta-polska.pl/",
|
1533 |
+
"required_fields": []
|
1534 |
+
},
|
1535 |
+
{
|
1536 |
+
"slug": "bpost-international",
|
1537 |
+
"name": "bpost international",
|
1538 |
+
"phone": "+32 (0)2 278 50 90",
|
1539 |
+
"other_name": "Belgium Post International, Minipak DDU",
|
1540 |
+
"web_url": "http://www.bpostinternational.com/",
|
1541 |
+
"required_fields": []
|
1542 |
+
},
|
1543 |
+
{
|
1544 |
+
"slug": "first-flight",
|
1545 |
+
"name": "First Flight Couriers",
|
1546 |
+
"phone": "+91 022-39576666",
|
1547 |
+
"other_name": "FirstFlight India",
|
1548 |
+
"web_url": "http://www.firstflight.net/",
|
1549 |
+
"required_fields": []
|
1550 |
+
},
|
1551 |
+
{
|
1552 |
+
"slug": "australia-post",
|
1553 |
+
"name": "Australia Post",
|
1554 |
+
"phone": "+61 3 8847 9980",
|
1555 |
+
"other_name": "AusPost",
|
1556 |
+
"web_url": "http://auspost.com.au/",
|
1557 |
+
"required_fields": []
|
1558 |
+
},
|
1559 |
+
{
|
1560 |
+
"slug": "ups-mi",
|
1561 |
+
"name": "UPS Mail Innovations",
|
1562 |
+
"phone": "+1 800-500-2224",
|
1563 |
+
"other_name": "UPS MI",
|
1564 |
+
"web_url": "http://www.upsmailinnovations.com/",
|
1565 |
+
"required_fields": []
|
1566 |
+
},
|
1567 |
+
{
|
1568 |
+
"slug": "dhl-benelux",
|
1569 |
+
"name": "DHL Benelux",
|
1570 |
+
"phone": "+31 26-324 6700",
|
1571 |
+
"other_name": "DHL Benelux",
|
1572 |
+
"web_url": "http://www.dhl.nl/",
|
1573 |
+
"required_fields": []
|
1574 |
+
},
|
1575 |
+
{
|
1576 |
+
"slug": "taxydromiki",
|
1577 |
+
"name": "Geniki Taxydromiki",
|
1578 |
+
"phone": "+30 210 485110",
|
1579 |
+
"other_name": "ΓΕΝΙΚΗ ΤΑΧΥΔΡΟΜΙΚΗ",
|
1580 |
+
"web_url": "http://www.taxydromiki.gr/",
|
1581 |
+
"required_fields": []
|
1582 |
+
},
|
1583 |
+
{
|
1584 |
+
"slug": "skynetworldwide-uk",
|
1585 |
+
"name": "Skynet Worldwide Express UK",
|
1586 |
+
"phone": "+44 (0) 20 8538 1988",
|
1587 |
+
"other_name": "Skynet UK",
|
1588 |
+
"web_url": "https://www.skynetworldwide.com",
|
1589 |
+
"required_fields": []
|
1590 |
+
},
|
1591 |
+
{
|
1592 |
+
"slug": "gls-italy",
|
1593 |
+
"name": "GLS Italy",
|
1594 |
+
"phone": "+39 199 151188",
|
1595 |
+
"other_name": "GLS Corriere Espresso",
|
1596 |
+
"web_url": "http://www.gls-italy.com/index_noreg.asp",
|
1597 |
+
"required_fields": []
|
1598 |
+
},
|
1599 |
+
{
|
1600 |
+
"slug": "envialia",
|
1601 |
+
"name": "Envialia",
|
1602 |
+
"phone": "+34 902400909",
|
1603 |
+
"other_name": "Envialia Spain",
|
1604 |
+
"web_url": "http://www.envialia.com/",
|
1605 |
+
"required_fields": []
|
1606 |
+
},
|
1607 |
+
{
|
1608 |
+
"slug": "yundaex",
|
1609 |
+
"name": "Yunda Express",
|
1610 |
+
"phone": "+86 400-821-6789",
|
1611 |
+
"other_name": "韵达快递",
|
1612 |
+
"web_url": "http://www.yundaex.com/",
|
1613 |
+
"required_fields": []
|
1614 |
+
},
|
1615 |
+
{
|
1616 |
+
"slug": "specialisedfreight-za",
|
1617 |
+
"name": "Specialised Freight",
|
1618 |
+
"phone": "+27 21 528 1000",
|
1619 |
+
"other_name": "SFS",
|
1620 |
+
"web_url": "http://www.specialisedfreight.co.za/",
|
1621 |
+
"required_fields": []
|
1622 |
+
},
|
1623 |
+
{
|
1624 |
+
"slug": "yodel",
|
1625 |
+
"name": "Yodel Domestic",
|
1626 |
+
"phone": "+44 0844 453 7443",
|
1627 |
+
"other_name": "Home Delivery Network Limited (HDNL)",
|
1628 |
+
"web_url": "http://www.yodel.co.uk/",
|
1629 |
+
"required_fields": []
|
1630 |
+
},
|
1631 |
+
{
|
1632 |
+
"slug": "city-link",
|
1633 |
+
"name": "City Link",
|
1634 |
+
"phone": "+44 8444 930 914",
|
1635 |
+
"other_name": "City Link UK",
|
1636 |
+
"web_url": "http://www.city-link.co.uk/",
|
1637 |
+
"required_fields": []
|
1638 |
+
},
|
1639 |
+
{
|
1640 |
+
"slug": "bpost",
|
1641 |
+
"name": "Belgium Post",
|
1642 |
+
"phone": "+32 2 276 22 74",
|
1643 |
+
"other_name": "bpost, Belgian Post",
|
1644 |
+
"web_url": "http://www.bpost.be/",
|
1645 |
+
"required_fields": []
|
1646 |
+
},
|
1647 |
+
{
|
1648 |
+
"slug": "dpd",
|
1649 |
+
"name": "DPD",
|
1650 |
+
"phone": "+31 20 480 2900",
|
1651 |
+
"other_name": "Dynamic Parcel Distribution",
|
1652 |
+
"web_url": "http://www.dpd.com/",
|
1653 |
+
"required_fields": []
|
1654 |
+
},
|
1655 |
+
{
|
1656 |
+
"slug": "thailand-post",
|
1657 |
+
"name": "Thailand Thai Post",
|
1658 |
+
"phone": "+66 (0) 2831 3131",
|
1659 |
+
"other_name": "ไปรษณีย์ไทย",
|
1660 |
+
"web_url": "http://www.thailandpost.co.th/home.php",
|
1661 |
+
"required_fields": []
|
1662 |
+
},
|
1663 |
+
{
|
1664 |
+
"slug": "redur-es",
|
1665 |
+
"name": "Redur Spain",
|
1666 |
+
"phone": "+34 93 263 16 16",
|
1667 |
+
"other_name": "Eurodis",
|
1668 |
+
"web_url": "http://www.redur.es/",
|
1669 |
+
"required_fields": []
|
1670 |
+
},
|
1671 |
+
{
|
1672 |
+
"slug": "bluedart",
|
1673 |
+
"name": "Bluedart",
|
1674 |
+
"phone": "+91 (0) 40-64564307",
|
1675 |
+
"other_name": "Blue Dart Express",
|
1676 |
+
"web_url": "http://www.bluedart.com/",
|
1677 |
+
"required_fields": []
|
1678 |
+
},
|
1679 |
+
{
|
1680 |
+
"slug": "dpe-za",
|
1681 |
+
"name": "DPE South Africa",
|
1682 |
+
"phone": "+27 (011) 573 3000",
|
1683 |
+
"other_name": "DPE Worldwide Express",
|
1684 |
+
"web_url": "http://www.dpe.co.za/",
|
1685 |
+
"required_fields": []
|
1686 |
+
},
|
1687 |
+
{
|
1688 |
+
"slug": "emirates-post",
|
1689 |
+
"name": "Emirates Post",
|
1690 |
+
"phone": "+971 600 599999",
|
1691 |
+
"other_name": "مجموعة بريد الإمارات, UAE Post",
|
1692 |
+
"web_url": "http://www.epg.gov.ae/",
|
1693 |
+
"required_fields": []
|
1694 |
+
},
|
1695 |
+
{
|
1696 |
+
"slug": "dhl-nl",
|
1697 |
+
"name": "DHL Netherlands",
|
1698 |
+
"phone": "+31 26-324 6700",
|
1699 |
+
"other_name": "DHL Nederlands",
|
1700 |
+
"web_url": "http://www.dhl.nl/",
|
1701 |
+
"required_fields": []
|
1702 |
+
},
|
1703 |
+
{
|
1704 |
+
"slug": "szdpex",
|
1705 |
+
"name": "DPEX China",
|
1706 |
+
"phone": "+86 755-8829 7707",
|
1707 |
+
"other_name": "DPEX(深圳)国际物流, Toll China",
|
1708 |
+
"web_url": "http://www.szdpex.com.cn/",
|
1709 |
+
"required_fields": []
|
1710 |
+
},
|
1711 |
+
{
|
1712 |
+
"slug": "qxpress",
|
1713 |
+
"name": "Qxpress",
|
1714 |
+
"phone": "+86 755-8829 7707",
|
1715 |
+
"other_name": "Qxpress Qoo10",
|
1716 |
+
"web_url": "http://www.qxpress.asia/",
|
1717 |
+
"required_fields": []
|
1718 |
+
},
|
1719 |
+
{
|
1720 |
+
"slug": "courier-plus",
|
1721 |
+
"name": "Courier Plus",
|
1722 |
+
"phone": "+234-18102031",
|
1723 |
+
"other_name": "Courier Plus",
|
1724 |
+
"web_url": "http://www.courierplus-ng.com/",
|
1725 |
+
"required_fields": []
|
1726 |
+
},
|
1727 |
+
{
|
1728 |
+
"slug": "taiwan-post",
|
1729 |
+
"name": "Taiwan Post",
|
1730 |
+
"phone": "+886 (02)2703-7527",
|
1731 |
+
"other_name": "Chunghwa Post, 台灣中華郵政",
|
1732 |
+
"web_url": "http://www.post.gov.tw/",
|
1733 |
+
"required_fields": []
|
1734 |
+
},
|
1735 |
+
{
|
1736 |
+
"slug": "sweden-posten",
|
1737 |
+
"name": "Sweden Posten",
|
1738 |
+
"phone": "+46 8 23 22 20",
|
1739 |
+
"other_name": "Sweden Post",
|
1740 |
+
"web_url": "http://www.posten.se/",
|
1741 |
+
"required_fields": []
|
1742 |
+
},
|
1743 |
+
{
|
1744 |
+
"slug": "dhl-global-mail",
|
1745 |
+
"name": "DHL Global Mail",
|
1746 |
+
"phone": "+1 800 225 5345",
|
1747 |
+
"other_name": "DHL GM",
|
1748 |
+
"web_url": "http://us.dhlglobalmail.com/",
|
1749 |
+
"required_fields": []
|
1750 |
+
},
|
1751 |
+
{
|
1752 |
+
"slug": "800bestex",
|
1753 |
+
"name": "Best Express",
|
1754 |
+
"phone": "+86 4009565656",
|
1755 |
+
"other_name": "百世汇通",
|
1756 |
+
"web_url": "http://www.800bestex.com/",
|
1757 |
+
"required_fields": []
|
1758 |
+
},
|
1759 |
+
{
|
1760 |
+
"slug": "dhl-deliverit",
|
1761 |
+
"name": "DHL 2-Mann-Handling",
|
1762 |
+
"phone": "+49 228 28609898",
|
1763 |
+
"other_name": "DHL Deliver IT",
|
1764 |
+
"web_url": "https://www.dhl-deliverit.com/web/guest/webavisierung",
|
1765 |
+
"required_fields": [
|
1766 |
+
"tracking_postal_code"
|
1767 |
+
]
|
1768 |
+
},
|
1769 |
+
{
|
1770 |
+
"slug": "dbschenker-se",
|
1771 |
+
"name": "DB Schenker Sweden",
|
1772 |
+
"phone": "+46 31 337 04 00",
|
1773 |
+
"other_name": "Deutsche Bahn",
|
1774 |
+
"web_url": "http://www.logistics.dbschenker.se/",
|
1775 |
+
"required_fields": []
|
1776 |
+
}
|
1777 |
+
];
|
1778 |
+
return data;
|
1779 |
+
}
|
trunk/assets/js/setting.js
ADDED
@@ -0,0 +1,46 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
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 |
+
}
|
21 |
+
|
22 |
+
jQuery('#couriers_select').change(function() {
|
23 |
+
var couriers_select = jQuery('#couriers_select').val();
|
24 |
+
var value = (couriers_select) ? couriers_select.join(',') : '';
|
25 |
+
jQuery('#couriers').val(value);
|
26 |
+
});
|
27 |
+
|
28 |
+
jQuery('#plugin').change(function() {
|
29 |
+
if (jQuery(this).val() == 'aftership') {
|
30 |
+
jQuery('#couriers').parent().parent().show();
|
31 |
+
} else {
|
32 |
+
jQuery('#couriers').parent().parent().hide();
|
33 |
+
}
|
34 |
+
})
|
35 |
+
|
36 |
+
|
37 |
+
if (jQuery('#couriers')) {
|
38 |
+
var couriers_select = jQuery('#couriers').val();
|
39 |
+
var couriers_select_array = (couriers_select) ? couriers_select.split(',') : [];
|
40 |
+
set_aftership_tracking_provider(couriers_select_array);
|
41 |
+
|
42 |
+
if (jQuery('#plugin').val() != 'aftership') {
|
43 |
+
jQuery('#couriers').parent().parent().hide();
|
44 |
+
}
|
45 |
+
}
|
46 |
+
});
|
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,186 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
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 |
+
|
148 |
+
// API server / response handlers
|
149 |
+
include_once('api/class-aftership-api-server.php');
|
150 |
+
include_once('api/interface-aftership-api-handler.php');
|
151 |
+
include_once('api/class-aftership-api-json-handler.php');
|
152 |
+
|
153 |
+
// authentication
|
154 |
+
include_once('api/class-aftership-api-authentication.php');
|
155 |
+
$this->authentication = new AfterShip_API_Authentication();
|
156 |
+
|
157 |
+
include_once('api/class-aftership-api-resource.php');
|
158 |
+
|
159 |
+
// self api
|
160 |
+
include_once('api/class-aftership-api-orders.php');
|
161 |
+
|
162 |
+
// allow plugins to load other response handlers or resource classes
|
163 |
+
do_action('woocommerce_api_loaded');
|
164 |
+
}
|
165 |
+
|
166 |
+
/**
|
167 |
+
* Register available API resources
|
168 |
+
*
|
169 |
+
* @since 2.1
|
170 |
+
* @param object $server the REST server
|
171 |
+
*/
|
172 |
+
public function register_resources($server)
|
173 |
+
{
|
174 |
+
|
175 |
+
$api_classes = apply_filters('aftership_api_classes',
|
176 |
+
array(
|
177 |
+
'AfterShip_API_Orders',
|
178 |
+
)
|
179 |
+
);
|
180 |
+
|
181 |
+
foreach ($api_classes as $api_class) {
|
182 |
+
$this->$api_class = new $api_class($server);
|
183 |
+
}
|
184 |
+
}
|
185 |
+
|
186 |
+
}
|
trunk/class-aftership-settings.php
ADDED
@@ -0,0 +1,231 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
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( 'WC_Dependencies' ) )
|
19 |
+
require_once 'woo-includes/class-wc-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' => 'woocommerce-shipment-tracking/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 |
+
|
150 |
+
/**
|
151 |
+
* Sanitize each setting field as needed
|
152 |
+
*
|
153 |
+
* @param array $input Contains all settings fields as array keys
|
154 |
+
*/
|
155 |
+
public function sanitize($input)
|
156 |
+
{
|
157 |
+
$new_input = array();
|
158 |
+
|
159 |
+
if (isset($input['couriers'])) {
|
160 |
+
$new_input['couriers'] = sanitize_text_field($input['couriers']);
|
161 |
+
}
|
162 |
+
|
163 |
+
if (isset($input['plugin'])) {
|
164 |
+
$new_input['plugin'] = sanitize_text_field($input['plugin']);
|
165 |
+
}
|
166 |
+
|
167 |
+
if (isset($input['use_track_button'])) {
|
168 |
+
$new_input['use_track_button'] = true;
|
169 |
+
}
|
170 |
+
|
171 |
+
return $new_input;
|
172 |
+
}
|
173 |
+
|
174 |
+
/**
|
175 |
+
* Print the Section text
|
176 |
+
*/
|
177 |
+
public function print_section_info()
|
178 |
+
{
|
179 |
+
//print 'Enter your settings below:';
|
180 |
+
}
|
181 |
+
|
182 |
+
public function couriers_callback(){
|
183 |
+
|
184 |
+
$couriers = array();
|
185 |
+
if (isset($this->options['couriers'])){
|
186 |
+
$couriers = explode(',', $this->options['couriers']);
|
187 |
+
}
|
188 |
+
|
189 |
+
// print_r($couriers);
|
190 |
+
echo '<select data-placeholder="Please select couriers" id="couriers_select" class="chosen-select " multiple style="width:100%">';
|
191 |
+
echo '</select>';
|
192 |
+
// echo '<br><a href="https://www.aftership.com/settings/courier" target="_blank">Update carrier list</a>';
|
193 |
+
echo '<input type="hidden" id="couriers" name="aftership_option_name[couriers]" value="' . implode(",", $couriers) . '"/>';
|
194 |
+
|
195 |
+
}
|
196 |
+
|
197 |
+
public function plugin_callback()
|
198 |
+
{
|
199 |
+
|
200 |
+
$options = "";
|
201 |
+
foreach ($this->plugins as $plugin) {
|
202 |
+
//print_r($plugin);
|
203 |
+
if (WC_Dependencies::plugin_active_check($plugin['path'])) {
|
204 |
+
$option = '<option value="' . $plugin['value'] . '"';
|
205 |
+
|
206 |
+
if (isset($this->options['plugin']) && esc_attr($this->options['plugin']) == $plugin['value']) {
|
207 |
+
$option .= ' selected="selected"';
|
208 |
+
}
|
209 |
+
|
210 |
+
$option .= '>' . $plugin['label'] . '</option>';
|
211 |
+
$options .= $option;
|
212 |
+
}
|
213 |
+
}
|
214 |
+
|
215 |
+
printf(
|
216 |
+
'<select id="plugin" name="aftership_option_name[plugin]" class="aftership_dropdown">' . $options . '</select>'
|
217 |
+
);
|
218 |
+
}
|
219 |
+
|
220 |
+
public function track_button_callback()
|
221 |
+
{
|
222 |
+
printf(
|
223 |
+
'<label><input type="checkbox" id="use_track_button" name="aftership_option_name[use_track_button]" %s>Use Track Button</label>',
|
224 |
+
(isset($this->options['use_track_button']) && $this->options['use_track_button'] === true) ? 'checked="checked"' : ''
|
225 |
+
);
|
226 |
+
}
|
227 |
+
}
|
228 |
+
|
229 |
+
|
230 |
+
if (is_admin())
|
231 |
+
$aftership_settings = new AfterShip_Settings();
|
trunk/readme.txt
ADDED
@@ -0,0 +1,181 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
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.0
|
7 |
+
Stable tag: 1.2.6
|
8 |
+
License: GPLv2 or later
|
9 |
+
License URI: http://www.gnu.org/licenses/gpl-2.0.html
|
10 |
+
|
11 |
+
Add tracking number and carrier name to WooCommerce, display tracking info at order history page, auto import tracking numbers to AfterShip.
|
12 |
+
|
13 |
+
== Description ==
|
14 |
+
|
15 |
+
###Add tracking number and carrier name fields (Free)
|
16 |
+
By installing AfterShip plugin, you can automatically add Tracking Number and Carrier fields to your admin panel. After you fulfill an order, simply enter the tracking number and select a carrier at WooCommerce, the same info will be displayed at customer's order history page. AfterShip supports over 200 carriers worldwide, you can select carriers by [signing up a free AfterShip account](https://www.aftership.com/signup).
|
17 |
+
|
18 |
+
###Display tracking info at order history page (Free)
|
19 |
+
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.
|
20 |
+
|
21 |
+
###Support 200+ International Carrier (Free)
|
22 |
+
AfterShip supports UPS tracking, FedEx tracking, USPS tracking, DHL tracking and shipment tracking of over 200+ carriers worlwide. Please scroll down to see the full list of our supported carriers.
|
23 |
+
|
24 |
+
|
25 |
+
###Track all shipments in one place (Free)
|
26 |
+
By setting up an auto import of tracking numbers to AfterShip, you can get the latest tracking info of all 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.
|
27 |
+
|
28 |
+
###Notify customers of delivery updates (Premium)
|
29 |
+
Upgrade to [Premium](https://www.aftership.com/premium) 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!
|
30 |
+
|
31 |
+
[youtube http://www.youtube.com/watch?v=1zCCx8Ap9ms]
|
32 |
+
|
33 |
+
###Full list of supported carriers (200+):
|
34 |
+
**①. US, Canada & Global Tracking (23)**
|
35 |
+
|
36 |
+
FedEx • UPS • DHL Express • USPS • UPS Mail Innovations • TNT • DPD • Aramex • DHL Global Mail • Toll Global Express • UPS Freight • Canada Post • Purolator • APC Postal Logistics • OnTrac • YRC • Asendia USA • LaserShip • i-parcel • ABF Freight • Estes • RL Carriers • Greyhound
|
37 |
+
|
38 |
+
**②. UK & Ireland Tracking (19)**
|
39 |
+
|
40 |
+
Royal Mail • Parcel Force • FedEx UK • DPD UK • SkyNet Worldwide Express • TNT UK • Interlink Express • UK Mail • YODEL • myHermes UK • City Link • Collect+ • DX • Deltec Courier • XDP Express • An Post • DPD Ireland • Fastway Ireland • Arrow XL
|
41 |
+
|
42 |
+
**③. Europe Tracking (66)**
|
43 |
+
|
44 |
+
Direct Link • International Seur • GLS • DHL Benelux • PostNord Logistics • Deutsche Post Mail • Deutsche Post DHL • Hermes Germany • DPD Germany • Austrian Post (Registered) • Austrian Post (Express) • Swiss Post • Correos de España • NACEX Spain • Spanish Seur • ASM • MRW • Redur Spain • Portugal CTT • Chronopost Portugal • Portugal Seur • La Poste • Colissimo • Chronopost France • Colis Privé • TNT France • Geodis Calberson France • PostNL Domestic • PostNL International • PostNL International 3S • DHL Netherlands • GLS Netherlands • Selektvracht • DHL Parcel NL • Belgium Post • bpost international • Itella Posti • Posten Norge • Sweden Posten • Post Danmark • Italy SDA • Poste Italiane Paccocelere • Poste Italiane • BRT Bartolini • GLS Italy • TNT Italy • Nexive (TNT Post Italy) • Russian Post • Nova Poshta • DHL Poland • Poczta Polska • DPD Poland • Siodemka • OPEK • Lietuvos paštas • Česká Pošta • ELTA Hellenic Post • ACS Courier • PTT Posta • Belpost • Bulgarian Posts • Hrvatska PoÅ¡ta • Kuehne + Nagel • Poșta Română • Cyprus Post • UkrPoshta
|
45 |
+
|
46 |
+
**④. Asia & China Tracking (57)**
|
47 |
+
|
48 |
+
DHL Global Mail Asia • Kerry Express Thailand • Singapore Post • Singapore Speedpost • TAQBIN Singapore • Korea Post • CJ GLS • India Post Domestic • India Post International • Delhivery • Bluedart • DTDC India • Professional Couriers • Safexpress • Red Express • Red Express Waybill • First Flight Couriers • Gati-KWE • GoJaVAS • Japan Post • Yamato Japan • Sagawa • Taiwan Post • Malaysia Post EMS / Poslaju • Malaysia Post - Registered • TAQBIN Malaysia • GDEX • SkyNet Malaysia • City-Link Express • Thailand Thai Post • Dynamic Logistics • 2GO • Xend • AIR21 • Jam Express • Pos Indonesia Domestic • Pos Indonesia Int'l • JNE • RPX Indonesia • Tiki • Wahana • LBC Express • First Logistics • Vietnam Post • Vietnam Post EMS • ViettelPost • Cambodia Post • S.F. Express • China Post • China EMS • 4PX • Yanwen • EC-Firstclass • AuPost China • WeDo Logistics • PayPal Package • JCEX • STO Express • Flyt Express • Hong Kong Post • TAQBIN Hong Kong • TGX
|
49 |
+
|
50 |
+
**⑤. Australia & New Zealand Tracking (10)**
|
51 |
+
|
52 |
+
Australia Post • Toll Priority • Toll IPEC • TNT Australia • Fastway Australia • StarTrack • Star Track Express • Couriers Please • New Zealand Post • CourierPost
|
53 |
+
|
54 |
+
**⑥. Latin America, Middle East & Other Tracking (18)**
|
55 |
+
|
56 |
+
Correos de Mexico • Estafeta • Mexico Senda Express • Mexico Redpack • Mexico Multipack • Mexico AeroFlash • Brazil Correios • Flash Courier • Correos Chile • Correo Argentino • OCA Argentina • Israel Post • Israel Post Domestic • South African Post Office • Fastway South Africa • Saudi Post • NiPost • Evergreen
|
57 |
+
|
58 |
+
|
59 |
+
== Installation ==
|
60 |
+
|
61 |
+
1. [Sign up AfterShip account for FREE](https://www.aftership.com/signup)
|
62 |
+
2. [Download AfterShip plugin](http://downloads.wordpress.org/plugin/aftership-woocommerce-tracking.zip), then install and activate at wordpress.
|
63 |
+
3. Select AfterShip Plugin or [WooCommerce Shipment Tracking Plugin](http://www.woothemes.com/products/shipment-tracking/) for entering tracking number
|
64 |
+
4. Check `Use Track Button` for displaying tracking info at order history page
|
65 |
+
5. Generate [AfterShip's WordPress API Key](http://aftership.uservoice.com/knowledgebase/articles/405909) under `Users` > `Your Profile`
|
66 |
+
6. Input `Store URL` and `AfterShip's WordPress API Key` at [AfterShip WooCommerce page](https://www.aftership.com/apps/woocommerce)
|
67 |
+
|
68 |
+
*** This plugin requires at least PHP 5.2.4
|
69 |
+
*** This plugin requires at least WooCommerce 2.1
|
70 |
+
|
71 |
+
###Further Reading
|
72 |
+
|
73 |
+
* [How to insert AfterShip Track Button to WordPress or WooCommerce](https://aftership.uservoice.com/knowledgebase/articles/268665)
|
74 |
+
* [Premium account pricing](https://www.aftership.com/premium)
|
75 |
+
* [List of supported couriers](https://www.aftership.com/courier)
|
76 |
+
* [Free vs Premium](https://www.aftership.com/free-vs-premium)
|
77 |
+
* [SMS Charges](https://www.aftership.com/sms-pricing)
|
78 |
+
* [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)
|
79 |
+
|
80 |
+
|
81 |
+
== Frequently Asked Questions ==
|
82 |
+
|
83 |
+
You'll find the FAQ on [AfterShip.com](https://aftership.uservoice.com/knowledgebase)
|
84 |
+
|
85 |
+
|
86 |
+
== Screenshots ==
|
87 |
+
|
88 |
+
1. Add tracking number and carrier to WooCommerce
|
89 |
+
2. Display tracking info at order history page
|
90 |
+
3. Support tracking of UPS, DHL, FedEx, USPS and 200+ carriers
|
91 |
+
4. AfterShip dashboard
|
92 |
+
5. Track all shipments in one place
|
93 |
+
6. View exception, and filter by status
|
94 |
+
7. Automatically send out delivery notifications
|
95 |
+
|
96 |
+
== Changelog ==
|
97 |
+
|
98 |
+
= 1.2.6 =
|
99 |
+
* Fix installation problem, php array
|
100 |
+
|
101 |
+
= 1.2.5 =
|
102 |
+
* No longer require to input AfterShip API key at Wordpress
|
103 |
+
* Allow carrier selection at Wordpress
|
104 |
+
* Support PHP 5.2.4 or greater
|
105 |
+
|
106 |
+
|
107 |
+
= 1.2.4 =
|
108 |
+
* Fix enable track button issues
|
109 |
+
* Support at least WooCommerce 2.1
|
110 |
+
|
111 |
+
= 1.2.3 =
|
112 |
+
* Fix undefined variables issue
|
113 |
+
* Add Icon
|
114 |
+
* Support Wordpress 4.0
|
115 |
+
|
116 |
+
= 1.2.2 =
|
117 |
+
* Fix the header issues of different server
|
118 |
+
|
119 |
+
= 1.2.1 =
|
120 |
+
* Fix the header issues of different server
|
121 |
+
|
122 |
+
= 1.2.0 =
|
123 |
+
* Fix the header issues of different server
|
124 |
+
|
125 |
+
= 1.1.9 =
|
126 |
+
* Fix the header issues of different server
|
127 |
+
|
128 |
+
= 1.1.8 =
|
129 |
+
* Fix the email display issues
|
130 |
+
|
131 |
+
= 1.1.7 =
|
132 |
+
* Fix the headers issues
|
133 |
+
|
134 |
+
= 1.1.6 =
|
135 |
+
* Fix the apache request headers issues
|
136 |
+
|
137 |
+
= 1.1.5 =
|
138 |
+
* Fix Bug - Order page - couriers callback
|
139 |
+
* Fix Bug - Avoid duplicate getAfterShipInstance()
|
140 |
+
|
141 |
+
= 1.1.4 =
|
142 |
+
* Fix Bug - assets location
|
143 |
+
* Fix Bug - WC Dependency
|
144 |
+
|
145 |
+
= 1.1.3 =
|
146 |
+
* Fix Bug - WC Dependency
|
147 |
+
* i18N change to AfterShip
|
148 |
+
|
149 |
+
= 1.1.2 =
|
150 |
+
* Updated the plugin name
|
151 |
+
|
152 |
+
= 1.1.1 =
|
153 |
+
* Updated the version number in aftership.php !
|
154 |
+
|
155 |
+
= 1.1.0 =
|
156 |
+
* Released
|
157 |
+
|
158 |
+
= 1.0.5 =
|
159 |
+
* Update Readme - add a video
|
160 |
+
|
161 |
+
= 1.0.4 =
|
162 |
+
* Delete changelog.txt
|
163 |
+
|
164 |
+
= 1.0.3 =
|
165 |
+
* Fix the plugin name
|
166 |
+
* Remove unused 3rd party plugin
|
167 |
+
|
168 |
+
= 1.0.2 =
|
169 |
+
* Remove the unnecessary plugin updater
|
170 |
+
|
171 |
+
= 1.0.1 =
|
172 |
+
* Fix the apache request headers issues
|
173 |
+
* Readme
|
174 |
+
|
175 |
+
= 1.0.0 =
|
176 |
+
* AfterShip plugin launched
|
177 |
+
|
178 |
+
|
179 |
+
== Upgrade Notice ==
|
180 |
+
|
181 |
+
No Upgrade Yet
|
trunk/woo-includes/class-wc-dependencies.php
ADDED
@@ -0,0 +1,30 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
<?php
|
2 |
+
/**
|
3 |
+
* WC Dependency Checker
|
4 |
+
*
|
5 |
+
* Checks if WooCommerce is enabled
|
6 |
+
*/
|
7 |
+
class WC_Dependencies {
|
8 |
+
|
9 |
+
private static $active_plugins;
|
10 |
+
|
11 |
+
public static function init() {
|
12 |
+
|
13 |
+
self::$active_plugins = (array) get_option( 'active_plugins', array() );
|
14 |
+
|
15 |
+
if ( is_multisite() )
|
16 |
+
self::$active_plugins = array_merge( self::$active_plugins, get_site_option( 'active_sitewide_plugins', array() ) );
|
17 |
+
}
|
18 |
+
|
19 |
+
public static function plugin_active_check($plugin){
|
20 |
+
if ( ! self::$active_plugins ) self::init();
|
21 |
+
return in_array( $plugin, self::$active_plugins ) || array_key_exists( $plugin, self::$active_plugins );
|
22 |
+
}
|
23 |
+
|
24 |
+
public static function woocommerce_active_check() {
|
25 |
+
return self::plugin_active_check('woocommerce/woocommerce.php');
|
26 |
+
}
|
27 |
+
|
28 |
+
}
|
29 |
+
|
30 |
+
|
trunk/woo-includes/woo-functions.php
ADDED
@@ -0,0 +1,15 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
<?php
|
2 |
+
/**
|
3 |
+
* Functions used by plugins
|
4 |
+
*/
|
5 |
+
if ( ! class_exists( 'WC_Dependencies' ) )
|
6 |
+
require_once 'class-wc-dependencies.php';
|
7 |
+
|
8 |
+
/**
|
9 |
+
* WC Detection
|
10 |
+
*/
|
11 |
+
if ( ! function_exists( 'is_woocommerce_active' ) ) {
|
12 |
+
function is_woocommerce_active() {
|
13 |
+
return WC_Dependencies::woocommerce_active_check();
|
14 |
+
}
|
15 |
+
}
|