| @@ -1,7 +1,15 @@ | ||
| 1 | 1 | <?php |
| 2 | 2 | |
| 3 | -if ( ! defined( 'WPINC' ) ) { | |
| 3 | +namespace UltimateStoreKit\Builder; | |
| 4 | + | |
| 5 | +if (! defined('ABSPATH')) { | |
| 6 | + exit; // Exit if accessed directly | |
| 7 | +} | |
| 8 | + | |
| 9 | +// phpcs:disable WordPress.NamingConventions.PrefixAllGlobals -- BDTUSK_ / ultimate_store_kit_ / ultimate-store-kit- are this plugin's established public prefixes. | |
| 10 | + | |
| 11 | +if (! defined('WPINC')) { | |
| 4 | 12 | die; |
| 5 | 13 | } |
| 6 | 14 | |
| 7 | 15 | use Elementor\Controls_Manager; |
| @@ -19,21 +27,120 @@ | ||
| 19 | 27 | private $current_template = null; |
| 20 | 28 | public $current_template_id = null; |
| 21 | 29 | |
| 22 | 30 | function __construct() { |
| 23 | - add_filter( 'template_include', [ $this, 'set_builder_template' ], 9999 ); | |
| 24 | - add_action( 'elementor/editor/init', [ $this, 'set_sample_post' ], 999 ); | |
| 31 | + add_filter('template_include', [$this, 'set_builder_template'], 9999); | |
| 32 | + add_action('elementor/editor/init', [$this, 'set_sample_post'], 999); | |
| 25 | 33 | |
| 26 | - add_action( 'print_default_editor_scripts', array( $this, 'my_custom_fonts' ) ); | |
| 34 | + add_action('print_default_editor_scripts', array($this, 'my_custom_fonts')); | |
| 35 | + add_filter("elementor/document/urls/wp_preview", [$this, 'change_preview_editor_url'], 999, 2); | |
| 27 | 36 | |
| 28 | - add_action( 'elementor/documents/register_controls', [ $this, 'register_document_controls' ] ); | |
| 37 | + add_action('elementor/documents/register_controls', [$this, 'register_document_controls']); | |
| 38 | + | |
| 39 | + // The template preview used to accept the literal string "verified" in place | |
| 40 | + // of a nonce whenever $_SERVER['HTTP_HOST'] contained one of a list of demo | |
| 41 | + // hostnames. Because Host is attacker-controlled and the check was a substring | |
| 42 | + // match, any unauthenticated visitor could render the Elementor content of an | |
| 43 | + // arbitrary post id -- including drafts and private posts -- on any site whose | |
| 44 | + // Host reached PHP as localhost/127.0.0.1 (common behind a reverse proxy) or | |
| 45 | + // whose domain merely contained one of those strings. Preview is now gated on | |
| 46 | + // the real per-post nonce plus an edit_post capability check; see get_template_id(). | |
| 29 | 47 | } |
| 30 | 48 | |
| 49 | + public function change_preview_editor_url($url, $document) { | |
| 50 | + $post_id = $document->get_main_id(); | |
| 51 | + $template_type = get_post_meta($post_id, Meta::TEMPLATE_TYPE, true); | |
| 52 | + | |
| 53 | + if (empty($template_type) || get_post_type($post_id) !== Meta::POST_TYPE) { | |
| 54 | + return $url; | |
| 55 | + } | |
| 56 | + | |
| 57 | + $template_data = explode(Builder_Template_Helper::separator(), $template_type); | |
| 58 | + if (count($template_data) < 2) { | |
| 59 | + return $url; | |
| 60 | + } | |
| 61 | + | |
| 62 | + $post_type = $template_data[0]; | |
| 63 | + $template_slug = $template_data[1]; | |
| 64 | + | |
| 65 | + // Get template URL based on template type | |
| 66 | + $template_url = ''; | |
| 67 | + | |
| 68 | + // Check for product category first | |
| 69 | + if ($template_slug === 'product-category') { | |
| 70 | + $product_cats = get_terms([ | |
| 71 | + 'taxonomy' => 'product_cat', | |
| 72 | + 'hide_empty' => true, | |
| 73 | + 'number' => 1, | |
| 74 | + ]); | |
| 75 | + | |
| 76 | + if (!empty($product_cats) && !is_wp_error($product_cats)) { | |
| 77 | + $template_url = get_term_link($product_cats[0]); | |
| 78 | + } | |
| 79 | + } | |
| 80 | + | |
| 81 | + // Check for product tag | |
| 82 | + elseif ($template_slug === 'product-tag') { | |
| 83 | + $product_tags = get_terms([ | |
| 84 | + 'taxonomy' => 'product_tag', | |
| 85 | + 'hide_empty' => true, | |
| 86 | + 'number' => 1, | |
| 87 | + ]); | |
| 88 | + | |
| 89 | + if (!empty($product_tags) && !is_wp_error($product_tags)) { | |
| 90 | + $template_url = get_term_link($product_tags[0]); | |
| 91 | + } | |
| 92 | + } elseif ($template_slug === 'shop' || $template_slug === 'archive') { | |
| 93 | + $template_url = get_permalink(wc_get_page_id('shop')); | |
| 94 | + } elseif ($template_slug === 'single' && $post_type === 'product') { | |
| 95 | + $page_settings_manager = \Elementor\Core\Settings\Manager::get_settings_managers('page'); | |
| 96 | + $page_settings_model = $page_settings_manager->get_model($post_id); | |
| 97 | + $sample_product = $page_settings_model->get_settings('usk_builder_sample_post_id'); | |
| 98 | + | |
| 99 | + $template_url = !empty($sample_product) ? | |
| 100 | + get_permalink($sample_product) : | |
| 101 | + $this->get_default_product_url(); | |
| 102 | + } elseif ($template_slug === 'cart') { | |
| 103 | + $template_url = wc_get_cart_url(); | |
| 104 | + } elseif ($template_slug === 'checkout') { | |
| 105 | + $template_url = wc_get_checkout_url(); | |
| 106 | + } elseif ( | |
| 107 | + $template_slug === 'myaccount' | |
| 108 | + || $template_slug === 'login' | |
| 109 | + || strpos($template_slug, 'myaccount-') === 0 | |
| 110 | + ) { | |
| 111 | + $template_url = get_permalink(wc_get_page_id('myaccount')); | |
| 112 | + } elseif ($template_slug === 'order-received') { | |
| 113 | + $orders = wc_get_orders(['limit' => 1]); | |
| 114 | + if (!empty($orders)) { | |
| 115 | + $order = $orders[0]; | |
| 116 | + $order_id = $order->get_id(); | |
| 117 | + $template_url = add_query_arg('order-received', $order_id, wc_get_checkout_url()); | |
| 118 | + } | |
| 119 | + } | |
| 120 | + | |
| 121 | + if (empty($template_url)) { | |
| 122 | + return $url; | |
| 123 | + } | |
| 124 | + | |
| 125 | + $param = [ | |
| 126 | + 'ultimate_store_kit_template_id' => $post_id, | |
| 127 | + 'ultimate_store_kit_preview_nonce' => wp_create_nonce('ultimate_store_kit_template_preview_' . $post_id), | |
| 128 | + 'preview' => true | |
| 129 | + ]; | |
| 130 | + | |
| 131 | + // Add parameters two URL | |
| 132 | + $url = add_query_arg($param, $template_url); | |
| 133 | + | |
| 134 | + return $url; | |
| 135 | + } | |
| 136 | + | |
| 31 | 137 | public function my_custom_fonts() { |
| 32 | - if ( is_admin() && Plugin::instance()->editor->is_edit_mode() ) { | |
| 33 | - if ( isset( $_REQUEST['usk-template'] ) ) { | |
| 34 | - wp_register_style( 'usk-template-builder-hide-preview-btn-inline', false ); // phpcs:ignore | |
| 35 | - wp_enqueue_style( 'usk-template-builder-hide-preview-btn-inline' ); | |
| 138 | + if (is_admin() && Plugin::instance()->editor->is_edit_mode()) { | |
| 139 | + // phpcs:ignore WordPress.Security.NonceVerification.Recommended -- Read-only check on whether a builder template is open; only enqueues a style. | |
| 140 | + if (isset($_REQUEST['usk-template'])) { | |
| 141 | + wp_register_style('usk-template-builder-hide-preview-btn-inline', false); // phpcs:ignore | |
| 142 | + wp_enqueue_style('usk-template-builder-hide-preview-btn-inline'); | |
| 36 | 143 | wp_add_inline_style( |
| 37 | 144 | 'usk-template-builder-hide-preview-btn-inline', |
| 38 | 145 | '#elementor-panel-footer-saver-preview {display:none!important}' |
| 39 | 146 | ); |
| @@ -40,50 +147,52 @@ | ||
| 40 | 147 | } |
| 41 | 148 | } |
| 42 | 149 | } |
| 43 | 150 | function set_sample_post() { |
| 44 | - if ( Builder_Template_Helper::isTemplateEditMode() ) { | |
| 151 | + if (Builder_Template_Helper::isTemplateEditMode()) { | |
| 45 | 152 | $object = \UltimateStoreKit\Includes\Builder\Builder_Post_Singleton::instance(); |
| 46 | 153 | $object::set_sample_post(); |
| 47 | 154 | } |
| 48 | 155 | } |
| 49 | 156 | |
| 50 | - function register_document_controls( $document ) { | |
| 51 | - if ( ! $document instanceof \Elementor\Core\DocumentTypes\PageBase | |
| 52 | - || ! $document::get_property( 'has_elements' ) ) { | |
| 157 | + function register_document_controls($document) { | |
| 158 | + if ( | |
| 159 | + ! $document instanceof \Elementor\Core\DocumentTypes\PageBase | |
| 160 | + || ! $document::get_property('has_elements') | |
| 161 | + ) { | |
| 53 | 162 | return; |
| 54 | 163 | } |
| 55 | 164 | |
| 56 | - if ( Plugin::instance()->preview->is_preview_mode() ) | |
| 165 | + if (Plugin::instance()->preview->is_preview_mode()) | |
| 57 | 166 | return; |
| 58 | 167 | |
| 59 | - if ( ! Builder_Template_Helper::isTemplateEditMode() ) { | |
| 168 | + if (! Builder_Template_Helper::isTemplateEditMode()) { | |
| 60 | 169 | return; |
| 61 | 170 | } |
| 62 | 171 | |
| 63 | 172 | global $post; |
| 64 | 173 | |
| 65 | - if ( ! isset( $post->ID ) ) { | |
| 174 | + if (! isset($post->ID)) { | |
| 66 | 175 | return; |
| 67 | 176 | } |
| 68 | - $meta = get_post_meta( $post->ID ); | |
| 177 | + $meta = get_post_meta($post->ID); | |
| 69 | 178 | |
| 70 | - $templateMeta = optional( $meta )[ Meta::TEMPLATE_TYPE ]; | |
| 71 | - if ( ! isset( $templateMeta[0] ) ) { | |
| 179 | + $templateMeta = ultimate_store_kit_optional($meta)[Meta::TEMPLATE_TYPE]; | |
| 180 | + if (! isset($templateMeta[0])) { | |
| 72 | 181 | return; |
| 73 | 182 | } |
| 74 | 183 | $postMeta = $templateMeta[0]; |
| 75 | - $postMeta = explode( '|', $postMeta ); | |
| 184 | + $postMeta = explode('|', $postMeta); | |
| 76 | 185 | $postType = $postMeta[0]; |
| 77 | 186 | |
| 78 | - if ( $postMeta[1] != 'single' ) { | |
| 187 | + if ($postMeta[1] != 'single') { | |
| 79 | 188 | return; |
| 80 | 189 | } |
| 81 | 190 | |
| 82 | 191 | $document->start_controls_section( |
| 83 | 192 | 'usk_page_setting_preview', |
| 84 | - [ | |
| 85 | - 'label' => esc_html__( 'Builder Settings', 'ultimate-store-kit' ), | |
| 193 | + [ | |
| 194 | + 'label' => esc_html__('Builder Settings', 'ultimate-store-kit'), | |
| 86 | 195 | 'tab' => Controls_Manager::TAB_SETTINGS, |
| 87 | 196 | ] |
| 88 | 197 | ); |
| 89 | 198 | |
| @@ -88,27 +197,27 @@ | ||
| 88 | 197 | ); |
| 89 | 198 | |
| 90 | 199 | $document->add_control( |
| 91 | 200 | 'usk_builder_sample_post_id', |
| 92 | - [ | |
| 93 | - 'label' => __( 'Builder Post', 'ultimate-store-kit' ), | |
| 201 | + [ | |
| 202 | + 'label' => __('Builder Post', 'ultimate-store-kit'), | |
| 94 | 203 | 'type' => Dynamic_Select::TYPE, |
| 95 | 204 | 'multiple' => false, |
| 96 | 205 | 'label_block' => true, |
| 97 | - 'query_args' => [ | |
| 98 | - 'post_type' => $postType | |
| 99 | - ], | |
| 206 | + 'query_args' => [ | |
| 207 | + 'post_type' => $postType | |
| 208 | + ], | |
| 100 | 209 | ] |
| 101 | 210 | ); |
| 102 | 211 | |
| 103 | 212 | $document->add_control( |
| 104 | 213 | 'usk_builder_sample_apply_preview', |
| 105 | - [ | |
| 214 | + [ | |
| 106 | 215 | 'type' => Controls_Manager::BUTTON, |
| 107 | - 'label' => esc_html__( 'Apply & Preview', 'ultimate-store-kit' ), | |
| 216 | + 'label' => esc_html__('Apply & Preview', 'ultimate-store-kit'), | |
| 108 | 217 | 'label_block' => true, |
| 109 | 218 | 'show_label' => false, |
| 110 | - 'text' => esc_html__( 'Apply & Preview', 'ultimate-store-kit' ), | |
| 219 | + 'text' => esc_html__('Apply & Preview', 'ultimate-store-kit'), | |
| 111 | 220 | 'separator' => 'none', |
| 112 | 221 | 'event' => 'ultimateStoreKitBuilderSetting:applySinglePagePostOnPreview', |
| 113 | 222 | ] |
| 114 | 223 | ); |
| @@ -119,73 +228,84 @@ | ||
| 119 | 228 | /** |
| 120 | 229 | * Rewrite default template |
| 121 | 230 | * |
| 122 | 231 | */ |
| 123 | - function set_builder_template( $template ) { | |
| 124 | - if ( Builder_Template_Helper::isTemplateEditMode() ) { | |
| 125 | - return $this->setBackendTemplate( $template ); | |
| 232 | + function set_builder_template($template) { | |
| 233 | + if (Builder_Template_Helper::isTemplateEditMode()) { | |
| 234 | + return $this->setBackendTemplate($template); | |
| 126 | 235 | } else { |
| 127 | - return $this->setFrontendTemplate( $template ); | |
| 236 | + return $this->setFrontendTemplate($template); | |
| 128 | 237 | } |
| 129 | 238 | } |
| 130 | 239 | |
| 131 | 240 | |
| 132 | - protected function setBackendTemplate( $template ) { | |
| 241 | + protected function setBackendTemplate($template) { | |
| 133 | 242 | return $template; |
| 134 | 243 | } |
| 135 | 244 | |
| 136 | 245 | |
| 137 | - protected function setFrontendTemplate( $template ) { | |
| 246 | + protected function setFrontendTemplate($template) { | |
| 138 | 247 | |
| 139 | - if ( get_post_type() == 'product' ) { | |
| 248 | + if (get_post_type() == 'product') { | |
| 140 | 249 | global $product; |
| 141 | 250 | $product = wc_get_product(); |
| 142 | 251 | } |
| 143 | 252 | |
| 144 | - if ( defined( 'ELEMENTOR_PATH' ) ) { | |
| 253 | + if (defined('ELEMENTOR_PATH')) { | |
| 145 | 254 | $elementorTem = ELEMENTOR_PATH . "modules/page-templates/templates/"; |
| 146 | - $elementorTem = explode( $elementorTem, $template ); | |
| 147 | - if ( count( $elementorTem ) == 2 ) { | |
| 255 | + $elementorTem = explode($elementorTem, $template); | |
| 256 | + if (count($elementorTem) == 2) { | |
| 148 | 257 | return $template; |
| 149 | 258 | } |
| 150 | 259 | } |
| 151 | 260 | |
| 152 | - if ( is_post_type_archive( 'product' ) || is_page( wc_get_page_id( 'shop' ) ) || is_product_taxonomy() ) { | |
| 153 | - if ( $custom_template = $this->get_template_id( 'shop' ) ) { | |
| 261 | + | |
| 262 | + if (is_post_type_archive('product') || is_page(wc_get_page_id('shop')) || is_product_taxonomy()) { | |
| 263 | + $template_type = 'shop'; | |
| 264 | + | |
| 265 | + if (is_tax('product_cat')) { | |
| 266 | + $template_type = 'category'; | |
| 267 | + } elseif (is_tax('product_tag')) { | |
| 268 | + $template_type = 'tag'; | |
| 269 | + } | |
| 270 | + | |
| 271 | + if ($custom_template = $this->get_template_id($template_type)) { | |
| 154 | 272 | $this->current_template_id = $custom_template; |
| 155 | - return $this->getTemplatePath( 'woocommerce/archive-product', $template ); | |
| 273 | + return $this->getTemplatePath('woocommerce/archive-product', $template); | |
| 156 | 274 | } |
| 157 | 275 | } |
| 158 | 276 | |
| 277 | + | |
| 159 | 278 | if ( is_cart() ) { |
| 160 | - if ( $custom_template = $this->get_template_id( 'cart', 'product' ) ) { | |
| 161 | - $this->current_template_id = $custom_template; | |
| 162 | - return $this->getTemplatePath( 'woocommerce/cart', $template ); | |
| 279 | + $cart_template = $this->resolve_cart_template( $template ); | |
| 280 | + | |
| 281 | + if ( $cart_template ) { | |
| 282 | + return $cart_template; | |
| 163 | 283 | } |
| 164 | 284 | } |
| 165 | 285 | |
| 166 | - if ( is_order_received_page() ) { | |
| 167 | - if ( $custom_template = $this->get_template_id( 'order-received', 'product' ) ) { | |
| 286 | + if (is_order_received_page()) { | |
| 287 | + if ($custom_template = $this->get_template_id('order-received', 'product')) { | |
| 168 | 288 | $this->current_template_id = $custom_template; |
| 169 | - return $this->getTemplatePath( 'woocommerce/order-received', $template ); | |
| 289 | + return $this->getTemplatePath('woocommerce/order-received', $template); | |
| 170 | 290 | } |
| 171 | 291 | } |
| 172 | 292 | |
| 173 | - if ( is_checkout() ) { | |
| 174 | - if ( $custom_template = $this->get_template_id( 'checkout', 'product' ) ) { | |
| 293 | + if (is_checkout()) { | |
| 294 | + if ($custom_template = $this->get_template_id('checkout', 'product')) { | |
| 175 | 295 | $this->current_template_id = $custom_template; |
| 176 | - return $this->getTemplatePath( 'woocommerce/checkout', $template ); | |
| 296 | + return $this->getTemplatePath('woocommerce/checkout', $template); | |
| 177 | 297 | } |
| 178 | 298 | } |
| 179 | 299 | |
| 180 | - if ( is_single() && get_post_type() == 'product' ) { | |
| 181 | - if ( $custom_template = $this->get_template_id( 'single', 'product' ) ) { | |
| 300 | + if (is_single() && get_post_type() == 'product') { | |
| 301 | + if ($custom_template = $this->get_template_id('single', 'product')) { | |
| 182 | 302 | $this->current_template_id = $custom_template; |
| 183 | - return $this->getTemplatePath( 'woocommerce/single-product', $template ); | |
| 303 | + return $this->getTemplatePath('woocommerce/single-product', $template); | |
| 184 | 304 | } |
| 185 | 305 | } |
| 186 | 306 | |
| 187 | - if ( is_account_page() ) { | |
| 307 | + if (is_account_page()) { | |
| 188 | 308 | global $wp; |
| 189 | 309 | $query_vars = WC()->query->get_query_vars(); |
| 190 | 310 | |
| 191 | 311 | /** |
| @@ -192,61 +312,79 @@ | ||
| 192 | 312 | * Add wishlist endpoint |
| 193 | 313 | */ |
| 194 | 314 | $query_vars['wishlist'] = 'wishlist'; |
| 195 | 315 | |
| 196 | - if ( $endpoint = array_intersect_key( $wp->query_vars, $query_vars ) ) { | |
| 197 | - $endpoint = array_key_first( $endpoint ); | |
| 316 | + $endpoint_match = array_intersect_key($wp->query_vars, $query_vars); | |
| 198 | 317 | |
| 199 | - if ( $endpoint && $custom_template = $this->get_template_id( $endpoint, 'account' ) ) { | |
| 318 | + // Logged-out visitors landing on /my-account/ (no endpoint) see the | |
| 319 | + // single Login & Register template, which is responsible for both | |
| 320 | + // authentication flows. WooCommerce's own form-login.php renders | |
| 321 | + // the login and registration forms on the same URL, so one | |
| 322 | + // template covers both intents. | |
| 323 | + if (! is_user_logged_in() && empty($endpoint_match)) { | |
| 324 | + if ($custom_template = $this->get_template_id('login', 'account')) { | |
| 200 | 325 | $this->current_template_id = $custom_template; |
| 201 | 326 | |
| 202 | - if ( $newTemplate = $this->getTemplatePath( "woocommerce/{$endpoint}" ) ) { | |
| 327 | + if ($newTemplate = $this->getTemplatePath('woocommerce/login')) { | |
| 203 | 328 | return $newTemplate; |
| 204 | 329 | } |
| 205 | 330 | |
| 206 | - return $this->getTemplatePath( "woocommerce/my-account", '' ); | |
| 331 | + return $this->getTemplatePath('woocommerce/my-account', $template); | |
| 207 | 332 | } |
| 333 | + } | |
| 208 | 334 | |
| 209 | - if ( $custom_template = $this->get_template_id( 'myaccount-orders', 'account' ) ) { | |
| 335 | + if ($endpoint = $endpoint_match) { | |
| 336 | + $endpoint = array_key_first($endpoint); | |
| 337 | + | |
| 338 | + if ($endpoint && $custom_template = $this->get_template_id($endpoint, 'account')) { | |
| 210 | 339 | $this->current_template_id = $custom_template; |
| 211 | - return $this->getTemplatePath( 'woocommerce/my-account', $template ); | |
| 340 | + | |
| 341 | + if ($newTemplate = $this->getTemplatePath("woocommerce/{$endpoint}")) { | |
| 342 | + return $newTemplate; | |
| 343 | + } | |
| 344 | + | |
| 345 | + return $this->getTemplatePath("woocommerce/my-account", ''); | |
| 212 | 346 | } |
| 213 | 347 | |
| 348 | + if ($custom_template = $this->get_template_id('myaccount-orders', 'account')) { | |
| 349 | + $this->current_template_id = $custom_template; | |
| 350 | + return $this->getTemplatePath('woocommerce/my-account', $template); | |
| 351 | + } | |
| 214 | 352 | } else { |
| 215 | - if ( $custom_template = $this->get_template_id( 'myaccount', 'account' ) ) { | |
| 353 | + if ($custom_template = $this->get_template_id('myaccount', 'account')) { | |
| 216 | 354 | $this->current_template_id = $custom_template; |
| 217 | - return $this->getTemplatePath( 'woocommerce/my-account', $template ); | |
| 355 | + return $this->getTemplatePath('woocommerce/my-account', $template); | |
| 218 | 356 | } |
| 219 | 357 | } |
| 220 | 358 | } |
| 221 | 359 | |
| 222 | 360 | |
| 223 | - if ( is_single() ) { | |
| 224 | - if ( $custom_template = $this->get_template_id( 'single', 'post' ) ) { | |
| 361 | + if (is_single()) { | |
| 362 | + if ($custom_template = $this->get_template_id('single', 'post')) { | |
| 225 | 363 | $this->current_template_id = $custom_template; |
| 226 | - return $this->getTemplatePath( 'single-post', $template ); | |
| 364 | + return $this->getTemplatePath('single-post', $template); | |
| 227 | 365 | } |
| 228 | 366 | } |
| 229 | 367 | |
| 230 | - if ( is_archive() ) { | |
| 231 | - if ( $custom_template = $this->get_template_id( 'archive', 'post' ) ) { | |
| 368 | + if (is_archive()) { | |
| 369 | + if ($custom_template = $this->get_template_id('archive', 'post')) { | |
| 232 | 370 | $this->current_template_id = $custom_template; |
| 233 | - return $this->getTemplatePath( 'archive-post', $template ); | |
| 371 | + return $this->getTemplatePath('archive-post', $template); | |
| 234 | 372 | } |
| 235 | 373 | } |
| 236 | 374 | |
| 237 | - if ( is_home() ) { | |
| 238 | - if ( $custom_template = $this->get_template_id( 'home', 'post' ) ) { | |
| 375 | + if (is_home()) { | |
| 376 | + if ($custom_template = $this->get_template_id('home', 'post')) { | |
| 239 | 377 | $this->current_template_id = $custom_template; |
| 240 | - return $this->getTemplatePath( 'home', $template ); | |
| 378 | + return $this->getTemplatePath('home', $template); | |
| 241 | 379 | } |
| 242 | 380 | } |
| 243 | 381 | |
| 244 | - if ( $page_Id = intval( get_option( 'bdt_usk_compare_products_page_id' ) ) ) { | |
| 245 | - if ( is_page( $page_Id ) ) { | |
| 246 | - if ( $custom_template = $this->get_template_id( 'compare-products', 'product' ) ) { | |
| 382 | + if ($page_Id = ultimate_store_kit_get_compare_page_option()) { | |
| 383 | + if (is_page($page_Id)) { | |
| 384 | + if ($custom_template = $this->get_template_id('compare-products', 'product')) { | |
| 247 | 385 | $this->current_template_id = $custom_template; |
| 248 | - return $this->getTemplatePath( 'home', $template ); | |
| 386 | + return $this->getTemplatePath('home', $template); | |
| 249 | 387 | } |
| 250 | 388 | } |
| 251 | 389 | } |
| 252 | 390 | |
| @@ -253,20 +391,20 @@ | ||
| 253 | 391 | return $template; |
| 254 | 392 | } |
| 255 | 393 | |
| 256 | 394 | |
| 257 | - public function getThemeTemplatePath( $slug ) { | |
| 395 | + public function getThemeTemplatePath($slug) { | |
| 258 | 396 | |
| 259 | 397 | $fullPath = get_template_directory() . "/ultimate-store-kit/$slug"; |
| 260 | - if ( file_exists( $fullPath ) ) { | |
| 398 | + if (file_exists($fullPath)) { | |
| 261 | 399 | return $fullPath; |
| 262 | 400 | } |
| 263 | 401 | } |
| 264 | 402 | |
| 265 | - public function getPluginTemplatePath( $slug ) { | |
| 403 | + public function getPluginTemplatePath($slug) { | |
| 266 | 404 | |
| 267 | 405 | $fullPath = BDTUSK_PATH . "includes/builder/templates/$slug"; |
| 268 | - if ( file_exists( $fullPath ) ) { | |
| 406 | + if (file_exists($fullPath)) { | |
| 269 | 407 | return $fullPath; |
| 270 | 408 | } |
| 271 | 409 | } |
| 272 | 410 | |
| @@ -278,16 +416,41 @@ | ||
| 278 | 416 | * @param $postType |
| 279 | 417 | * |
| 280 | 418 | * @return mixed|void|null |
| 281 | 419 | */ |
| 282 | - public function get_template_id( $slug, $postType = false ) { | |
| 420 | + public function get_template_id($slug, $postType = false) { | |
| 421 | + // If we already have a template ID for this request, return it | |
| 422 | + if (null !== $this->current_template_id) { | |
| 423 | + return $this->current_template_id; | |
| 424 | + } | |
| 283 | 425 | |
| 284 | - if ( null !== $this->current_template_id ) { | |
| 285 | - return $this->current_template_id; | |
| 426 | + // Handle template preview from URL parameters. | |
| 427 | + if (!empty($_GET['preview']) && !empty($_GET['ultimate_store_kit_template_id']) && !empty($_GET['ultimate_store_kit_preview_nonce'])) { | |
| 428 | + $usk_template_id = absint(wp_unslash($_GET['ultimate_store_kit_template_id'])); | |
| 429 | + $nonce = sanitize_text_field(wp_unslash($_GET['ultimate_store_kit_preview_nonce'])); | |
| 430 | + | |
| 431 | + // The nonce is bound to the specific template and to the user who | |
| 432 | + // generated it, and the capability check makes sure a leaked preview | |
| 433 | + // URL cannot be replayed by someone who may not edit the template. | |
| 434 | + $nonce_verified = $usk_template_id | |
| 435 | + && wp_verify_nonce($nonce, 'ultimate_store_kit_template_preview_' . $usk_template_id) | |
| 436 | + && current_user_can('edit_post', $usk_template_id); | |
| 437 | + | |
| 438 | + if ($nonce_verified && get_post_type($usk_template_id) === Meta::POST_TYPE) { | |
| 439 | + $template_type = get_post_meta($usk_template_id, Meta::TEMPLATE_TYPE, true); | |
| 440 | + if (!empty($template_type)) { | |
| 441 | + $template_data = explode(Builder_Template_Helper::separator(), $template_type); | |
| 442 | + if (count($template_data) >= 2 && $template_data[1] === $slug && ($postType === false || $template_data[0] === $postType)) { | |
| 443 | + $this->current_template_id = $usk_template_id; | |
| 444 | + return $this->current_template_id; | |
| 445 | + } | |
| 446 | + } | |
| 447 | + } | |
| 286 | 448 | } |
| 287 | 449 | |
| 288 | - $templateId = Builder_Template_Helper::getTemplate( $slug, $postType ); | |
| 289 | - $this->current_template_id = apply_filters( 'ultimate-store-kit-builder/custom-shop-template', $templateId ); | |
| 450 | + // Regular template retrieval | |
| 451 | + $templateId = Builder_Template_Helper::getTemplate($slug, $postType); | |
| 452 | + $this->current_template_id = apply_filters('ultimate-store-kit-builder/custom-shop-template', $templateId); | |
| 290 | 453 | |
| 291 | 454 | return $this->current_template_id; |
| 292 | 455 | } |
| 293 | 456 | |
| @@ -299,16 +462,16 @@ | ||
| 299 | 462 | * @param $default |
| 300 | 463 | * |
| 301 | 464 | * @return mixed|string|void |
| 302 | 465 | */ |
| 303 | - protected function getTemplatePath( $slug, $default = '' ) { | |
| 466 | + protected function getTemplatePath($slug, $default = '') { | |
| 304 | 467 | $phpSlug = "{$slug}.php"; |
| 305 | 468 | |
| 306 | - if ( $template = $this->getThemeTemplatePath( $phpSlug ) ) { | |
| 469 | + if ($template = $this->getThemeTemplatePath($phpSlug)) { | |
| 307 | 470 | return $template; |
| 308 | 471 | } |
| 309 | 472 | |
| 310 | - if ( $template = $this->getPluginTemplatePath( $phpSlug ) ) { | |
| 473 | + if ($template = $this->getPluginTemplatePath($phpSlug)) { | |
| 311 | 474 | return $template; |
| 312 | 475 | } |
| 313 | 476 | |
| 314 | 477 | return $default; |
| @@ -313,10 +476,43 @@ | ||
| 313 | 476 | |
| 314 | 477 | return $default; |
| 315 | 478 | } |
| 316 | 479 | |
| 480 | + /** | |
| 481 | + * Resolve the plugin cart template for WooCommerce cart requests. | |
| 482 | + * | |
| 483 | + * @param string $template Default WordPress template path. | |
| 484 | + * @return string|false | |
| 485 | + */ | |
| 486 | + protected function resolve_cart_template( $template ) { | |
| 487 | + if ( ! Cart_Render::is_available() ) { | |
| 488 | + return false; | |
| 489 | + } | |
| 490 | + | |
| 491 | + $custom_template = $this->get_template_id( 'cart', 'product' ); | |
| 492 | + $this->current_template_id = $custom_template ? absint( $custom_template ) : null; | |
| 493 | + | |
| 494 | + return $this->getTemplatePath( 'woocommerce/cart', $template ); | |
| 495 | + } | |
| 496 | + | |
| 497 | + /** | |
| 498 | + * Get default product URL with proper error checking | |
| 499 | + * | |
| 500 | + * @return string | |
| 501 | + */ | |
| 502 | + protected function get_default_product_url() { | |
| 503 | + $products = wc_get_products(['status' => 'publish', 'limit' => 1]); | |
| 504 | + | |
| 505 | + if (!empty($products) && isset($products[0]) && is_object($products[0])) { | |
| 506 | + $product = $products[0]; | |
| 507 | + if (method_exists($product, 'get_id')) { | |
| 508 | + return get_permalink($product->get_id()); | |
| 509 | + } | |
| 510 | + } | |
| 511 | + | |
| 512 | + // Fallback to shop page if no products found | |
| 513 | + return get_permalink(wc_get_page_id('shop')); | |
| 514 | + } | |
| 317 | 515 | } |
| 318 | 516 | |
| 319 | 517 | |
| 320 | 518 | Builder_Integration::instance(); |
| 321 | - | |
| 322 | - | |