PluginProbe
WowAddons – Product Addons and Product Options With Custom Fields / trunk
WowAddons – Product Addons and Product Options With Custom Fields vtrunk
1.7.2 1.7.1 1.7.0 1.6.21 1.6.20 1.6.19 1.6.18 1.6.17 1.6.16 1.6.15 1.6.14 1.6.13 1.6.12 1.6.11 1.6.10 1.6.9 1.6.8 1.6.7 1.6.6 1.5.10 1.5.11 1.5.2 1.5.3 1.5.4 1.5.5 All 57 releases
product-addons / includes / blocks / class-render-product-fields.php

class-render-product-fields.php in WowAddons – Product Addons and Product Options With Custom Fields trunk, at includes/blocks/class-render-product-fields.php

324 lines 9.4 KB
No matching file
Up and down to move Enter to open Esc to close
Raw Download Zip
1 <?php //phpcs:ignore
2 /**
3 * Main Render Blocks Controller
4 *
5 * @package PRAD
6 * @since 1.0.0
7 */
8
9 namespace PRAD\Includes\Blocks;
10
11 use PRAD\Includes\Blocks\Renderers\Block_Renderer;
12 use PRAD\Includes\Services\Product_Blocks_Service;
13 use PRAD\Includes\Xpo;
14
15 defined( 'ABSPATH' ) || exit;
16
17 /**
18 * Main Render Blocks Class
19 */
20 class Render_Product_Fields {
21
22 /**
23 * Block renderer instance
24 *
25 * @var Block_Renderer
26 */
27 private Block_Renderer $renderer;
28
29 /**
30 * Product blocks service
31 *
32 * @var Product_Blocks_Service
33 */
34 private Product_Blocks_Service $blocks_service;
35
36 /**
37 * Constructor
38 */
39 public function __construct() {
40 $this->renderer = new Block_Renderer();
41 $this->blocks_service = new Product_Blocks_Service();
42
43 $this->init_hooks();
44 }
45
46 /**
47 * Initialize WordPress hooks
48 */
49 private function init_hooks(): void {
50 add_action( 'woocommerce_before_add_to_cart_button', array( $this, 'before_add_to_cart_button' ), 100 );
51 add_filter( 'woocommerce_product_get_gallery_image_ids', array( $this, 'prad_add_custom_gallery_image' ), 99, 2 );
52 }
53
54 /**
55 * Render blocks before add to cart button
56 */
57 public function before_add_to_cart_button(): void {
58 global $product;
59
60 if ( ! $product || ! is_a( $product, 'WC_Product' ) ) {
61 return;
62 }
63
64 $product_id = $product->get_id();
65 $blocks_data = $this->blocks_service->get_product_blocks_data( $product_id );
66
67 if ( empty( $blocks_data['blocks'] ) ) {
68 return;
69 }
70
71 // Enqueue necessary assets.
72 // $this->assets->enqueue_frontend_assets();.
73 do_action( 'prad_enqueue_block_css' );
74 do_action( 'prad_enqueue_block_js' );
75 if ( wp_doing_ajax() || wp_is_serving_rest_request() ) {
76 do_action( 'prad_load_script_on_ajax' );
77 }
78
79 // Render the complete addon wrapper.
80 echo $this->render_addon_wrapper( $product, $blocks_data ); // phpcs:ignore WordPress.Security.EscapeOutput.OutputNotEscaped
81 }
82
83 /**
84 * Render complete addon wrapper.
85 *
86 * @param \WC_Product $product Product object.
87 * @param array $blocks_data Blocks data array.
88 * @return string HTML output.
89 */
90 private function render_addon_wrapper( $product, array $blocks_data ): string {
91 $product_id = $product->get_id();
92 $prad_new_style_enabled = get_option( 'prad_global_style_thematic_css', '' );
93 $html = '<div class="prad-addons-wrapper prad-loading' . ( $prad_new_style_enabled ? ' prad-thematic-style' : '' ) . '">';
94 $html .= '<div class="prad-loader"></div>';
95
96 // Hidden fields for price calculation.
97 $html .= $this->render_hidden_fields( $product, $blocks_data );
98
99 // Render blocks.
100 foreach ( $blocks_data['blocks'] as $addon_id => $addon_blocks ) {
101 $html .= sprintf(
102 '<div class="prad-blocks-container prad-relative prad-mb-24" data-productid="%s" data-optionid="%s">',
103 esc_attr( $product_id ),
104 esc_attr( $addon_id )
105 );
106
107 // Edit link for administrators.
108 if ( current_user_can( Xpo::prad_old_view_permisson_handler() ) ) {
109 $html .= sprintf(
110 '<a class="prad-absolute prad-fron-edit-addon prad-z-99" target="_blank" href="%s">%s</a>',
111 esc_url( admin_url( 'admin.php?page=prad-dashboard#lists/' . $addon_id ) ),
112 esc_html__( 'Edit Addon', 'product-addons' )
113 );
114 }
115
116 // Render addon blocks.
117 $html .= $this->renderer->render_blocks( $addon_blocks, $product_id );
118
119 $html .= '</div>';
120 }
121
122 // Price summary.
123 $html .= $this->render_price_summary( $product );
124
125 $html .= '</div>';
126
127 return $html;
128 }
129
130 /**
131 * Render hidden fields for JavaScript functionality.
132 *
133 * @param \WC_Product $product Product object.
134 * @param array $blocks_data Blocks data array.
135 * @return string HTML output.
136 */
137 private function render_hidden_fields( $product, array $blocks_data ): string {
138 $product_id = $product->get_id();
139
140 // Get price data.
141 $price_data = $this->blocks_service->get_product_price_data( $product );
142
143 $html = '';
144
145 if ( $product->has_attributes() ) {
146 $attributes = $product->get_attributes();
147 $product_type = $product->get_type();
148
149 if ( ! empty( $attributes ) ) {
150 $data_attributes = array();
151
152 foreach ( $attributes as $attribute ) {
153 $attribute_name = $attribute->get_name();
154 if ( $attribute->is_taxonomy() ) {
155 $terms = wc_get_product_terms(
156 $product->get_id(),
157 $attribute_name,
158 array( 'fields' => 'all' )
159 );
160 foreach ( $terms as $term ) {
161 $data_attributes[ $attribute_name ][ $term->slug ] = (int) $term->term_id;
162 }
163 }
164 }
165 $html .= sprintf(
166 '<span class="prad-field-none" id="prad-product-attributes" data-product-type="%s" data-attributes="%s"></span>',
167 esc_attr( $product_type ),
168 esc_attr( wp_json_encode( $data_attributes ) )
169 );
170 }
171 }
172
173 // Variations data for variable products.
174 if ( ! empty( $price_data['variations'] ) ) {
175 $html .= sprintf(
176 '<span class="prad-field-none" id="prad_variations_list" data-variations="%s"></span>',
177 esc_attr( wp_json_encode( $price_data['variations'] ) )
178 );
179
180 $html .= sprintf(
181 '<span class="prad-field-none" id="prad_variations_list_percentage" data-variations="%s"></span>',
182 esc_attr( wp_json_encode( $price_data['variations_percentage'] ) )
183 );
184 }
185
186 // Base price data.
187 $html .= sprintf(
188 '<span class="prad-field-none" id="prad_base_price">%s</span>',
189 esc_html( $price_data['base_price'] )
190 );
191
192 $html .= sprintf(
193 '<span class="prad-field-none" id="prad_base_price_percentage">%s</span>',
194 esc_html( $price_data['base_price_percentage'] )
195 );
196
197 // Hidden form fields.
198 $html .= '<input type="hidden" name="prad_selection" id="prad_selection" />';
199 $html .= '<input type="hidden" name="prad_products_selection" id="prad_products_selection" />';
200
201 $product_dynamic_data = array(
202 'product_weight' => $product->get_weight() ?? 0,
203 'product_length' => $product->get_length() ?? 0,
204 'product_width' => $product->get_width() ?? 0,
205 'product_height' => $product->get_height() ?? 0,
206 );
207
208 $html .= sprintf(
209 '<input type="hidden" name="prad_product_shipping_dynamic" id="prad_product_shipping_dynamic" value="%s" />',
210 esc_attr( wp_json_encode( $product_dynamic_data ) )
211 );
212
213 $html .= sprintf(
214 '<input type="hidden" name="prad_option_published_ids" id="prad_option_published_ids" value="%s"/>',
215 esc_attr( wp_json_encode( $blocks_data['published_ids'] ) )
216 );
217
218 return $html;
219 }
220
221 /**
222 * Render price summary section.
223 *
224 * @param \WC_Product $product Product object.
225 * @return string HTML output.
226 */
227 private function render_price_summary( $product ): string {
228 $base_price = $this->blocks_service->get_product_base_price( $product );
229 $enable_addons_price = Xpo::get_prad_settings_item( 'enableAddonsPriceText', true );
230 $enable_addons_price_total = Xpo::get_prad_settings_item( 'enableAddonsPriceTotalText', true );
231 if ( false === $enable_addons_price && false === $enable_addons_price_total ) {
232 return '';
233 }
234
235 $addons_label = esc_html( Xpo::get_prad_settings_item( 'addonsPriceText', 'Addons Price' ) );
236 $total_label = esc_html( Xpo::get_prad_settings_item( 'totalPriceText', 'Total Price' ) );
237
238 $addons_price_html = sprintf(
239 '<div class="prad-price-row">
240 <strong class="prad-label">%s:</strong>
241 <span id="prad_option_price" class="prad-value">%s</span>
242 </div>',
243 $addons_label,
244 wc_price( 0 )
245 );
246
247 $total_price_html = sprintf(
248 '<div class="prad-price-row">
249 <strong class="prad-label">%s:</strong>
250 <span id="prad_option_total_price" class="prad-value">%s</span>
251 </div>',
252 $total_label,
253 wc_price( $base_price )
254 );
255
256 if ( false === $enable_addons_price ) {
257 $addons_price_html = '';
258 }
259 if ( false === $enable_addons_price_total ) {
260 $total_price_html = '';
261 }
262
263 return sprintf(
264 '<div class="prad-product-price-summary prad-mt-48">%s%s</div>',
265 $addons_price_html,
266 $total_price_html
267 );
268 }
269
270 /**
271 * Get blocks for a specific product (public method for external access).
272 *
273 * @param int $product_id Product ID.
274 * @return array Blocks data array.
275 */
276 public function get_product_blocks( int $product_id ): array {
277 return $this->blocks_service->get_product_blocks_data( $product_id );
278 }
279
280 /**
281 * Render blocks programmatically (for use in other contexts).
282 *
283 * @param array $blocks_data Blocks data array.
284 * @param int $product_id Product ID.
285 * @return string HTML output.
286 */
287 public function render_blocks_html( array $blocks_data, int $product_id ): string {
288 return $this->renderer->render_blocks( $blocks_data, $product_id );
289 }
290
291 /**
292 * Add custom gallery images for product blocks.
293 *
294 * @param array $gallery_image_ids Gallery image IDs.
295 * @param \WC_Product $product Product object.
296 * @return array Modified gallery image IDs.
297 */
298 public function prad_add_custom_gallery_image( $gallery_image_ids, $product ) {
299 if ( is_product() ) {
300 $published_options = $this->blocks_service->get_product_blocks_data( $product->get_id() );
301 if ( empty( $published_options['published_ids'] ) ) {
302 return $gallery_image_ids;
303 }
304
305 $image_data = get_option( 'prad_product_image_update_data', array() );
306 if ( empty( $image_data ) ) {
307 return $gallery_image_ids;
308 }
309
310 $custom_image_id = array();
311 foreach ( $image_data as $k => $ids ) {
312 if ( in_array( $k, $published_options['published_ids'] ) ) {
313 $custom_image_id = array_merge( $custom_image_id, $ids );
314 }
315 }
316
317 $gallery_image_ids = array_values( array_unique( array_merge( $gallery_image_ids, $custom_image_id ) ) );
318
319 }
320
321 return $gallery_image_ids;
322 }
323 }
324