// 1. Register Custom Post Type for Smart Audios add_action('init', 'sap_register_cpt'); function sap_register_cpt() { register_post_type('sap_audio', array( 'public' => false, 'show_ui' => true, // Show in admin area so you can manage them 'label' => 'Smart Audios', 'supports' => array('title', 'custom-fields') )); } // 2. REST API Endpoints for the React App to communicate with WordPress add_action('rest_api_init', function() { register_rest_route('sap/v1', '/audios', array( array( 'methods' => 'GET', 'callback' => 'sap_get_audios', 'permission_callback' => '__return_true' // Publicly readable ), array( 'methods' => 'POST', 'callback' => 'sap_create_audio', 'permission_callback' => function() { return current_user_can('upload_files'); // Only logged-in users with upload capability can add } ) )); register_rest_route('sap/v1', '/audios/(?P\d+)', array( array( 'methods' => 'DELETE', 'callback' => 'sap_delete_audio', 'permission_callback' => function() { return current_user_can('delete_posts'); // Only users who can delete posts can delete } ) )); }); function sap_get_audios($request) { $posts = get_posts(array( 'post_type' => 'sap_audio', 'posts_per_page' => -1, 'post_status' => 'publish', 'orderby' => 'date', 'order' => 'DESC' )); $data = array(); foreach($posts as $p) { $attachment_id = get_post_meta($p->ID, 'audio_attachment_id', true); $url = wp_get_attachment_url($attachment_id); $transcript = json_decode(get_post_meta($p->ID, 'transcript', true), true); $categories = json_decode(get_post_meta($p->ID, 'categories', true), true); $tags = json_decode(get_post_meta($p->ID, 'tags', true), true); $data[] = array( 'id' => (string)$p->ID, 'title' => $p->post_title, 'fileName' => get_post_meta($p->ID, 'fileName', true), 'fileUrl' => $url ? $url : '', 'transcript' => $transcript ? $transcript : '', 'categories' => $categories ? $categories : array(), 'tags' => $tags ? $tags : array(), 'duration' => (float)get_post_meta($p->ID, 'duration', true), 'uploadDate' => (float)get_post_meta($p->ID, 'uploadDate', true) ); } return rest_ensure_response($data); } function sap_create_audio($request) { require_once( ABSPATH . 'wp-admin/includes/image.php' ); require_once( ABSPATH . 'wp-admin/includes/file.php' ); require_once( ABSPATH . 'wp-admin/includes/media.php' ); $attachment_id = media_handle_upload('file', 0); if ( is_wp_error( $attachment_id ) ) { return new WP_Error( 'upload_error', $attachment_id->get_error_message(), array( 'status' => 500 ) ); } $metadata_str = $request->get_param('metadata'); $metadata = json_decode(stripslashes($metadata_str), true); if (!$metadata) { $metadata = json_decode($metadata_str, true); } $post_id = wp_insert_post(array( 'post_title' => sanitize_text_field($metadata['title']), 'post_type' => 'sap_audio', 'post_status' => 'publish' )); update_post_meta($post_id, 'audio_attachment_id', $attachment_id); update_post_meta($post_id, 'fileName', sanitize_text_field($metadata['fileName'])); update_post_meta($post_id, 'transcript', wp_slash(wp_json_encode($metadata['transcript']))); update_post_meta($post_id, 'categories', wp_slash(wp_json_encode($metadata['categories']))); update_post_meta($post_id, 'tags', wp_slash(wp_json_encode($metadata['tags']))); update_post_meta($post_id, 'duration', (float)$metadata['duration']); update_post_meta($post_id, 'uploadDate', time() * 1000); $url = wp_get_attachment_url($attachment_id); $metadata['id'] = (string)$post_id; $metadata['fileUrl'] = $url; return rest_ensure_response($metadata); } function sap_delete_audio($request) { $post_id = (int) $request['id']; $attachment_id = get_post_meta($post_id, 'audio_attachment_id', true); if ($attachment_id) { wp_delete_attachment($attachment_id, true); } wp_delete_post($post_id, true); return rest_ensure_response(array('success' => true)); } // 3. Enqueue React App Scripts and Styles on the specific page add_action('wp_enqueue_scripts', 'sap_enqueue_assets'); function sap_enqueue_assets() { // ONLY load on the specific page slug if (!is_page('test-smart-audio')) { return; } // Get the active theme directory URL and path $theme_url = get_stylesheet_directory_uri(); $theme_dir = get_stylesheet_directory(); $assets_dir = $theme_dir . '/dist/assets/'; if (is_dir($assets_dir)) { $files = scandir($assets_dir); $js_index = 0; $css_index = 0; $main_js_handle = ''; foreach ($files as $file) { if (pathinfo($file, PATHINFO_EXTENSION) === 'js') { $handle = 'sap-react-app-' . $js_index; wp_enqueue_script( $handle, $theme_url . '/dist/assets/' . $file, array(), '1.0.0', true ); if ($js_index === 0) { $main_js_handle = $handle; } $js_index++; } if (pathinfo($file, PATHINFO_EXTENSION) === 'css') { $handle = 'sap-react-styles-' . $css_index; wp_enqueue_style( $handle, $theme_url . '/dist/assets/' . $file, array(), '1.0.0' ); $css_index++; } } // Pass configuration to the React app if ($main_js_handle !== '') { wp_localize_script($main_js_handle, 'sapConfig', array( 'geminiApiKey' => 'AIzaSyC1_s4Yx9EzRV3FGZMujMqotz4892Qo4yI', 'theme' => 'default', 'apiUrl' => esc_url_raw( rest_url( 'sap/v1' ) ), 'nonce' => wp_create_nonce( 'wp_rest' ), 'isFrontend' => "1" )); } } else { error_log('Smart Audio Player: dist/assets directory not found at ' . $assets_dir); } } // 4. Add type="module" to the React scripts (Required for Vite) add_filter('script_loader_tag', 'sap_add_type_attribute', 10, 3); function sap_add_type_attribute($tag, $handle, $src) { if (strpos($handle, 'sap-react-app') !== false) { $tag = '' . "\n"; } return $tag; } https://hassansomali.com/wp-sitemap-posts-post-1.xmlhttps://hassansomali.com/wp-sitemap-posts-page-1.xmlhttps://hassansomali.com/wp-sitemap-taxonomies-category-1.xmlhttps://hassansomali.com/wp-sitemap-taxonomies-post_tag-1.xmlhttps://hassansomali.com/wp-sitemap-users-1.xml