PluginProbe
FluentCart A New Era of eCommerce – Faster, Lighter, and Simpler / 1.6.5
FluentCart A New Era of eCommerce – Faster, Lighter, and Simpler v1.6.5
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 1.3.19 All 49 releases
fluent-cart / app / Hooks / Handlers / BlockEditors / Cart / CartBlockEditor.php

CartBlockEditor.php in FluentCart A New Era of eCommerce – Faster, Lighter, and Simpler 1.6.5, at app/Hooks/Handlers/BlockEditors/Cart/CartBlockEditor.php

155 lines 5.1 KB
No matching file
Up and down to move Enter to open Esc to close
Raw Download Zip
1 <?php
2
3 namespace FluentCart\App\Hooks\Handlers\BlockEditors\Cart;
4
5 use FluentCart\App\Helpers\CartHelper;
6 use FluentCart\App\Hooks\Cart\CartLoader;
7 use FluentCart\App\Hooks\Handlers\BlockEditors\BlockEditor;
8 use FluentCart\App\Hooks\Handlers\BlockEditors\Cart\InnerBlocks\InnerBlocks;
9 use FluentCart\App\Modules\Templating\AssetLoader;
10 use FluentCart\App\Services\Renderer\CartRenderer;
11 use FluentCart\App\Services\Translations\TransStrings;
12 use FluentCart\App\Vite;
13
14 /**
15 * Container block for the cart page.
16 *
17 * Composes the cart out of three child blocks (items, totals, checkout button)
18 * rather than emitting one fixed lump of markup, so an editor can reorder the
19 * regions or drop their own blocks between them — the same shape the Checkout
20 * block uses. The empty-cart state stays in the container: it replaces every
21 * region at once, so no individual child owns it.
22 */
23 class CartBlockEditor extends BlockEditor
24 {
25 protected static string $editorName = 'cart';
26
27 public function init(): void
28 {
29 parent::init();
30
31 InnerBlocks::register();
32 }
33
34 public function getScripts(): array
35 {
36 return [
37 [
38 'source' => 'admin/BlockEditor/Cart/CartBlockEditor.jsx',
39 'dependencies' => ['wp-blocks', 'wp-components']
40 ]
41 ];
42 }
43
44 public function getStyles(): array
45 {
46 return [
47 'admin/BlockEditor/Cart/style/cart-block-editor.scss'
48 ];
49 }
50
51 /**
52 * No style supports.
53 *
54 * The cart's appearance is owned end to end by core's cart stylesheet, which
55 * this block and the [fluent_cart_cart] shortcode both render through. Any
56 * block support would layer wrapper-level colour, spacing or border on top
57 * of that and let a page drift away from the shipped design, so the Styles
58 * tab is deliberately empty. `html => false` is a capability switch, not a
59 * style; `align` is placement, and it is what lets the cart go full width.
60 */
61 public function supports(): array
62 {
63 return [
64 'html' => false,
65 'align' => ['wide', 'full'],
66 ];
67 }
68
69 /**
70 * The container renders its children itself so it can wrap them in the
71 * cart section and short-circuit to the empty state.
72 */
73 protected function skipInnerBlocks(): bool
74 {
75 return true;
76 }
77
78 public function localizeData(): array
79 {
80 return [
81 $this->getLocalizationKey() => [
82 'slug' => $this->slugPrefix,
83 'name' => static::getEditorName(),
84 'title' => __('Cart', 'fluent-cart'),
85 'description' => __('This block will display the shopping cart.', 'fluent-cart'),
86 'placeholder_image' => Vite::getAssetUrl('images/placeholder.svg'),
87 ],
88 'fluent_cart_block_translation' => TransStrings::blockStrings(),
89 ];
90 }
91
92 public function render(array $shortCodeAttribute, $block = null)
93 {
94 (new CartLoader())->registerDependency();
95 AssetLoader::markFrontendAssetsRequired();
96
97 $cart = CartHelper::getCart();
98 $cartItems = $cart->cart_data ?? [];
99 $renderer = new CartRenderer($cartItems);
100
101 ob_start();
102
103 if (!$cart || !$cart->cart_data) {
104 $renderer->renderEmpty();
105 } else {
106 // Coupons can expire or stop qualifying between add-to-cart and this
107 // page view; the shortcode revalidates for the same reason.
108 $cart->reValidateCoupons();
109
110 $hasInnerBlocks = $block instanceof \WP_Block && !empty($block->inner_blocks);
111
112 if ($hasInnerBlocks) {
113 $this->renderRegions($block);
114 } else {
115 // No children: a bare <!-- wp:fluent-cart/cart /--> (inserted by
116 // a pattern or left behind after the regions were deleted) must
117 // still show a usable cart, not an empty box. CartRenderer emits
118 // its own section wrapper, so nothing is added around it here.
119 $renderer->render();
120 }
121 }
122
123 return sprintf(
124 '<div %s>%s</div>',
125 get_block_wrapper_attributes(['class' => 'fct-cart-block']),
126 ob_get_clean()
127 );
128 }
129
130 /**
131 * Wrap the child regions in the cart section.
132 *
133 * Labelled with aria-label rather than CartRenderer's aria-labelledby +
134 * screen-reader heading: that markup hardcodes id="fct-cart-page-title", so
135 * reusing it would emit a duplicate id whenever a page holds two carts, or a
136 * cart block alongside the [fluent_cart_cart] shortcode.
137 *
138 * @param \WP_Block $block
139 * @return void
140 */
141 private function renderRegions($block)
142 {
143 ?>
144 <section class="fct-cart-page" role="region"
145 aria-label="<?php esc_attr_e('Your Shopping Cart', 'fluent-cart'); ?>">
146 <?php
147 foreach ($block->inner_blocks as $innerBlock) {
148 echo $innerBlock->render(); // phpcs:ignore WordPress.Security.EscapeOutput.OutputNotEscaped
149 }
150 ?>
151 </section>
152 <?php
153 }
154 }
155