'Sales Orders', 'odoo-invoices' => 'Invoices', 'odoo-deliveries' => 'Deliveries', 'odoo-returns' => 'Returns', ]; const OPTION_MAP = [ 'odoo-sales-orders' => 'fusion_woodoo_show_orders', 'odoo-invoices' => 'fusion_woodoo_show_invoices', 'odoo-deliveries' => 'fusion_woodoo_show_deliveries', 'odoo-returns' => 'fusion_woodoo_show_returns', ]; const TEMPLATE_MAP = [ 'odoo-sales-orders' => 'sales-orders.php', 'odoo-invoices' => 'invoices.php', 'odoo-deliveries' => 'deliveries.php', 'odoo-returns' => 'returns.php', ]; public function __construct() { add_action('init', [$this, 'add_rewrite_endpoints']); add_filter('woocommerce_account_menu_items', [$this, 'add_menu_items']); foreach (array_keys(self::ENDPOINTS) as $endpoint) { add_action('woocommerce_account_' . $endpoint . '_endpoint', [$this, 'render_endpoint_content']); } // AJAX handler for PDF downloads add_action('wp_ajax_fusion_woodoo_download_pdf', [$this, 'ajax_download_pdf']); } public function add_rewrite_endpoints(): void { foreach (array_keys(self::ENDPOINTS) as $endpoint) { add_rewrite_endpoint($endpoint, EP_ROOT | EP_PAGES); } } public function add_menu_items(array $items): array { $new_items = []; foreach ($items as $key => $label) { $new_items[$key] = $label; // Insert Odoo tabs after 'orders' if ($key === 'orders') { foreach (self::ENDPOINTS as $endpoint => $title) { if (get_option(self::OPTION_MAP[$endpoint], 1)) { $new_items[$endpoint] = __($title, 'fusion-woodoo'); } } } } return $new_items; } /** * Generic renderer — dispatches to the correct template. */ public function render_endpoint_content(): void { // Determine which endpoint triggered this action $current = null; foreach (array_keys(self::ENDPOINTS) as $endpoint) { if (did_action('woocommerce_account_' . $endpoint . '_endpoint')) { $current = $endpoint; break; } } if (!$current || !isset(self::TEMPLATE_MAP[$current])) { return; } $template = FUSION_WOODOO_PLUGIN_DIR . 'templates/my-account/' . self::TEMPLATE_MAP[$current]; if (file_exists($template)) { include $template; } } /** * AJAX: serve a stored PDF file to the logged-in customer who owns the order. */ public function ajax_download_pdf(): void { check_ajax_referer('fusion_woodoo_nonce', 'nonce'); $order_id = (int) ($_GET['order_id'] ?? 0); $type = sanitize_key($_GET['type'] ?? 'invoice'); if (!$order_id || !is_user_logged_in()) { wp_die(__('Access denied.', 'fusion-woodoo'), 403); } $order = wc_get_order($order_id); if (!$order || $order->get_customer_id() !== get_current_user_id()) { wp_die(__('Access denied.', 'fusion-woodoo'), 403); } $meta_key = $type === 'delivery' ? '_odoo_delivery_pdf' : '_odoo_invoice_pdf'; $rel_path = $order->get_meta($meta_key); if (empty($rel_path)) { wp_die(__('PDF not found.', 'fusion-woodoo'), 404); } $upload = wp_upload_dir(); $file_path = $upload['basedir'] . $rel_path; if (!file_exists($file_path) || !is_file($file_path)) { wp_die(__('PDF file not found on server.', 'fusion-woodoo'), 404); } // Security: ensure path stays within uploads dir $real_base = realpath($upload['basedir']); $real_file = realpath($file_path); if (!$real_file || strpos($real_file, $real_base) !== 0) { wp_die(__('Access denied.', 'fusion-woodoo'), 403); } header('Content-Type: application/pdf'); header('Content-Disposition: attachment; filename="' . basename($real_file) . '"'); header('Content-Length: ' . filesize($real_file)); readfile($real_file); exit; } }