'dprcu_model_texture', 'posts_per_page' => -1, 'orderby' => 'title', 'order' => 'ASC', ) ); $data = array(); foreach ( $posts as $p ) { $terms = get_the_terms( $p->ID, 'dprcu_texture_category' ); $cats = array(); if ( $terms && !is_wp_error( $terms ) ) { foreach ( $terms as $term ) { $cats[] = array( 'id' => $term->term_id, 'name' => $term->name, ); } } $data[] = array( 'id' => $p->ID, 'name' => $p->post_title, 'img' => ( get_the_post_thumbnail_url( $p->ID, 'thumbnail' ) ? get_the_post_thumbnail_url( $p->ID, 'thumbnail' ) : '' ), 'color' => ( get_post_meta( $p->ID, '_dprcu_texture_color', true ) ? get_post_meta( $p->ID, '_dprcu_texture_color', true ) : '' ), 'categories' => $cats, ); } // Cache for one hour; cleared by dprcu_bust_textures_cache() below. set_transient( $cache_key, $data, HOUR_IN_SECONDS ); return $data; } /** * Busts the texture list transient whenever a model_texture is saved or deleted. * * @param int $post_id Post ID. */ function dprcu_bust_textures_cache( $post_id ) { if ( 'dprcu_model_texture' === get_post_type( $post_id ) ) { delete_transient( 'dprcu_all_textures' ); } } add_action( 'save_post', 'dprcu_bust_textures_cache' ); add_action( 'delete_post', 'dprcu_bust_textures_cache' ); function dprcu_metabox_html( $post ) { $model_url = get_post_meta( $post->ID, '_dprcu_3d_model_url', true ); $viewer_only = get_post_meta( $post->ID, '_dprcu_3d_viewer_only', true ); $config_json = get_post_meta( $post->ID, '_dprcu_customizer_config', true ); $steps_data = ( $config_json ? json_decode( $config_json, true ) : array() ); $camera_pos = get_post_meta( $post->ID, '_dprcu_camera_position', true ); wp_nonce_field( 'dprcu_save_metabox', 'dprcu_metabox_nonce' ); ?>

$step ) { ?>
☰
Icon Preview

$option ) { $tex_ids_raw = $option['texture_ids'] ?? $option['texture_id'] ?? ''; $tex_ids = ( is_array( $tex_ids_raw ) ? $tex_ids_raw : array_filter( explode( ',', $tex_ids_raw ) ) ); ?>
☰
Icon Preview Icon Preview
×
can_use_premium_code__premium_only() ) { dprcu_render_geometry_controls__premium_only( $option, $step_id, $opt_id ); } else { dprcu_render_geometry_controls_locked(); } ?>
can_use_premium_code__premium_only() ) { dprcu_render_bulk_add_button__premium_only(); } else { dprcu_render_bulk_add_button_disabled(); } ?>

can_use_premium_code__premium_only() ) { dprcu_render_bulk_modal__premium_only(); ?>
☰
Icon Preview

can_use_premium_code__premium_only() ) { dprcu_render_bulk_add_button__premium_only(); } else { dprcu_render_bulk_add_button_disabled(); } ?>
$html, ) ); } add_action( 'wp_ajax_dprcu_render_step', 'dprcu_ajax_render_step' ); /** * AJAX handler to render a new option's HTML. * * Returns sanitized HTML for a new empty option card. */ function dprcu_ajax_render_option() { check_ajax_referer( 'dprcu_metabox_nonce', 'nonce' ); $step_id = ( isset( $_POST['step_id'] ) ? sanitize_text_field( wp_unslash( $_POST['step_id'] ) ) : '' ); $opt_id = ( isset( $_POST['opt_id'] ) ? sanitize_text_field( wp_unslash( $_POST['opt_id'] ) ) : '' ); if ( !$step_id || !$opt_id ) { wp_send_json_error( 'Missing step_id or opt_id' ); } ob_start(); ?>
☰
can_use_premium_code__premium_only() ) { dprcu_render_geometry_controls__premium_only( array(), $step_id, $opt_id ); } else { dprcu_render_geometry_controls_locked(); } ?>
$html, ) ); } add_action( 'wp_ajax_dprcu_render_option', 'dprcu_ajax_render_option' ); /** * Enqueue scripts and styles for the product metabox. */ function dprcu_enqueue_metabox_assets() { $screen = get_current_screen(); if ( !$screen || 'product' !== $screen->id ) { return; } wp_enqueue_media(); // Enqueue CSS wp_enqueue_style( 'dprcu-metabox-styles', plugins_url( 'css/metabox-styles.css', __FILE__ ), array(), ( filemtime( plugin_dir_path( __FILE__ ) . 'css/metabox-styles.css' ) ?: '1.0' ) ); // Enqueue jQuery UI Sortable wp_enqueue_script( 'jquery-ui-sortable' ); // Enqueue admin model scanner (for the 3D preview) wp_enqueue_script( 'dprcu-admin-model-scanner', plugin_dir_url( dirname( __FILE__ ) ) . 'dist/adminScanner.bundle.js', array('jquery'), '1.0', true ); // Pass scene settings (HDR env map, background color) so the admin preview // can mirror the front-end customizer.js scene setup. $global_settings = get_option( 'dprcu_settings', array() ); $bg_colors_str = $global_settings['bg_colors'] ?? "#f0f0f0\n#ffffff\n#222222"; $bg_colors = array_values( array_filter( preg_split( '/\\r\\n|[\\r\\n]/', $bg_colors_str ) ) ); wp_localize_script( 'dprcu-admin-model-scanner', 'dprcu_model_scanner', array( 'hdrFile' => esc_url( $global_settings['hdr_file'] ?? '' ), 'bgColor' => $bg_colors[0] ?? '#f0f0f0', ) ); // Enqueue JS — full free or full premium version of the metabox scripts. // The if-block is stripped from the free build by Freemius; only the else remains. if ( dprcu_fs()?->can_use_premium_code__premium_only() ) { wp_enqueue_script( 'dprcu-metabox-scripts', plugins_url( 'js/metabox-scripts__premium_only.js', __FILE__ ), array('jquery', 'jquery-ui-sortable'), ( filemtime( plugin_dir_path( __FILE__ ) . 'js/metabox-scripts__premium_only.js' ) ?: '1.0' ), true ); } else { wp_enqueue_script( 'dprcu-metabox-scripts', plugins_url( 'js/metabox-scripts.js', __FILE__ ), array('jquery', 'jquery-ui-sortable'), ( filemtime( plugin_dir_path( __FILE__ ) . 'js/metabox-scripts.js' ) ?: '1.0' ), true ); } // Pass textures data and nonce to JS $textures = dprcu_get_all_textures(); wp_localize_script( 'dprcu-metabox-scripts', 'dprcu_availableTextures', $textures ); wp_localize_script( 'dprcu-metabox-scripts', 'dprcu_ajax', array( 'nonce' => wp_create_nonce( 'dprcu_metabox_nonce' ), 'ajaxUrl' => admin_url( 'admin-ajax.php' ), ) ); } add_action( 'admin_enqueue_scripts', 'dprcu_enqueue_metabox_assets' ); /** * Normalises a multi-select field that may arrive as a PHP array (from *