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

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

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