PluginProbe
FluentCart A New Era of eCommerce – Faster, Lighter, and Simpler / 1.3.20
FluentCart A New Era of eCommerce – Faster, Lighter, and Simpler v1.3.20
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 / CPT / FluentProducts.php

FluentProducts.php in FluentCart A New Era of eCommerce – Faster, Lighter, and Simpler 1.3.20, at app/CPT/FluentProducts.php

405 lines 15.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\CPT;
4
5
6 use FluentCart\Api\StoreSettings;
7 use FluentCart\App\App;
8 use FluentCart\App\Services\URL;
9 use FluentCart\App\Vite;
10 use FluentCart\Framework\Support\Arr;
11
12 class FluentProducts
13 {
14
15 const CPT_NAME = 'fluent-products';
16
17 protected $showStandaloneMenu = false;
18
19 public function register()
20 {
21 add_filter('get_edit_post_link', function ($link, $postId) {
22 if ($this->showStandaloneMenu) {
23 return $link;
24 }
25
26 $post = get_post($postId);
27 if ($post && $post->post_type === 'fluent-products') {
28 return URL::getDashboardUrl('products/' . $postId);
29 }
30
31 return $link;
32 }, 99, 2);
33
34
35 add_action('init', function () {
36
37 $this->showStandaloneMenu = apply_filters('fluent_cart/show_standalone_product_menu', false);
38
39 $this->registerPostType();
40 $this->registerProductTaxonomies();
41 });
42
43 add_action('admin_enqueue_scripts', function () {
44 if ($this->showStandaloneMenu) {
45 return;
46 }
47 $screen = get_current_screen();
48 $isProductEditingScreen = $screen && $screen->post_type === 'fluent-products' && $screen->base === 'post';
49 if (!$isProductEditingScreen) {
50 if ($screen && $screen->post_type === 'fluent-products' && ($screen->base == 'edit-tags' || $screen->base == 'term')) {
51 $this->customizeTaxonomyScreen();
52 }
53 return;
54 }
55
56 // Make sure the default admin styles are enqueued
57 wp_enqueue_style('wp-admin');
58
59 $custom_css =
60 '#editor .editor-sidebar__panel .editor-post-summary .editor-post-trash,' .
61 '#wpadminbar,' .
62 '#adminmenu,' .
63 '#adminmenuback,' .
64 '#adminmenuwrap {' .
65 'display: none !important;' .
66 '}' .
67 '#wpbody-content .interface-interface-skeleton {' .
68 'left: 0 !important;' .
69 'top: 0 !important;' .
70 '}' .
71 '#wpcontent, #wpfooter {' .
72 'margin-left: 0 !important;' .
73 'margin-right: 0 !important;' .
74 '}';
75
76 wp_add_inline_style('wp-admin', $custom_css);
77
78 wp_register_script('fluent-products-inline-js', '', [], FLUENTCART_VERSION, true);
79 wp_enqueue_script('fluent-products-inline-js');
80
81 $custom_js = "window.addEventListener('click', function (event) {
82 const anchor = event.target.closest('a');
83 if (anchor) {
84 event.preventDefault();
85 let href = anchor.getAttribute('href');
86 if (href && href != '#' && !href.startsWith('javascript:')) {
87 window.open(href, '_blank');
88 }
89 }
90 });";
91
92 // wp_add_inline_script('fluent-products-inline-js', $custom_js);
93
94 });
95
96 // add_action('elementor/editor/after_enqueue_scripts', function () {
97 // $this->registerElementorScript();
98 // });
99
100 add_action('enqueue_block_editor_assets', function () {
101 global $post;
102
103 // Only apply to book post type
104 if (!isset($post->post_type) || 'fluent-products' !== $post->post_type) {
105 return;
106 }
107
108
109 wp_add_inline_script(
110 'wp-blocks',
111 "
112 wp.domReady( function() {
113 // Force fullscreen mode
114 wp.data.dispatch( 'core/edit-post' ).toggleFeature( 'fullscreenMode', true );
115
116 // Hide the fullscreen toggle button
117 const style = document.createElement( 'style' );
118 style.textContent = '.edit-post-fullscreen-mode-close, .components-button[aria-label=\"Exit fullscreen\"], .edit-post-fullscreen-mode-close ~ .edit-post-header-toolbar__left button[aria-label=\"Exit fullscreen\"] { display: none !important; }';
119 document.head.appendChild( style );
120 } );
121 "
122 );
123 });
124
125 add_action('update_post_meta', [$this, 'handleThumbChange'], 10, 4);
126 add_action('added_post_meta', [$this, 'handleThumbChange'], 10, 4);
127 }
128
129 public function registerElementorScript()
130 {
131 $custom_js = "console.log('doc ready - editor context');
132
133 // Wait for Elementor editor to be ready
134 jQuery(window).on('elementor:init', () => {
135 console.log('Elementor editor initialized');
136
137 jQuery(document).on('click', '#elementor-editor-wrapper-v2 .MuiButtonGroup-root > button', function() {
138 console.log('Button clicked!', this);
139
140 let content = '';
141
142 try {
143 const previewFrame = jQuery('#elementor-preview-iframe')[0];
144 if (previewFrame && previewFrame.contentDocument) {
145 const previewContent = previewFrame.contentDocument.querySelector('.elementor');
146 if (previewContent) {
147 content = previewContent.outerHTML;
148 console.log('Content from preview frame:', content.substring(0, 200) + '...');
149 }
150 }
151 } catch (e) {
152 console.log('Could not access preview frame:', e);
153 }
154
155 // Fallback: Get structured data
156 if (!content && typeof elementor !== 'undefined') {
157 try {
158 content = JSON.stringify(elementor.documents.currentDocument.container.children.toJSON());
159 } catch (e) {
160 console.log('Could not get elementor data:', e);
161 }
162 }
163
164 // Send message to parent window
165 window.parent.postMessage(
166 {
167 type: 'gutenbergContentChanged',
168 content: content,
169 timestamp: Date.now()
170 },
171 '*'
172 );
173 });
174 });";
175
176 wp_add_inline_script('elementor-editor', $custom_js);
177 }
178
179 public function registerPostType()
180 {
181 $productSlug = (new StoreSettings())->get('product_slug') ?? 'item';
182 $urlSlug = apply_filters('fluent_cart/front_url_slug', $productSlug, []);
183 $urlWithFront = apply_filters('fluent_cart/product_url_with_front', true, [
184 'slug' => $urlSlug
185 ]);
186
187 $singularName = __('Product', 'fluent-cart');
188
189 if (defined('WC_PLUGIN_FILE')) {
190 $singularName = __('Product (FluentCart)', 'fluent-cart');
191 }
192
193 register_post_type(self::CPT_NAME, [
194 'capability_type' => 'post',
195 // 'capabilities' => [
196 // 'edit_post' => 'edit_your_post_type',
197 // 'read_post' => 'read_your_post_type',
198 // 'delete_post' => 'do_not_allow', // block trash/delete
199 // 'edit_posts' => 'edit_your_post_types',
200 // 'edit_others_posts' => 'edit_others_your_post_types',
201 // 'publish_posts' => 'publish_your_post_types',
202 // 'read_private_posts' => 'read_private_your_post_types',
203 // ],
204 // 'map_meta_cap' => true,
205 'label' => __('Products', 'fluent-cart'),
206 'labels' => [
207 'name' => __('Products', 'fluent-cart'),
208 'singular_name' => $singularName,
209 'add_new' => _x('Add New Product', 'product', 'fluent-cart'),
210 'add_new_item' => __('Add New Product', 'fluent-cart'),
211 'edit_item' => __('Edit Product', 'fluent-cart'),
212 'view_item' => __('View Product', 'fluent-cart'),
213 'search_items' => __('Search products', 'fluent-cart'),
214 ],
215 //'_edit_link' => 'admin.php?page=fluent-cart#/products/%d/pricing',
216 'description' => __('FluentCart products post type', 'fluent-cart'),
217 'public' => true,
218 'hierarchical' => false,
219 'exclude_from_search' => false,
220 'publicly_queryable' => true,
221 'show_ui' => true,
222 'show_in_menu' => $this->showStandaloneMenu,
223 'show_in_nav_menus' => true,
224 'show_in_admin_bar' => true,
225 'menu_position' => 24,
226 'has_archive' => true,
227 'show_in_rest' => true,
228 // 'rest_base' => $urlSlug, // Optional: customize REST API base
229 'rest_controller_class' => 'WP_REST_Posts_Controller', // Optional: use default controller
230 'supports' => [
231 'title',
232 'editor',
233 'excerpt',
234 'thumbnail',
235 'author',
236 'revisions',
237 'custom-fields',
238 ],
239 'rewrite' => [
240 'slug' => $urlSlug,
241 'with_front' => $urlWithFront,
242 'feeds' => true,
243 'pages' => true,
244 ],
245 'query_var' => $urlSlug,
246 'can_export' => true,
247 'delete_with_user' => false
248 ]);
249
250 $this->disableCreateAndEditForFluentProducts();
251 }
252
253 public function disableCreateAndEditForFluentProducts()
254 {
255 add_action('admin_init', function () {
256 // return for ajax and rest api
257 if ((defined('DOING_AJAX') && DOING_AJAX) || (defined('REST_REQUEST') && REST_REQUEST)) {
258 return;
259 }
260
261 global $pagenow;
262
263 if ($pagenow != 'post-new.php') {
264 return;
265 }
266
267 // disable direct create product
268 $postType = $_GET['post_type'] ?? '';
269 if ($postType == self::CPT_NAME) {
270 wp_redirect(admin_url('admin.php?page=fluent-cart#/products/?add-new=true'));
271 exit;
272 }
273 });
274 }
275
276 public function registerProductTaxonomies()
277 {
278 register_taxonomy('product-categories', self::CPT_NAME, [
279 'hierarchical' => true,
280 'show_ui' => true,
281 'show_admin_column' => true,
282 'show_in_rest' => true,
283 'query_var' => true,
284 'rewrite' => ['slug' => 'product-categories'],
285 'labels' => [
286 'name' => __('Categories', 'fluent-cart'),
287 'singular_name' => __('Category', 'fluent-cart'),
288 'search_items' => __('Search Categories', 'fluent-cart'),
289 'all_items' => __('All Categories', 'fluent-cart'),
290 'parent_item' => __('Parent Category', 'fluent-cart'),
291 'parent_item_colon' => __('Parent Category:', 'fluent-cart'),
292 'edit_item' => __('Edit Category', 'fluent-cart'),
293 'update_item' => __('Update Category', 'fluent-cart'),
294 'add_new_item' => __('Add New Category', 'fluent-cart'),
295 'new_item_name' => __('New Category Name', 'fluent-cart'),
296 'menu_name' => __('Product Category', 'fluent-cart'),
297 'not_found' => __('No categories found.', 'fluent-cart'),
298 ],
299 ]);
300
301 register_taxonomy('product-brands', self::CPT_NAME, [
302 'hierarchical' => true,
303 'show_ui' => true,
304 'show_in_rest' => true,
305 'show_admin_column' => false,
306 'query_var' => true,
307 'rewrite' => ['slug' => 'product-brands'],
308 'labels' => [
309 'name' => __('Brands', 'fluent-cart'),
310 'singular_name' => __('Brand', 'fluent-cart'),
311 'search_items' => __('All Brand', 'fluent-cart'),
312 'all_items' => __('All Brands', 'fluent-cart'),
313 'parent_item' => __('Parent Brand', 'fluent-cart'),
314 'edit_item' => __('Edit Brand', 'fluent-cart'),
315 'update_item' => __('Update Brand', 'fluent-cart'),
316 'add_new_item' => __('Add New Brand', 'fluent-cart'),
317 'new_item_name' => __('New Brand Name', 'fluent-cart'),
318 'menu_name' => __('Product Brand', 'fluent-cart'),
319 'view_item' => __('View Brand', 'fluent-cart'),
320 'not_found' => __('No Brand found', 'fluent-cart'),
321 ],
322 ]);
323 }
324
325 public function customizeTaxonomyScreen()
326 {
327
328 Vite::enqueueScript('fluent_cart_admin_global_js',
329 'admin/global.js',
330 );
331
332 Vite::enqueueStyle('fluent_cart_admin_app_css',
333 'styles/tailwind/style.css',
334 );
335
336 Vite::enqueueStyle('fluent_cart_taxonomy_css',
337 'styles/tailwind/taxonomy.scss',
338 );
339
340 add_action('in_admin_header', function () {
341 ?>
342 <div style="margin-left: -20px;" class="fc_taxonomy_menu" id="fct_admin_menu_holder">
343 <?php do_action('fluent_cart/admin_menu'); ?>
344 </div>
345 <?php
346 });
347 }
348
349 public function handleThumbChange($meta_id, $object_id, $meta_key, $_meta_value)
350 {
351 if ($meta_key !== '_thumbnail_id') {
352 return;
353 }
354
355
356 $post = get_post($object_id);
357
358
359 if ($post->post_type !== FluentProducts::CPT_NAME) {
360 return;
361 }
362
363
364 //get post meta
365 $oldGallery = get_post_meta($object_id, FluentProducts::CPT_NAME . '-gallery-image', true);
366
367 if (!is_array($oldGallery)) {
368 $oldGallery = [];
369 }
370
371 $currentThumbnailId = $_meta_value;
372
373
374 //get thumbnail image with all info like title id and url
375 $currentThumbnail = wp_prepare_attachment_for_js($currentThumbnailId);
376 $currentThumbnail = [
377 'id' => $currentThumbnailId,
378 'url' => Arr::get($currentThumbnail, 'url'),
379 'name' => Arr::get($currentThumbnail, 'title')
380 ];
381
382 $currentThumbnailId = Arr::get($currentThumbnail, 'id');
383
384
385 $found = false;
386 $index = 0;
387 foreach ($oldGallery as $index => $image) {
388 if ($image['id'] == $currentThumbnailId) {
389 $found = true;
390 break;
391 }
392 }
393
394
395 //if found bring it on top
396 if ($found) {
397 unset($oldGallery[$index]);
398 array_unshift($oldGallery, $image);
399 } else {
400 array_unshift($oldGallery, $currentThumbnail);
401 }
402 update_post_meta($object_id, FluentProducts::CPT_NAME . '-gallery-image', $oldGallery);
403 }
404 }
405