PluginProbe ʕ •ᴥ•ʔ
Independent Analytics – WordPress Analytics Plugin / 2.14.2
Independent Analytics – WordPress Analytics Plugin v2.14.2
2.15.0 2.14.10 trunk 1.1 1.10 1.10.1 1.11 1.12 1.13 1.14 1.15 1.16 1.17 1.17.1 1.17.2 1.17.3 1.17.4 1.18 1.18.1 1.19.0 1.19.1 1.2 1.20.0 1.21.0 1.22.0 1.22.1 1.23.0 1.23.1 1.24.0 1.24.1 1.25.0 1.25.1 1.26.0 1.27.0 1.28.0 1.28.1 1.28.2 1.28.3 1.29.0 1.3 1.30.0 1.30.1 1.4 1.5 1.6 1.7 1.8 1.9 2.0.0 2.0.1 2.1.4 2.1.5 2.1.6 2.10.0 2.10.1 2.10.2 2.10.3 2.10.4 2.11.0 2.11.1 2.11.10 2.11.2 2.11.3 2.11.4 2.11.5 2.11.6 2.11.7 2.11.8 2.11.9 2.12.0 2.12.1 2.12.2 2.13.1 2.13.2 2.13.5 2.13.6 2.14.0 2.14.1 2.14.2 2.14.4 2.14.6 2.14.7 2.14.8 2.14.9 2.2.0 2.2.1 2.3.1 2.3.2 2.4.2 2.4.3 2.5.0 2.5.1 2.6.0 2.6.1 2.6.2 2.6.3 2.6.4 2.7.0 2.7.1 2.7.2 2.7.3 2.8.2 2.8.3 2.8.4 2.8.5 2.8.6 2.8.7 2.8.8 2.8.9 2.9.2 2.9.3 2.9.4 2.9.5 2.9.6 2.9.7
independent-analytics / IAWP / Ecommerce / WooCommerce_Order.php
independent-analytics / IAWP / Ecommerce Last commit date
EDD_Order.php 5 months ago Fluent_Cart_Order.php 5 months ago PMPro_Order.php 5 months ago SureCart_Event_Sync_Job.php 1 year ago SureCart_Order.php 5 months ago SureCart_Store.php 1 year ago WooCommerce_Order.php 5 months ago WooCommerce_Status_Manager.php 1 year ago
WooCommerce_Order.php
214 lines
1 <?php
2
3 namespace IAWP\Ecommerce;
4
5 use IAWP\Illuminate_Builder;
6 use IAWP\Models\Visitor;
7 use IAWP\Query;
8 use IAWP\Utils\Timezone;
9 /** @internal */
10 class WooCommerce_Order
11 {
12 private $order_id;
13 private $status;
14 private $total;
15 private $total_refunded;
16 private $total_refunds;
17 private $is_discounted;
18 /**
19 * @param int $order_id WooCommerce order ID
20 */
21 public function __construct(int $order_id)
22 {
23 $order = wc_get_order($order_id);
24 // Total based on order currency, not shop currency
25 $total = \intval(\round($order->get_total() * 100));
26 // Refund amount based on order currency, not shop currency
27 $total_refunded = \intval(\round(\floatval($order->get_total_refunded()) * 100));
28 [$total, $total_refunded] = $this->convert_to_base_currency($order, $total, $total_refunded);
29 $this->order_id = $order_id;
30 $this->status = $order->get_status();
31 $this->total = $total;
32 $this->total_refunded = $total_refunded;
33 $this->total_refunds = \count($order->get_refunds());
34 $this->is_discounted = $this->is_discounted_order($order);
35 }
36 public function insert() : void
37 {
38 $visitor = Visitor::fetch_current_visitor();
39 if (!$visitor->has_recorded_session()) {
40 return;
41 }
42 $orders_table = Query::get_table_name(Query::ORDERS);
43 Illuminate_Builder::new()->from($orders_table)->insertOrIgnore(['is_included_in_analytics' => (new \IAWP\Ecommerce\WooCommerce_Status_Manager())->is_tracked_status($this->status), 'woocommerce_order_id' => $this->order_id, 'woocommerce_order_status' => $this->status, 'view_id' => $visitor->most_recent_view_id(), 'initial_view_id' => $visitor->most_recent_initial_view_id(), 'total' => $this->total, 'total_refunded' => $this->total_refunded, 'total_refunds' => $this->total_refunds, 'is_discounted' => $this->is_discounted, 'created_at' => (new \DateTime('now', Timezone::utc_timezone()))->format('Y-m-d H:i:s')]);
44 }
45 public function update() : void
46 {
47 $orders_table = Query::get_table_name(Query::ORDERS);
48 Illuminate_Builder::new()->from($orders_table)->where('woocommerce_order_id', '=', $this->order_id)->update(['is_included_in_analytics' => (new \IAWP\Ecommerce\WooCommerce_Status_Manager())->is_tracked_status($this->status), 'woocommerce_order_status' => $this->status, 'total' => $this->total, 'total_refunded' => $this->total_refunded, 'total_refunds' => $this->total_refunds, 'is_discounted' => $this->is_discounted]);
49 }
50 private function convert_to_base_currency($order, $total, $total_refunded)
51 {
52 $exchange_rate = $this->exchange_rate($order);
53 if (\is_float($exchange_rate)) {
54 // Exchange rate is from shop currency to order currency (divide)
55 $total = \intval(\round($total / $exchange_rate));
56 $total_refunded = \intval(\round($total_refunded / $exchange_rate));
57 }
58 return [$total, $total_refunded];
59 }
60 private function is_discounted_order($order) : bool
61 {
62 if ($order->get_total_discount() > 0) {
63 return \true;
64 }
65 foreach ($order->get_items() as $item) {
66 if ($item->get_product()->is_on_sale()) {
67 return \true;
68 }
69 }
70 return \false;
71 }
72 private function exchange_rate($order) : ?float
73 {
74 $rate_getters = [fn() => $this->aelia_exchange_rate($order), fn() => $this->wpml_exchange_rate($order), fn() => $this->curcy_exchange_rate($order), fn() => $this->pbc_exchange_rate($order), fn() => $this->yith_exchange_rate($order), fn() => $this->woopayments_exchange_rate($order), fn() => $this->yay_currency_exchange_rate($order)];
75 foreach ($rate_getters as $rate_getter) {
76 $exchange_rate = $rate_getter();
77 if (\is_float($exchange_rate)) {
78 return $exchange_rate;
79 }
80 }
81 return null;
82 }
83 private function aelia_exchange_rate($order) : ?float
84 {
85 $exchange_rate = $order->get_meta('_base_currency_exchange_rate');
86 if (!\is_numeric($exchange_rate)) {
87 return null;
88 }
89 return 1 / \floatval($exchange_rate);
90 }
91 private function wpml_exchange_rate($order) : ?float
92 {
93 $currency_code = $order->get_currency();
94 if (!\is_plugin_active('woocommerce-multilingual/wpml-woocommerce.php')) {
95 return null;
96 }
97 $wcml_options = \get_option('_wcml_settings');
98 if (!\is_array($wcml_options)) {
99 return null;
100 }
101 if (!\array_key_exists('currency_options', $wcml_options)) {
102 return null;
103 }
104 if (!\is_array($wcml_options['currency_options']) || !\array_key_exists($currency_code, $wcml_options['currency_options'])) {
105 return null;
106 }
107 if (!\is_array($wcml_options['currency_options'][$currency_code]) || !\array_key_exists('rate', $wcml_options['currency_options'][$currency_code])) {
108 return null;
109 }
110 $exchange_rate = \floatval($wcml_options['currency_options'][$currency_code]['rate']);
111 // Was there an error parsing value as float?
112 if ($exchange_rate === 0.0) {
113 return null;
114 }
115 return $exchange_rate;
116 }
117 private function curcy_exchange_rate($order) : ?float
118 {
119 $rates = $order->get_meta('wmc_order_info');
120 $currency = $order->get_currency();
121 if (!\is_array($rates)) {
122 return null;
123 }
124 $rate = $rates[$currency]['rate'] ?? null;
125 if (!\is_numeric($rate)) {
126 return null;
127 }
128 return (float) $rate;
129 }
130 private function pbc_exchange_rate($order) : ?float
131 {
132 $exchange_rate = $order->get_meta('_wcpbc_base_exchange_rate');
133 if (!\is_numeric($exchange_rate)) {
134 return null;
135 }
136 return 1 / \floatval($exchange_rate);
137 }
138 private function yith_exchange_rate($order) : ?float
139 {
140 $currency = $order->get_currency();
141 $is_yith_order = !empty($order->get_meta('_yith_wcmcs_default_currency_on_creation'));
142 if (!$is_yith_order) {
143 return null;
144 }
145 try {
146 $rates = \yith_wcmcs_get_currencies();
147 if (!\array_key_exists($currency, $rates)) {
148 return null;
149 }
150 return $rates[$currency]->get_rate('raw');
151 } catch (\Throwable $e) {
152 return null;
153 }
154 }
155 private function woopayments_exchange_rate($order) : ?float
156 {
157 $rate = $order->get_meta('_wcpay_multi_currency_order_exchange_rate');
158 if (!\is_numeric($rate)) {
159 return null;
160 }
161 return (float) $rate;
162 }
163 private function yay_currency_exchange_rate($order) : ?float
164 {
165 $rate = $order->get_meta('yay_currency_order_rate');
166 if (!\is_numeric($rate)) {
167 return null;
168 }
169 return (float) $rate;
170 }
171 public static function register_hooks()
172 {
173 // Required for block checkout
174 \add_action('woocommerce_store_api_checkout_order_processed', function ($order) {
175 try {
176 $woocommerce_order = new self($order->get_id());
177 $woocommerce_order->insert();
178 } catch (\Throwable $e) {
179 \error_log('Independent Analytics was unable to track the analytics for a WooCommerce order. Please report this error to Independent Analytics. The error message is below.');
180 \error_log($e->getMessage());
181 }
182 });
183 // Required for shortcode checkout
184 \add_action('woocommerce_checkout_order_created', function ($order) {
185 try {
186 $woocommerce_order = new self($order->get_id());
187 $woocommerce_order->insert();
188 } catch (\Throwable $e) {
189 \error_log('Independent Analytics was unable to track the analytics for a WooCommerce order. Please report this error to Independent Analytics. The error message is below.');
190 \error_log($e->getMessage());
191 }
192 });
193 \add_action('woocommerce_order_status_changed', function ($order_id) {
194 try {
195 $woocommerce_order = new self($order_id);
196 $woocommerce_order->update();
197 } catch (\Throwable $e) {
198 \error_log('Independent Analytics was unable to track the analytics for a WooCommerce order. Please report this error to Independent Analytics. The error message is below.');
199 \error_log($e->getMessage());
200 }
201 });
202 // Captures a partial refund, something that woocommerce_order_status_changed will not do
203 \add_action('woocommerce_order_refunded', function ($order_id) {
204 try {
205 $woocommerce_order = new self($order_id);
206 $woocommerce_order->update();
207 } catch (\Throwable $e) {
208 \error_log('Independent Analytics was unable to track the analytics for a WooCommerce order. Please report this error to Independent Analytics. The error message is below.');
209 \error_log($e->getMessage());
210 }
211 });
212 }
213 }
214