PluginProbe
FluentCart A New Era of eCommerce – Faster, Lighter, and Simpler / 1.5.1
FluentCart A New Era of eCommerce – Faster, Lighter, and Simpler v1.5.1
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 trunk All 48 releases
fluent-cart / app / Modules / Templating / Bricks / BricksLoader.php

BricksLoader.php in FluentCart A New Era of eCommerce – Faster, Lighter, and Simpler 1.5.1, at app/Modules/Templating/Bricks/BricksLoader.php

204 lines 6.2 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\Modules\Templating\Bricks;
4
5 use Bricks\Elements;
6 use FluentCart\Framework\Support\Arr;
7 use FluentCart\App\Models\Product;
8
9 class BricksLoader
10 {
11 public function register()
12 {
13 if (!defined('BRICKS_VERSION')) {
14 return;
15 }
16
17 add_action('init', [$this, 'loadElements'], 20);
18
19 (new DynamicData())->register();
20
21 add_action('wp_footer', [$this, 'addDynamicFieldClassesScript']);
22
23 add_filter('fluent_cart/template/disable_taxonomy_fallback', function ($result) {
24 $bricks_data = \Bricks\Database::get_template_data('archive');
25
26 if ($bricks_data) {
27 return true;
28 }
29
30 return $result;
31 });
32
33 add_filter('fluent_cart/products_views/preload_collection_bricks', [$this, 'preloadProductCollectionsAjax'], 10, 2);
34
35 }
36
37 public function loadElements()
38 {
39 $elements = [
40 'ProductTitle' => 'fct-product-title',
41 'ProductShortDescription' => 'fct-product-short-description',
42 'ProductContent' => 'fct-product-content',
43 'ProductStock' => 'fct-product-stock',
44 'PriceRange' => 'fct-price-range',
45 'BuySection' => 'fct-product-buy-section',
46 'ProductGallery' => 'fct-product-gallery',
47 'ProductsCollection' => 'fct-products',
48 ];
49
50 foreach ($elements as $elementKey => $elementName) {
51 $elementFile = FLUENTCART_PLUGIN_PATH . "app/Modules/Templating/Bricks/Elements/$elementKey.php";
52 $className = "\\FluentCart\\App\\Modules\\Templating\\Bricks\\Elements\\$elementKey";
53 Elements::register_element($elementFile, $elementName, $className);
54 }
55
56 }
57
58 public function preloadProductCollectionsAjax($view, $args)
59 {
60 $products = $args['products'];
61 $clientId = Arr::get($args, 'client_id', '');
62
63 $settings = get_transient('fc_bx_collection_' . $clientId);
64 if (!$settings) {
65 return $view;
66 }
67
68 do_action('fluent_cart/bricks/rendering_ajax_collection');
69
70 ob_start();
71 $post_index = 1;
72
73 foreach ($products as $product) {
74 $post = get_post($product->ID);
75 setup_postdata($post);
76 BricksHelper::setFormCurrentPost($post);
77 BricksHelper::renderCollectionCard($settings, $product, $post_index, $clientId);
78
79 $post_index++;
80 }
81 wp_reset_postdata();
82
83 return ob_get_clean();
84 }
85
86 public function addDynamicFieldClassesScript()
87 {
88 ?>
89 <script>
90 document.addEventListener('DOMContentLoaded', function() {
91 const classMap = {
92 'product-title': 'fct-dynamic-product-title',
93 'product-image': 'fct-dynamic-product-image',
94 'product-excerpt': 'fct-dynamic-product-excerpt',
95 'product-price': 'fct-dynamic-product-price',
96 'product-button': 'fct-dynamic-product-button'
97 };
98
99 const applyDynamicFieldClass = function(marker) {
100 if (marker.hasAttribute('data-fct-field-class-applied')) {
101 return;
102 }
103
104 const className = classMap[marker.getAttribute('data-fct-field')];
105
106 if (!className) {
107 marker.setAttribute('data-fct-field-class-applied', '1');
108 return;
109 }
110
111 let dynamicDiv = marker.closest('.dynamic');
112
113 if (!dynamicDiv) {
114 dynamicDiv = marker.parentElement;
115 while (dynamicDiv && !dynamicDiv.classList.contains('dynamic')) {
116 dynamicDiv = dynamicDiv.parentElement;
117 }
118 }
119
120 if (dynamicDiv) {
121 dynamicDiv.classList.add(className);
122 }
123
124 marker.setAttribute('data-fct-field-class-applied', '1');
125 };
126
127 let scheduled = false;
128 const pendingNodes = new Set();
129
130 const processNode = function(node) {
131 if (!node || node.nodeType !== 1) {
132 return;
133 }
134
135 const markers = node.matches('[data-fct-field]')
136 ? [node]
137 : node.querySelectorAll('[data-fct-field]');
138
139 markers.forEach(applyDynamicFieldClass);
140 };
141
142 const scheduleNode = function(node) {
143 pendingNodes.add(node);
144
145 if (scheduled) {
146 return;
147 }
148
149 scheduled = true;
150 requestAnimationFrame(function() {
151 pendingNodes.forEach(processNode);
152 pendingNodes.clear();
153 scheduled = false;
154 });
155 };
156
157 document.querySelectorAll('[data-fluent-cart-shop-app-product-list]').forEach(function(productList) {
158 processNode(productList);
159
160 new MutationObserver(function(mutations) {
161 mutations.forEach(function(mutation) {
162 mutation.addedNodes.forEach(scheduleNode);
163 });
164 }).observe(productList, {
165 childList: true,
166 subtree: true
167 });
168 });
169 });
170 </script>
171 <?php
172 }
173
174 /**
175 * Get product options for select controls.
176 * Limits to 50 recent products for editor performance.
177 * Users can search or use manual product ID for others.
178 */
179 public static function getProductOptions()
180 {
181 if (!class_exists('\FluentCart\App\Models\Product')) {
182 return [];
183 }
184
185 $options = [];
186
187 try {
188 $products = Product::query()
189 ->where('post_status', 'publish')
190 ->orderBy('post_date', 'DESC')
191 ->limit(50)
192 ->get();
193
194 foreach ($products as $product) {
195 $options[$product->ID] = $product->post_title;
196 }
197 } catch (\Exception $e) {
198 // Silently fail if models aren't available
199 }
200
201 return $options;
202 }
203 }
204