PluginProbe
FluentCart A New Era of eCommerce – Faster, Lighter, and Simpler / 1.6.4
FluentCart A New Era of eCommerce – Faster, Lighter, and Simpler v1.6.4
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 1.2.0 All 47 releases
fluent-cart / app / Modules / Templating / BlockTemplates / TemplateParts / ProductModalTemplatePart.php

ProductModalTemplatePart.php in FluentCart A New Era of eCommerce – Faster, Lighter, and Simpler 1.6.4, at app/Modules/Templating/BlockTemplates/TemplateParts/ProductModalTemplatePart.php

371 lines 10.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\Modules\Templating\BlockTemplates\TemplateParts;
4
5 class ProductModalTemplatePart
6 {
7 /**
8 * The slug of the template part.
9 *
10 * @var string
11 */
12 const SLUG = 'product-modal';
13
14 /**
15 * The area of the template part.
16 *
17 * @var string
18 */
19 const AREA = 'uncategorized';
20
21 /**
22 * Plugin namespace for template parts.
23 *
24 * @var string
25 */
26 const PLUGIN_NAMESPACE = 'fluent-cart';
27
28 /**
29 * Initialization method.
30 */
31 public function init()
32 {
33 add_action('init', [$this, 'register']);
34 }
35
36 /**
37 * Register the template part.
38 */
39 public function register()
40 {
41
42
43
44 add_filter('get_block_templates', [$this, 'addTemplatePart'], 10, 3);
45 add_filter('pre_get_block_file_template', [$this, 'getTemplatePart'], 10, 3);
46 }
47
48 /**
49 * Add the template part to the list of available template parts.
50 *
51 * @param array $query_result Array of found block templates.
52 * @param array $query Arguments to retrieve templates.
53 * @param string $template_type wp_template or wp_template_part.
54 * @return array Modified array of block templates.
55 */
56 public function addTemplatePart($query_result, $query, $template_type)
57 {
58 if ('wp_template_part' !== $template_type) {
59 return $query_result;
60 }
61
62 // dd($query_result);
63
64 // Check if our template part is already in the results
65 $template_id = $this->getTemplatePartId();
66 foreach ($query_result as $template) {
67 if ($template->id === $template_id) {
68 return $query_result;
69 }
70 }
71
72 // Create the template part object
73 $template_part = $this->buildTemplatePartObject();
74
75 $query_result[] = $template_part;
76
77 return $query_result;
78 }
79
80 /**
81 * Get template part when requested.
82 *
83 * @param \WP_Block_Template|null $template Block template object.
84 * @param string $id Template unique identifier.
85 * @param string $template_type Template type.
86 * @return \WP_Block_Template|null
87 */
88 public function getTemplatePart($template, $id, $template_type)
89 {
90 if ('wp_template_part' !== $template_type) {
91 return $template;
92 }
93
94 if ($this->getTemplatePartId() !== $id) {
95 return $template;
96 }
97
98 return $this->buildTemplatePartObject();
99 }
100
101 /**
102 * Build the template part object.
103 *
104 * @return \WP_Block_Template
105 */
106 private function buildTemplatePartObject()
107 {
108 $template_part = new \WP_Block_Template();
109 $template_part->type = 'wp_template_part';
110 $template_part->theme = get_stylesheet(); // Use current theme
111 $template_part->slug = self::SLUG;
112 $template_part->id = $this->getTemplatePartId();
113 $template_part->title = $this->getTitle();
114 $template_part->description = $this->getDescription();
115 $template_part->content = $this->getDefaultTemplate();
116 $template_part->source = 'plugin';
117 $template_part->origin = 'plugin';
118 $template_part->status = 'publish';
119 $template_part->has_theme_file = false;
120 $template_part->is_custom = true;
121 $template_part->area = self::AREA;
122 $template_part->post_types = [];
123 $template_part->plugin = self::PLUGIN_NAMESPACE;
124
125 return $template_part;
126 }
127
128 /**
129 * Returns the title of the template part.
130 *
131 * @return string
132 */
133 public function getTitle()
134 {
135 return _x('Product Modal', 'Template part name', 'fluent-cart');
136 }
137
138 /**
139 * Returns the description of the template part.
140 *
141 * @return string
142 */
143 public function getDescription()
144 {
145 return __('Editable template part for Single Product Modal.', 'fluent-cart');
146 }
147
148 /**
149 * Returns the default template content.
150 *
151 * @return string
152 */
153 public function getDefaultTemplate()
154 {
155 ob_start();
156 ?>
157 <!-- wp:group {"templateLock":"contentOnly","tagName":"main","className":"alignfull is-style-default","layout":{"type":"default"}} -->
158 <main class="wp-block-group alignfull is-style-default">
159 <!-- wp:group {"lock":{"move":true,"remove":true},"align":"wide","layout":{"type":"default"}} -->
160 <div class="wp-block-group alignwide">
161 <!-- wp:shortcode {"lock":{"move":true,"remove":true}} -->
162 [fluent_cart_product_header]
163 <!-- /wp:shortcode -->
164 </div>
165 <!-- /wp:group -->
166
167 <!-- wp:paragraph {"placeholder":"Add your content here..."} -->
168 <p></p>
169 <!-- /wp:paragraph -->
170 </main>
171 <!-- /wp:group -->
172 <?php
173 return ob_get_clean();
174 }
175
176 /**
177 * Get the current content of the template part (including user modifications).
178 *
179 * @return string|null
180 */
181 public function getTemplateContent()
182 {
183 // First, try to get the user-customized version from the database
184 $template_part_post = $this->getTemplatePartPost();
185
186 if ($template_part_post && !empty($template_part_post->post_content)) {
187 return $template_part_post->post_content;
188 }
189
190 // Fall back to default template
191 return $this->getDefaultTemplate();
192 }
193
194 /**
195 * Get the template part post from the database.
196 *
197 * @return \WP_Post|null
198 */
199 private function getTemplatePartPost()
200 {
201 $args = [
202 'post_type' => 'wp_template_part',
203 'post_status' => ['publish', 'auto-draft'],
204 'title' => $this->getTitle(),
205 'posts_per_page' => 1,
206 'no_found_rows' => true,
207 'update_post_meta_cache' => false,
208 'update_post_term_cache' => false,
209 ];
210
211 // Try to find by slug first
212 $args['name'] = self::SLUG;
213 $query = new \WP_Query($args);
214
215 if ($query->have_posts()) {
216 return $query->posts[0];
217 }
218
219 // Also check with theme-specific slug
220 $args['name'] = get_stylesheet() . '//' . self::SLUG;
221 $query = new \WP_Query($args);
222
223 if ($query->have_posts()) {
224 return $query->posts[0];
225 }
226
227 return null;
228 }
229
230 /**
231 * Render the template part with current content (including user customizations).
232 *
233 * @param array $args Optional arguments to pass to the template part.
234 * @return string Rendered HTML output.
235 */
236 public function render($args = [])
237 {
238 $content = $this->getTemplateContent();
239
240 if (empty($content)) {
241 return '';
242 }
243
244 // Apply filters before rendering (allows other plugins to modify)
245 $content = apply_filters('fluent_cart/template_part_content', $content, self::SLUG, $args);
246 $content = apply_filters('fluent_cart/template_part_content_' . self::SLUG, $content, $args);
247
248 // Parse and render blocks
249 $output = do_blocks($content);
250
251 // Apply filters after rendering
252 $output = apply_filters('fluent_cart/template_part_output', $output, self::SLUG, $args);
253 $output = apply_filters('fluent_cart/template_part_output_' . self::SLUG, $output, $args);
254
255 return $output;
256 }
257
258 /**
259 * Render the template part and echo it.
260 *
261 * @param array $args Optional arguments to pass to the template part.
262 */
263 public function display($args = [])
264 {
265 // phpcs:ignore WordPress.Security.EscapeOutput.OutputNotEscaped -- escaped in render method
266 echo $this->render($args);
267 }
268
269 /**
270 * Get the template part ID.
271 *
272 * @return string
273 */
274 public function getTemplatePartId()
275 {
276 return get_stylesheet() . '//' . self::SLUG;
277 }
278
279 /**
280 * Check if the template part has been customized by the user.
281 *
282 * @return bool
283 */
284 public function isCustomized()
285 {
286 $template_part_post = $this->getTemplatePartPost();
287 return !is_null($template_part_post);
288 }
289
290 /**
291 * Reset the template part to default (remove customizations).
292 *
293 * @return bool True on success, false on failure.
294 */
295 public function resetToDefault()
296 {
297 $template_part_post = $this->getTemplatePartPost();
298
299 if ($template_part_post) {
300 $result = wp_delete_post($template_part_post->ID, true);
301
302 if ($result) {
303 // Clear any caches
304 wp_cache_delete('get_block_templates', 'block_templates');
305 return true;
306 }
307
308 return false;
309 }
310
311 return true; // Already at default
312 }
313
314 /**
315 * Export the template part content (for backup or migration).
316 *
317 * @return array
318 */
319 public function export()
320 {
321 return [
322 'slug' => self::SLUG,
323 'title' => $this->getTitle(),
324 'description' => $this->getDescription(),
325 'content' => $this->getTemplateContent(),
326 'is_custom' => $this->isCustomized(),
327 'plugin' => self::PLUGIN_NAMESPACE,
328 ];
329 }
330
331 /**
332 * Import template part content.
333 *
334 * @param string $content The template content to import.
335 * @return bool|\WP_Error True on success, WP_Error on failure.
336 */
337 public function import($content)
338 {
339 if (empty($content)) {
340 return new \WP_Error('empty_content', __('Template content cannot be empty.', 'fluent-cart'));
341 }
342
343 // Delete existing customization
344 $this->resetToDefault();
345
346 // Create new template part post
347 $post_data = [
348 'post_type' => 'wp_template_part',
349 'post_status' => 'publish',
350 'post_title' => $this->getTitle(),
351 'post_name' => self::SLUG,
352 'post_content' => $content,
353 'tax_input' => [
354 'wp_theme' => [get_stylesheet()],
355 'wp_template_part_area' => [self::AREA],
356 ],
357 ];
358
359 $post_id = wp_insert_post($post_data, true);
360
361 if (is_wp_error($post_id)) {
362 return $post_id;
363 }
364
365 // Clear caches
366 wp_cache_delete('get_block_templates', 'block_templates');
367
368 return true;
369 }
370 }
371