Warning: chmod(): Operation not permitted in /var/www/hopeinstoughton_www/wp-content/plugins/simple-universal-google-analytics/main.php on line 8 [0] in function chmod in /var/www/hopeinstoughton_www/wp-content/plugins/simple-universal-google-analytics/main.php on line 8 [1] in function include_once in /var/www/hopeinstoughton_www/wp-settings.php on line 560 [2] in function require_once in /var/www/hopeinstoughton_www/wp-config.php on line 85 [3] in function require_once in /var/www/hopeinstoughton_www/wp-load.php on line 50 [4] in function require_once in /var/www/hopeinstoughton_www/wp-blog-header.php on line 13 [5] in function require in /var/www/hopeinstoughton_www/index.php on line 17
| Server IP : 94.177.8.99 / Your IP : 216.73.217.165 Web Server : Apache/2.4.58 (Ubuntu) System : Linux aries 6.8.0-134-generic #134-Ubuntu SMP PREEMPT_DYNAMIC Fri Jun 26 18:43:11 UTC 2026 x86_64 User : www-data ( 33) PHP Version : 8.1.34 Disable Function : NONE MySQL : OFF | cURL : ON | WGET : ON | Perl : ON | Python : OFF | Sudo : ON | Pkexec : OFF Directory : /var/www/theyoungdesigners_com/modules/store/model/ |
Upload File : |
<?php
// to do: show history?
class TrackingItem implements JsonSerializable {
private $item_id;
private $order_id;
private $status_id;
private $tracking;
private $status;
private $changed;
private $detail;
use \modules\database\traits {
\modules\database\traits::__construct as __ConstructDatabase;
}
public function __construct() {
$this->__ConstructDatabase();
$this->item_id = '';
$this->order_id = '';
$this->tracking = '';
$this->status = '';
$this->status_id = 0;
$this->changed = FALSE;
$this->detail = [];
// shipper?
}
public function jsonSerialize() {
return [
'item_id' => $this->item_id,
'order_id' => $this->order_id,
'tracking' => $this->tracking,
'status' => $this->status ?? '',
'detail' => $this->detail ?? [],
];
}
public function ItemId() {
if (func_num_args()) {
$this->item_id = func_get_arg(0);
return $this;
}
return $this->item_id;
}
public function OrderId() {
if (func_num_args()) {
$this->order_id = func_get_arg(0);
$this->changed = TRUE;
return $this;
}
return $this->order_id;
}
public function Tracking() {
if (func_num_args()) {
$this->tracking = func_get_arg(0);
$this->changed = TRUE;
return $this;
}
return $this->tracking;
}
public function Status() {
if (func_num_args()) {
$this->status = func_get_arg(0);
$this->changed = TRUE;
return $this;
}
if (empty($this->status)) {
return $this->_extractStatus();
}
return $this->status;
}
public function StatusId() {
if (func_num_args()) {
$this->status_id = func_get_arg(0);
$this->changed = TRUE;
return $this;
}
return $this->status_id;
}
public function Detail() {
if (func_num_args()) {
$this->detail = func_get_arg(0);
$this->status = $this->_extractStatus();
$this->changed = TRUE;
return $this;
}
return $this->detail;
}
public function LoadFromDataset($data, $sot_id = 0) {
if ($sot_id) $this->item_id = $sot_id;
$this->order_id = $data->sot_order;
$this->tracking = $data->sot_tracking;
$this->status = $data->sot_status;
$this->status_id= $data->sot_status_id;
$this->detail = json_decode($data->sot_detail, TRUE);
}
public function updateItem($data) {
if ($data['tracking'] != $this->tracking) $this->Tracking($data['tracking']);
if (array_key_exists('status', $data) && $data['status'] != $this->status) $this->Status($data['status']);
if (array_key_exists('detail', $data)) $this->Detail($data['detail']);
return $this->changed;
}
public function Update() {
$this->TableName('store_order_tracking')
->InsertOrUpdate([
'sot_id' => $this->item_id,
],[
'sot_tracking' => $this->tracking,
'sot_status' => $this->status,
'sot_detail' => json_encode($this->detail, JSON_UNESCAPED_SLASHES),
'sot_status_id' => $this->status_id,
]);
$this->DbErr();
$this->changed = FALSE;
}
private function _extractStatus() {
switch($this->detail['transitStatus'] ?? '') {
case 'IN_TRANSIT':
$this->status_id = 200;
return 'On the Way';
case 'INFO_RECEIVED':
$this->status_id = 100;
return 'Shipping Label Created';
case 'WAITING_DELIVERY':
$this->status_id = 300;
return 'Out for Delivery';
case 'DELIVERED':
$this->status_id = 400;
return 'Delivered';
case 'NO_RECORD':
$this->status_id = 0;
return 'Shipping Label not found'; // check back later
case '':
return '';
default:
return $this->detail['transitStatus'];
}
}
private function _asHistory_location($x) {
if ($x == '') return 0;
$p = strpos($x, ',');
if ($p !== FALSE) {
$p++;
$x = substr($x, 0, $p) . ' ' . trim(substr($x, $p));
}
return $x;
}
private function _asHistory($x) {
$output = [];
foreach($x['trackingDetails'] as $item) {
$status = $item['eventDetail'];
if (($p = strpos($status, '->')) !== FALSE) {
$status = substr($status, 0, $p);
}
$dt = strtotime($item['eventTime'] . 'Z');
$output[] = [
'status' => $status,
'location' => $this->_asHistory_location($item['address'] ?? ''),
'date' => gmdate('F j, Y, g:i a', $dt), // January 25, 2025, 11:07 am
];
}
return $output;
}
public function AsHandlebars_full() {
if (isset($this->detail['localLogisticsInfo']['trackingDetails'])) {
$node = $this->detail['localLogisticsInfo'];
$history = $this->_asHistory($node);
$link = $node['courierTrackingLink'];
$shipper = $node['courierNameEN'];
// ups link from track123 is inaccurate
if ($node['courierCode'] == 'ups') {
$link = 'https://www.ups.com/track?track=yes&trackNums={trackingNo}';
}
$link = str_replace('#{trackingNo}', $this->Tracking(), $link);
} else {
$history = [];
$link = $shipper = 0;
}
$result = [
'number' => $this->Tracking(),
'status' => 'In Transit',
'history' => $history,
'link' => $link,
'shipper' => $shipper,
];
if (isset($this->detail['expectedDelivery'])) {
$dt = strtotime($this->detail['expectedDelivery'] . 'Z');
$result['estimated'] = gmdate('l, F j, Y', $dt);
}
$result['progress'] = $this->Status();
return $result;
}
}
class Tracking_Model extends Database_Model {
private $order_id;
private $tracking = [];
public function OrderId() {
if (func_num_args()) {
$old_id = $this->order_id;
$this->order_id = func_get_arg(0);
if ($old_id != $this->order_id) {
$this->tracking = $this->Load();
}
return $this;
}
return $this->order_id;
}
public function Load() {
$result = [];
if ($this->order_id) {
$rows = $this->Query('select * from `store_order_tracking`')
->Where('sot_order=%d', $this->order_id)
->OrderBy('sot_id')
->Get();
foreach($rows as $row) {
$node = new TrackingItem();
$node->LoadFromDataset($row, $row->sot_id);
$result[] = $node;
}
}
return $result;
}
public function AsHandlebars() {
$col = '';
foreach($this->tracking as $item) {
$tracking_number = $item->Tracking();
if ($tracking_number != '') $col .= "$tracking_number\n";
}
return [
'tracking' => $col,
];
}
public function SaveTrackings($numbers) {
// make sure the numbers are in the correct format
// if any unsuitable - list them and exit
$unsuitable = '';
foreach($numbers as $index => &$tracking_number) {
$tracking_number = strtoupper($tracking_number);
$res = hook_execute('tracking.validate', NULL, $tracking_number);
if (!is_object($res)) {
if ($unsuitable != '') $unsuitable .= ', ';
$unsuitable .= $tracking_number;
}
}
unset($tracking_number);
if ($unsuitable != '') {
return 'These tracking numbers are unrecognized: ' . $unsuitable; // don't know which freight service uses tracking numbers in this format
}
// $this->tracking has the old numbers
$old = [];
foreach($this->tracking as $item) {
$data = $item->jsonSerialize();
$key = $data['tracking'];
$old[$key] = $data;
}
$this->TableName('store_order_tracking')
->AutoInc('sot_id');
// $numbers has the new
foreach($numbers as $index => $tracking_number) {
$tracking_number = strtoupper($tracking_number);
$data = $old[$tracking_number] ?? NULL;
if ($index > count($this->tracking) - 1) {
$data = $this->InsertOrUpdate([
'sot_id' => NULL,
], [
'sot_order' => $this->order_id,
'sot_tracking' => $tracking_number,
]);
$this->_registerTracking($tracking_number);
} else {
$isnew = is_null($data);
if ($isnew) { // replace old tracking number with new
$data = [
'tracking' => $tracking_number,
'detail' => [],
];
}
// update item, returns true if changed
if ($this->tracking[$index]->updateItem($data)) { // object row_id does not change
// save in database
$this->tracking[$index]->Update();
if ($isnew) {
$this->_registerTracking($this->tracking[$index]->Tracking());
}
}
}
}
// anything left over will be deleted from db
$ids = [];
for($i = count($numbers); $i < count($this->tracking); $i++) {
$ids[] = $this->tracking[$i]->ItemId();
}
// delete items
if (count($ids)) {
$this->Query('delete from `store_order_tracking`')
->Where('sot_order=%d', $this->order_id)
->WhereIn('sot_id', $ids)
->Get();
}
// save the tracking numbers, creating a new record for each
// if it is a new tracking number, register a callback with the appropriate shipping company
$this->Load();
return TRUE;
}
private function _registerTracking($tracking_number) {
hook_execute('freight.track', $tracking_number);
}
public function getTracking($tracking_number) {
$row = $this->Query('select * from `store_order_tracking`')
->Where('sot_tracking=%s', $tracking_number)
->OrderBy('sot_id desc')
->Get()
->First();
if (!empty($row) && !$row->empty()) {
$node = new TrackingItem();
$node->LoadFromDataset($row, $row->sot_id);
return $node;
} else {
return NULL;
}
}
public function mergeTracking(&$data) {
// merge in tracking numbers for the selected orders
$ids = [];
foreach($data as $order) {
$ids[$order['id']] = [];
}
unset($order);
$rows = $this->Query('select * from `store_order_tracking`')
->WhereIn('sot_order', array_keys($ids))
->Get();
$node = new TrackingItem();
foreach($rows as $row) {
$node->LoadFromDataset($row, $row->sot_id);
$order_id = $node->OrderId();
$ids[$order_id][] = $node->jsonSerialize();
}
foreach($data as &$order) {
$order_id = $order['id'];
if (count($ids[$order_id])) {
$order['tracking'] = [];
foreach($ids[$order_id] as $entry) {
$order['tracking'][] = $entry['tracking'];
}
}
}
}
public function AsHandlebars_full($specific = '') {
$output = [];
foreach($this->tracking as $item) {
if ($specific == '' || $item->Tracking() == $specific) {
$output[] = $item->AsHandlebars_full();
}
}
return $output;
}
public function AsHandlebars_list() {
$output = [];
foreach($this->tracking as $item) {
$res = hook_execute('tracking.validate', NULL, $item->Tracking());
$output[] = [
'number' => $item->Tracking(),
'status' => $item->Status(),
'carrier' => is_null($res) ? '' : strtoupper($res->carrier),
// expected delivery date?
];
}
return $output;
}
}