| 1 |
<?php |
| 2 |
|
| 3 |
namespace FluentCart\App\Modules\Integrations; |
| 4 |
use FluentCart\App\App; |
| 5 |
use FluentCart\App\Helpers\Status; |
| 6 |
use FluentCart\App\Hooks\Scheduler\JobRunner; |
| 7 |
use FluentCart\App\Hooks\Scheduler\Scheduler; |
| 8 |
use FluentCart\App\Models\Customer; |
| 9 |
use FluentCart\App\Models\Meta; |
| 10 |
use FluentCart\App\Models\Order; |
| 11 |
use FluentCart\App\Models\OrderTransaction; |
| 12 |
use FluentCart\App\Models\ProductMeta; |
| 13 |
use FluentCart\App\Models\ScheduledAction; |
| 14 |
use FluentCart\App\Services\DateTime\DateTime; |
| 15 |
use FluentCart\Framework\Support\Arr; |
| 16 |
|
| 17 |
class GlobalNotificationHandler |
| 18 |
{ |
| 19 |
protected static $customerCache = []; |
| 20 |
protected static $transactionCache = []; |
| 21 |
protected static $orderCache = []; |
| 22 |
|
| 23 |
protected function getCustomer($customerId) |
| 24 |
{ |
| 25 |
if (isset(static::$customerCache[$customerId])) { |
| 26 |
return static::$customerCache[$customerId]; |
| 27 |
} |
| 28 |
|
| 29 |
$customer = Customer::query()->find($customerId); |
| 30 |
if ($customer) { |
| 31 |
static::$customerCache[$customerId] = $customer; |
| 32 |
} |
| 33 |
|
| 34 |
return $customer; |
| 35 |
} |
| 36 |
|
| 37 |
protected function getTransaction($orderId) |
| 38 |
{ |
| 39 |
if (isset(static::$transactionCache[$orderId])) { |
| 40 |
return static::$transactionCache[$orderId]; |
| 41 |
} |
| 42 |
|
| 43 |
$transaction = OrderTransaction::query() |
| 44 |
->where('order_id', $orderId) |
| 45 |
->orderBy('id', 'desc') |
| 46 |
->first(); |
| 47 |
|
| 48 |
if ($transaction) { |
| 49 |
static::$transactionCache[$orderId] = $transaction; |
| 50 |
} |
| 51 |
|
| 52 |
return $transaction; |
| 53 |
} |
| 54 |
|
| 55 |
|
| 56 |
protected function getOrder($orderId) |
| 57 |
{ |
| 58 |
if (isset(static::$orderCache[$orderId])) { |
| 59 |
return static::$orderCache[$orderId]; |
| 60 |
} |
| 61 |
|
| 62 |
$order = Order::query()->find($orderId); |
| 63 |
if ($order) { |
| 64 |
static::$orderCache[$order->id] = $order; |
| 65 |
} |
| 66 |
|
| 67 |
return $order; |
| 68 |
} |
| 69 |
|
| 70 |
public function maybeHandleGlobalNotify($order, $customer, $targetHook, $group): void |
| 71 |
{ |
| 72 |
//active feeds for orders |
| 73 |
$feeds = (new GlobalIntegrationSettings())->getNotificationFeeds(); |
| 74 |
$this->triggerNotification($feeds, $order, $customer, $targetHook, $group); |
| 75 |
} |
| 76 |
|
| 77 |
public function triggerNotification($feeds, $order, $customer, $targetHook = '', $group = 'integration', $object_type = 'order_integration'): void |
| 78 |
{ |
| 79 |
//trigger notification for each active feed |
| 80 |
$asyncFeeds = []; |
| 81 |
foreach ($feeds as $key => $feed) { |
| 82 |
if (isset($feed['enabled']) && (bool)$feed['enabled']) { |
| 83 |
$enabledTriggers = Arr::get($feed, 'feed.event_trigger', []); |
| 84 |
if (!$enabledTriggers || !in_array($targetHook, $enabledTriggers)) { |
| 85 |
continue; |
| 86 |
} |
| 87 |
|
| 88 |
$feed = $this->processFeedData($order, $feed); |
| 89 |
|
| 90 |
$feedKey = Arr::get($feed, 'provider'); |
| 91 |
if (!empty($feedKey)){ |
| 92 |
$action = 'fluent_cart/integration/integration_notify_' . $feedKey; |
| 93 |
$scheduleActionData = [ |
| 94 |
'action' => $action, |
| 95 |
'object_id' => $order['id'], |
| 96 |
'object_type' => $object_type, |
| 97 |
'scheduled_at' => DateTime::gmtNow(), |
| 98 |
'group' => $group, |
| 99 |
'data' => json_encode([ |
| 100 |
'feed_id' => $feed['id'] |
| 101 |
]) |
| 102 |
]; |
| 103 |
|
| 104 |
if (apply_filters('fluent_cart/integration/notifying_async_' . $feedKey, true)) { |
| 105 |
$asyncFeeds[] = $scheduleActionData; |
| 106 |
$hook = 'fluent_cart/integration/schedule_feed'; |
| 107 |
(new JobRunner())->async($hook, $scheduleActionData); |
| 108 |
} else { |
| 109 |
do_action( |
| 110 |
'fluent_cart/integration/integration_notify_' . $feedKey, |
| 111 |
$feed, |
| 112 |
$order, |
| 113 |
$customer |
| 114 |
); |
| 115 |
} |
| 116 |
} |
| 117 |
} |
| 118 |
} |
| 119 |
|
| 120 |
if (!$asyncFeeds) { |
| 121 |
do_action('fluent_cart/integrations/global_notify_completed', $order, $feeds); |
| 122 |
} |
| 123 |
} |
| 124 |
|
| 125 |
public function handleGlobalIntegration($action, $feed, $order, $customer, $transaction): void |
| 126 |
{ |
| 127 |
$formatFeed = (new GlobalIntegrationSettings())->formatFeedData($feed); |
| 128 |
$parsedFeedData = $this->processFeedData($order, $formatFeed); |
| 129 |
do_action($action, $parsedFeedData, $order, $customer, $transaction); |
| 130 |
} |
| 131 |
|
| 132 |
protected function getFeed($queue, $feedId) |
| 133 |
{ |
| 134 |
$query = $queue->object_type === 'order_integration' |
| 135 |
? Meta::query()->where('id', $feedId) |
| 136 |
: ProductMeta::query()->where('id', $feedId); |
| 137 |
|
| 138 |
return $query->where('object_type', $queue->object_type)->first(); |
| 139 |
} |
| 140 |
|
| 141 |
public function handleGlobalAsyncIntegration($queue): void |
| 142 |
{ |
| 143 |
$queueData = is_string($queue->data) ? json_decode($queue->data) : $queue->data; |
| 144 |
|
| 145 |
if (!isset($queueData->feed_id)) { |
| 146 |
return; |
| 147 |
} |
| 148 |
|
| 149 |
$feed = $this->getFeed($queue, $queueData->feed_id); |
| 150 |
if (!$feed) { |
| 151 |
return; |
| 152 |
} |
| 153 |
$order = $this->getOrder($queue->object_id); |
| 154 |
if (!$order) { |
| 155 |
return; |
| 156 |
} |
| 157 |
$customer = $this->getCustomer($order->customer_id); |
| 158 |
$transaction = $this->getTransaction($order->id); |
| 159 |
|
| 160 |
ScheduledAction::query()->where('id', $queue->id)->update([ |
| 161 |
'status' => Status::SCHEDULE_PROCESSING, |
| 162 |
'retry_count' => $queue->retry_count + 1, |
| 163 |
'scheduled_at' => DateTime::gmtNow() |
| 164 |
]); |
| 165 |
|
| 166 |
$this->processNotification($queue->action, $feed, $order, $customer, $transaction); |
| 167 |
|
| 168 |
// complete the queue |
| 169 |
ScheduledAction::query()->where('id', $queue->id)->update([ |
| 170 |
'status' => Status::SCHEDULE_COMPLETED, |
| 171 |
]); |
| 172 |
} |
| 173 |
|
| 174 |
/** |
| 175 |
* Process notification through global integration manager |
| 176 |
* |
| 177 |
* @param string $action |
| 178 |
* @param Meta|ProductMeta $feed |
| 179 |
* @param Order $order |
| 180 |
* @param Customer|null $customer |
| 181 |
* @param OrderTransaction|null $transaction |
| 182 |
* @return void |
| 183 |
*/ |
| 184 |
protected function processNotification(string $action, $feed, Order $order, ?Customer $customer, ?OrderTransaction $transaction): void |
| 185 |
{ |
| 186 |
$globalNotification = new GlobalNotificationHandler(); |
| 187 |
$globalNotification->handleGlobalIntegration( |
| 188 |
$action, $feed, $order, $customer, $transaction |
| 189 |
); |
| 190 |
} |
| 191 |
|
| 192 |
public function processFeedData($order, $feed) |
| 193 |
{ |
| 194 |
$userData = [ |
| 195 |
'first_name' => Arr::get($order, 'customer.first_name'), |
| 196 |
'last_name' => Arr::get($order, 'customer.last_name'), |
| 197 |
'email' => Arr::get($order, 'customer.email'), |
| 198 |
'phone' => Arr::get($order, 'customer.phone'), |
| 199 |
'country' => Arr::get($order, 'customer.country'), |
| 200 |
'city' => Arr::get($order, 'customer.city'), |
| 201 |
'state' => Arr::get($order, 'customer.state'), |
| 202 |
'postcode' => Arr::get($order, 'customer.postcode'), |
| 203 |
]; |
| 204 |
$feedDataUpdated = array_merge($feed['feed'], $userData); |
| 205 |
|
| 206 |
$feed['feed'] = $feedDataUpdated; |
| 207 |
return $feed; |
| 208 |
} |
| 209 |
|
| 210 |
public function processIntegrationAction($queueId): void |
| 211 |
{ |
| 212 |
$queue = ScheduledAction::query()->find($queueId); |
| 213 |
if (!$queue || empty($queue->action)) { |
| 214 |
return; |
| 215 |
} |
| 216 |
$this->handleGlobalAsyncIntegration($queue); |
| 217 |
} |
| 218 |
|
| 219 |
} |