PluginProbe
FluentCart A New Era of eCommerce – Faster, Lighter, and Simpler / 1.7.0
FluentCart A New Era of eCommerce – Faster, Lighter, and Simpler v1.7.0
1.7.0 1.6.6 1.6.5 1.6.4 1.6.3 1.6.2 1.6.1 1.6.0 1.5.4 1.5.5 1.5.3 1.5.2 1.5.1 1.5.0 1.4.2 1.4.1 1.4.0 1.3.28 1.3.27 1.3.26 1.3.25 1.3.23 1.3.22 1.3.21 1.3.20 All 50 releases
fluent-cart / app / Hooks / actions.php

actions.php in FluentCart A New Era of eCommerce – Faster, Lighter, and Simpler 1.7.0, at app/Hooks/actions.php

310 lines 13.2 KB
No matching file
Up and down to move Enter to open Esc to close
Raw Download Zip
1 <?php if (!defined('ABSPATH')) exit; ?>
2 <?php
3
4 /**
5 * All registered action's handlers should be in app\Hooks\Handlers,
6 * addAction is similar to add_action and addCustomAction is just a
7 * wrapper over add_action which will add a prefix to the hook name
8 * using the plugin slug to make it unique in all WordPress plugins,
9 * ex: $app->addCustomAction('foo', ['FooHandler', 'handleFoo']) is
10 * equivalent to add_action('slug-foo', ['FooHandler', 'handleFoo']).
11 */
12
13 /**
14 * @var $app FluentCart\Framework\Foundation\Application
15 */
16
17 use FluentCart\App\Http\Routes\WebRoutes;
18
19 (new \FluentCart\App\CPT\FluentProducts)->register();
20 (new \FluentCart\App\Services\Email\EmailNotificationMailer)->register();
21 (new \FluentCart\App\Hooks\Handlers\CPTHandler)->register();
22 (new \FluentCart\App\Hooks\Handlers\MenuHandler)->register();
23 (new \FluentCart\App\Hooks\Handlers\AdminMenuBarHandler)->register();
24 (new \FluentCart\App\Hooks\Handlers\FluentCartHandler)->register();
25 (new \FluentCart\App\Hooks\Handlers\RetentionSnapshotHandler)->register();
26 (new \FluentCart\App\Hooks\Handlers\ReminderHandler)->register();
27
28 (new \FluentCart\App\Hooks\Handlers\ShortCodes\ShopAppHandler)->register();
29 (new \FluentCart\App\Hooks\Handlers\ShortCodes\OrderReviewShortCode)->register();
30
31 (new FluentCart\App\Hooks\Handlers\CustomCheckout\CustomCheckout())->register();
32
33 // Tax Module Init
34 add_action('init', function () {
35 (new \FluentCart\App\Modules\Tax\TaxModule())->register();
36 }, 1);
37
38 // Turnstile Module Init
39 (new \FluentCart\App\Modules\Turnstile\TurnstileInit())->register(\FluentCart\App\App::getInstance());
40
41 // Reviews Module Init
42 (new \FluentCart\App\Modules\Reviews\ReviewModule())->register();
43
44 (new \FluentCart\App\Modules\FluentPlayer\FluentPlayerAdminAssets())->register();
45
46 // Register Pro Gateways Promo
47 (new \FluentCart\App\Hooks\Handlers\PromoGatewaysHandler())->register();
48
49 // Register Addon Gateways
50 (new \FluentCart\App\Hooks\Handlers\AddonGatewaysHandler())->register();
51
52 // Web Checkout
53 (new \FluentCart\App\Hooks\Cart\WebCheckoutHandler())->register();
54
55
56 \FluentCart\App\Hooks\Handlers\BlockEditors\ShopApp\ShopAppBlockEditor::register();
57 \FluentCart\App\Hooks\Handlers\BlockEditors\ProductCarousel\ProductCarouselBlockEditor::register();
58 \FluentCart\App\Hooks\Handlers\BlockEditors\MediaCarousel\MediaCarouselBlockEditor::register();
59
60 \FluentCart\App\Hooks\Handlers\ShortCodes\SearchBarShortCode::register();
61 \FluentCart\App\Hooks\Handlers\BlockEditors\SearchBarBlockEditor::register();
62 \FluentCart\App\Hooks\Handlers\BlockEditors\PricingTableBlockEditor::register();
63 \FluentCart\App\Hooks\Handlers\BlockEditors\CustomerProfileBlockEditor::register();
64 \FluentCart\App\Hooks\Handlers\ShortCodes\CustomerProfileHandler::register();
65 \FluentCart\App\Hooks\Handlers\BlockEditors\Checkout\CheckoutBlockEditor::register();
66 \FluentCart\App\Hooks\Handlers\ShortCodes\CartShortcode::register();
67 \FluentCart\App\Hooks\Handlers\ShortCodes\PricingTableShortCode::register();
68 \FluentCart\App\Hooks\Handlers\ShortCodes\Checkout\CheckoutPageHandler::register();
69 \FluentCart\App\Hooks\Handlers\BlockEditors\ProductCardBlockEditor::register();
70 \FluentCart\App\Hooks\Handlers\BlockEditors\ProductGalleryBlockEditor::register();
71 \FluentCart\App\Hooks\Handlers\BlockEditors\ProductInfoBlockEditor::register();
72 \FluentCart\App\Hooks\Handlers\BlockEditors\BuySectionBlockEditor::register();
73 \FluentCart\App\Hooks\Handlers\BlockEditors\ProductTitleBlockEditor::register();
74 \FluentCart\App\Hooks\Handlers\BlockEditors\ProductImageBlockEditor::register();
75 \FluentCart\App\Hooks\Handlers\BlockEditors\PriceRangeBlockEditor::register();
76 \FluentCart\App\Hooks\Handlers\BlockEditors\SaleBadgeBlockEditor::register();
77 \FluentCart\App\Hooks\Handlers\BlockEditors\ExcerptBlockEditor::register();
78 \FluentCart\App\Hooks\Handlers\BlockEditors\ProductDescriptionBlockEditor::register();
79 \FluentCart\App\Hooks\Handlers\ShortCodes\ProductCardShortCode::register();
80 \FluentCart\App\Hooks\Handlers\BlockEditors\Buttons\BuyNowButtonBlockEditor::register();
81 \FluentCart\App\Hooks\Handlers\BlockEditors\Buttons\AddToCartButtonBlockEditor::register();
82
83 \FluentCart\App\Hooks\Handlers\BlockEditors\MiniCartBlockEditor::register();
84 \FluentCart\App\Hooks\Handlers\BlockEditors\Cart\CartBlockEditor::register();
85 \FluentCart\App\Hooks\Handlers\BlockEditors\ProductCategoriesListBlockEditor::register();
86 \FluentCart\App\Hooks\Handlers\BlockEditors\RelatedProduct\RelatedProductBlockEditor::register();
87 \FluentCart\App\Hooks\Handlers\ShortCodes\Buttons\DirectCheckoutShortcode::register();
88 \FluentCart\App\Hooks\Handlers\ShortCodes\Buttons\AddToCartShortcode::register();
89 \FluentCart\App\Hooks\Handlers\ShortCodes\MiniCartShortcode::register();
90 \FluentCart\App\Hooks\Handlers\ShortCodes\ProductCategoriesListShortcode::register();
91 \FluentCart\App\Hooks\Handlers\ShortCodes\ProductTitleShortCode::register();
92 \FluentCart\App\Hooks\Handlers\ShortCodes\ProductImageShortCode::register();
93 \FluentCart\App\Hooks\Handlers\ShortCodes\SingleProductShortCode::register();
94
95
96 \FluentCart\App\Hooks\Handlers\BlockEditors\ProductSkuBlockEditor::register();
97 \FluentCart\App\Hooks\Handlers\BlockEditors\ProductPackageDescriptionBlockEditor::register();
98 \FluentCart\App\Hooks\Handlers\BlockEditors\StoreLogoBlockEditor::register();
99 \FluentCart\App\Hooks\Handlers\ShortCodes\StoreLogoShortCode::register();
100 \FluentCart\App\Hooks\Handlers\BlockEditors\CustomerDashboardButtonBlockEditor::register();
101 \FluentCart\App\Hooks\Handlers\ShortCodes\CustomerDashboardButtonShortcode::register();
102
103
104 (new \FluentCart\App\Modules\StockManagement\StockManagement())->register(fluentCart());
105
106 if (\FluentCart\Api\ModuleSettings::isActive('stock_management')) {
107 \FluentCart\App\Hooks\Handlers\BlockEditors\StockBlock::register();
108 \FluentCart\App\Hooks\Handlers\BlockEditors\SoldOutBadgeBlockEditor::register();
109 }
110
111 if (\FluentCart\Api\ModuleSettings::isActive('reviews') && class_exists(\FluentCart\App\Hooks\Handlers\BlockEditors\ProductReviewsBlockEditor::class)) {
112 \FluentCart\App\Hooks\Handlers\BlockEditors\ProductReviewsBlockEditor::register();
113 \FluentCart\App\Hooks\Handlers\BlockEditors\ProductRatingBlockEditor::register();
114 \FluentCart\App\Hooks\Handlers\BlockEditors\WriteAReviewButtonBlockEditor::register();
115 \FluentCart\App\Hooks\Handlers\BlockEditors\ProductReviewFormBlockEditor::register();
116 \FluentCart\App\Hooks\Handlers\BlockEditors\ProductReviewSummaryBlockEditor::register();
117 \FluentCart\App\Hooks\Handlers\BlockEditors\ProductReviewList\ProductReviewListBlockEditor::register();
118 \FluentCart\App\Hooks\Handlers\BlockEditors\ProductReviewSummaryGroupBlockEditor::register();
119 \FluentCart\App\Hooks\Handlers\ShortCodes\ProductReviewsShortCode::register();
120 }
121
122 (new \FluentCart\App\Hooks\Cart\CartLoader)->register();
123 (new \FluentCart\App\Hooks\Handlers\GlobalPaymentHandler)->register();
124
125 \FluentCart\App\Http\Routes\WebRoutes::register();
126
127 (new \FluentCart\App\Modules\IntegrationActions\GlobalIntegrationActionHandler())->register();
128 (new \FluentCart\App\Hooks\Handlers\GlobalStorageHandler)->register();
129
130
131 //Register Page Handlers
132 (new \FluentCart\App\Hooks\Handlers\ShortCodes\ReceiptHandler)->register();
133
134 (new \FluentCart\App\Modules\Coupon\CouponHandler)->register();
135
136 \FluentCart\App\Services\Theme\AdminTheme::applyTheme();
137 \FluentCart\App\Services\Theme\FrontendTheme::applyTheme();
138
139 (new \FluentCart\App\CPT\Pages)->handlePageDelete();
140 (new \FluentCart\App\Services\FileSystem\DownloadService)->register();
141
142 (new \FluentCart\App\Hooks\Handlers\UserHandler())->register();
143
144 // Corrected hook name: fluent_cart/order_paid_async_private_handle
145 // Legacy (typo'd) listener kept for any pending Action Scheduler jobs
146 $orderPaidAsyncHandler = function ($data) {
147 $orderId = \FluentCart\Framework\Support\Arr::get($data, 'order_id');
148
149 if (!$orderId) {
150 return;
151 }
152
153 $order = \FluentCart\App\Models\Order::find($orderId);
154 if (!$order || $order->payment_status !== 'paid') {
155 return;
156 }
157
158 // Claim the run by deleting the meta and branching on the affected-row count.
159 // The Action Scheduler worker and the receipt-page AJAX nudge
160 // (IntegrationEventListener::runOrderActionsAjax) can arrive together, so a
161 // read-then-delete would let both pass the guard and fire order_paid_done
162 // twice. A single DELETE is atomic: MySQL hands the row to exactly one
163 // caller, and the loser sees 0 rows and returns.
164 if (!$order->deleteMeta('action_scheduler_id')) {
165 return;
166 }
167
168 $transaction = \FluentCart\App\Models\OrderTransaction::query()
169 ->where('order_id', $order->id)
170 ->where('status', \FluentCart\App\Helpers\Status::TRANSACTION_SUCCEEDED)
171 ->orderBy('id', 'DESC')
172 ->first();
173
174 $eventData = [
175 'order' => $order,
176 'transaction' => $transaction,
177 'customer' => $order->customer
178 ];
179
180 if ($order->type === 'subscription' || $order->type === 'renewal') {
181 $subscription = \FluentCart\App\Models\Subscription::query()->where('parent_order_id', $order->id)->first();
182 if ($subscription) {
183 $eventData['subscription'] = $subscription;
184 }
185 }
186
187 do_action('fluent_cart/order_paid_done', $eventData);
188
189 };
190 add_action('fluent_cart/order_paid_async_private_handle', $orderPaidAsyncHandler, 1, 1);
191
192 // The settled half of a review approval — see ReviewApproved::afterDispatch().
193 // Runs off the request, so it trusts nothing it was told: the review is
194 // re-read, and only one that is still an approved top-level review is
195 // announced. Deleted or held back since, nothing fires.
196 $reviewApprovedAsyncHandler = function ($data) {
197 $reviewId = (int) \FluentCart\Framework\Support\Arr::get($data, 'review_id');
198
199 if (!$reviewId) {
200 return;
201 }
202
203 $review = \FluentCart\App\Models\ProductReview::query()->with('product')->find($reviewId);
204
205 if (!$review || $review->parent_id || $review->status !== \FluentCart\App\Helpers\Status::REVIEW_APPROVED) {
206 return;
207 }
208
209 do_action('fluent_cart/review_approved_done', [
210 'review' => $review,
211 'product' => $review->product,
212 ]);
213 };
214 add_action('fluent_cart/review_approved_async_private_handle', $reviewApprovedAsyncHandler, 1, 1);
215
216 // The settled half of a store reply — see ReviewReplied::afterDispatch().
217 // Announced only while both halves are published: the reply itself, and the
218 // review it answers. A reply to a review nobody can see is not a
219 // conversation the reviewer can be pointed at.
220 $reviewRepliedAsyncHandler = function ($data) {
221 $replyId = (int) \FluentCart\Framework\Support\Arr::get($data, 'reply_id');
222
223 if (!$replyId) {
224 return;
225 }
226
227 $reply = \FluentCart\App\Models\ProductReview::query()->with('product')->find($replyId);
228
229 if (!$reply || !$reply->parent_id || !$reply->is_admin_reply || $reply->status !== \FluentCart\App\Helpers\Status::REVIEW_APPROVED) {
230 return;
231 }
232
233 $review = \FluentCart\App\Models\ProductReview::query()->find((int) $reply->parent_id);
234
235 if (!$review || $review->parent_id || $review->status !== \FluentCart\App\Helpers\Status::REVIEW_APPROVED) {
236 return;
237 }
238
239 do_action('fluent_cart/review_replied_done', [
240 'reply' => $reply,
241 'review' => $review,
242 'product' => $reply->product,
243 ]);
244 };
245 add_action('fluent_cart/review_replied_async_private_handle', $reviewRepliedAsyncHandler, 1, 1);
246
247
248 //
249 //$app->addAction('fluent_cart/orders_filter_customer', function ($query, $filters) {
250 // return (new \FluentCart\App\Models\Order)->buildCustomerFilterQuery($query, $filters);
251 //}, 10, 2);
252
253 // require the CLI
254 if (defined('WP_CLI') && WP_CLI) {
255 \WP_CLI::add_command('fluent_cart', '\FluentCart\App\Hooks\CLI\Commands');
256
257 }
258
259 \FluentCart\App\Modules\Subscriptions\SubscriptionModule::register();
260 \FluentCart\App\Modules\Shipping\ShippingModule::register();
261 \FluentCart\App\Modules\StoreManagedRenewal\RenewalModule::register();
262 (new \FluentCart\App\Hooks\Handlers\AttributesHandler())->register();
263 (new \FluentCart\App\Hooks\Handlers\AdvancedVariationHandler())->register();
264
265 // MCP (Model Context Protocol) — operator AI tools. Ships OFF; enabled in
266 // Settings → Features & addon → MCP. See MCPInit::boot() for the bootstrap.
267 \FluentCart\App\Modules\MCP\MCPInit::boot();
268
269 $app->ready(function () use ($app) {
270 \FluentCart\App\Models\Connection\ConnectionManager::connect($this->app);
271 });
272
273
274 // Add to your theme's functions.php or a custom plugin
275 // For Elementor preview URL
276
277
278 (new \FluentCart\App\Services\Integration)->register();
279
280 $app->addAction('fluent_cart/integration/schedule_feed', function ($queueId) use ($app) {
281 (new \FluentCart\App\Modules\Integrations\GlobalNotificationHandler())->processIntegrationAction($queueId);
282 });
283
284 // Schedulers
285 (new \FluentCart\App\Hooks\Scheduler\AutoSchedules\FiveMinuteScheduler())->register();
286 (new \FluentCart\App\Hooks\Scheduler\AutoSchedules\HourlyScheduler())->register();
287 (new \FluentCart\App\Hooks\Scheduler\AutoSchedules\DailyScheduler())->register();
288
289
290 /**
291 * Theme Hooks
292 */
293
294 add_action('init', [\FluentCart\App\Modules\Templating\TemplateLoader::class, 'init']);
295 add_action('after_setup_theme', function () {
296 \FluentCart\App\Modules\Templating\TemplateLoader::registerBlockParts();
297 (new \FluentCart\App\Modules\Templating\Bricks\BricksLoader())->register();
298 });
299
300
301 /**
302 * Development Hooks
303 */
304
305 add_action('init', function () {
306 if (!is_admin()) {
307 WebRoutes::renderModalCheckout();
308 }
309 });
310