file_storage = new Audio_File_Storage( $directory_manager, $file_writer ); $this->metadata_manager = new Audio_File_Metadata(); $this->file_cleaner = new Audio_File_Cleaner( $file_deleter, $this->metadata_manager ); // Keep old components for backwards compatibility. $this->directory_manager = $directory_manager ?? new Audio_Directory_Manager(); $this->file_writer = $file_writer ?? new Audio_File_Writer( $this->directory_manager ); $this->file_deleter = $file_deleter ?? new Audio_File_Deleter(); } /** * Save audio content to file - delegates to new architecture. * * @param string $audio_content Binary audio content. * @param int $post_id Post ID for filename generation. * @return array Result with success status, URL, path, and size. */ public function save_audio_file( $audio_content, $post_id ) { // Use new architecture. $storage_result = $this->file_storage->store_audio_content( $audio_content, $post_id ); if ( ! empty( $storage_result['success'] ) ) { // Store metadata. $this->metadata_manager->store_metadata( $post_id, array( 'url' => $storage_result['url'], 'path' => $storage_result['path'], 'size' => $storage_result['size'], 'filename' => $storage_result['filename'], 'format' => $storage_result['format'] ?? 'mp3', ) ); } return $storage_result; } /** * Delete audio file from disk - delegates to new architecture. * * @param string $audio_url URL of the audio file to delete. * @return bool True if deleted successfully, false otherwise. */ public function delete_audio_file( $audio_url ) { // Try to find post ID from URL to clean up metadata. $post_id = $this->find_post_id_by_url( $audio_url ); if ( $post_id ) { $cleanup_result = $this->file_cleaner->cleanup_post_audio( $post_id ); return ! empty( $cleanup_result['success'] ); } // Fallback to old method. return $this->file_deleter->delete_audio_file( $audio_url ); } /** * Check and fix directory permissions. * * @return bool True if all directories are writable, false otherwise. */ public function check_and_fix_permissions() { return $this->directory_manager->check_and_fix_permissions(); } /** * Get upload directory path. * * @return string Upload directory path. */ public function get_upload_path() { return $this->directory_manager->get_upload_path(); } /** * Get upload directory URL. * * @return string Upload directory URL. */ public function get_upload_url() { return $this->directory_manager->get_upload_url(); } /** * Get file writer instance. * * @return Audio_File_Writer Writer instance. */ public function get_file_writer() { return $this->file_writer; } /** * Get file deleter instance. * * @return Audio_File_Deleter Deleter instance. */ public function get_file_deleter() { return $this->file_deleter; } /** * Get file storage instance. * * @return Audio_File_Storage Storage instance. */ public function get_file_storage() { return $this->file_storage; } /** * Get metadata manager instance. * * @return Audio_File_Metadata Metadata manager. */ public function get_metadata_manager() { return $this->metadata_manager; } /** * Get file cleaner instance. * * @return Audio_File_Cleaner Cleaner instance. */ public function get_file_cleaner() { return $this->file_cleaner; } /** * Find post ID by audio URL. * * @param string $audio_url Audio file URL. * @return int|null Post ID or null if not found. */ private function find_post_id_by_url( string $audio_url ): ?int { global $wpdb; $meta_key = 'accessibility_audio_tts_url'; $cache_key = 'accessibility_audio_tts_post_id_by_url_' . md5( $audio_url ); $post_id = wp_cache_get( $cache_key, 'accessibility_audio_tts' ); if ( false === $post_id ) { // phpcs:ignore WordPress.DB.DirectDatabaseQuery.DirectQuery, WordPress.DB.DirectDatabaseQuery.NoCaching -- Prepared lookup by exact URL (cached below). $post_id = $wpdb->get_var( $wpdb->prepare( "SELECT post_id FROM {$wpdb->postmeta} WHERE meta_key = %s AND meta_value = %s LIMIT 1", $meta_key, $audio_url ) ); wp_cache_set( $cache_key, $post_id, 'accessibility_audio_tts', 300 ); } return $post_id ? (int) $post_id : null; } }