plugin_name = $plugin_name; $this->version = $version; $this->db_manager = QDR_TSS_DB_Manager::instance(); $this->file_manager = QDR_TSS_File_Manager::instance(); $this->settings = QDR_TSS_Settings::instance(); } /** * Register the REST API routes. * * @since 1.0.0 */ public function register_routes() { // Chunked upload endpoints register_rest_route($this->namespace, '/upload/init', array( 'methods' => WP_REST_Server::CREATABLE, 'callback' => array($this, 'init_chunked_upload'), 'permission_callback' => array($this, 'check_permission'), )); register_rest_route($this->namespace, '/upload/chunk', array( 'methods' => WP_REST_Server::CREATABLE, 'callback' => array($this, 'upload_chunk'), 'permission_callback' => array($this, 'check_permission'), )); register_rest_route($this->namespace, '/upload/finalize', array( 'methods' => WP_REST_Server::CREATABLE, 'callback' => array($this, 'finalize_chunked_upload'), 'permission_callback' => array($this, 'check_permission'), )); } /** * Check permission for REST API requests. * * @since 1.0.0 * @return bool True if authorized, false otherwise. */ public function check_permission() { $rest_controller = new QDR_TSS_REST_Controller($this->plugin_name, $this->version); return $rest_controller->check_rest_permission(); } /** * Initialize chunked upload. * * @since 1.0.0 * @param WP_REST_Request $request Full details about the request. * @return WP_REST_Response|WP_Error Response object on success, or WP_Error object on failure. */ public function init_chunked_upload($request) { // Check required parameters if (!isset($request['original_file_name']) || !isset($request['file_size'])) { return new WP_Error( 'qdr_tss_missing_params', __('Missing required parameters.', 'qdr-temporary-shared-storage'), array('status' => 400) ); } $file_size = (int) $request['file_size']; $max_upload_size = $this->settings->get_setting('max_upload_size'); // Check max upload size if ($file_size > $max_upload_size) { return new WP_Error( 'qdr_tss_file_too_large', __('File exceeds maximum upload size.', 'qdr-temporary-shared-storage'), array('status' => 400) ); } // Check total storage usage if ($this->db_manager->would_exceed_storage_limit($file_size, $max_upload_size)) { return new WP_Error( 'qdr_tss_storage_limit', __('Storage limit exceeded.', 'qdr-temporary-shared-storage'), array('status' => 400) ); } // Initialize chunked upload $upload_id = $this->file_manager->init_chunked_upload(); if (!$upload_id) { return new WP_Error( 'qdr_tss_init_failed', __('Failed to initialize upload.', 'qdr-temporary-shared-storage'), array('status' => 500) ); } return new WP_REST_Response(array( 'upload_id' => $upload_id, 'status' => 'initialized' ), 200); } /** * Upload a chunk. * * @since 1.0.0 * @param WP_REST_Request $request Full details about the request. * @return WP_REST_Response|WP_Error Response object on success, or WP_Error object on failure. */ public function upload_chunk($request) { // Check required parameters if (!isset($request['upload_id']) || !isset($request['chunk_index']) || !isset($request['total_chunks'])) { return new WP_Error( 'qdr_tss_missing_params', __('Missing required parameters.', 'qdr-temporary-shared-storage'), array('status' => 400) ); } $upload_id = $request['upload_id']; $chunk_index = (int) $request['chunk_index']; $total_chunks = (int) $request['total_chunks']; // Handle file upload $files = $request->get_file_params(); if (empty($files) || !isset($files['chunk'])) { return new WP_Error( 'qdr_tss_no_file', __('No file uploaded.', 'qdr-temporary-shared-storage'), array('status' => 400) ); } $chunk_file = $files['chunk']; // Store chunk $result = $this->file_manager->store_chunk($upload_id, $chunk_index, $chunk_file); if (!$result) { return new WP_Error( 'qdr_tss_chunk_failed', __('Failed to upload chunk.', 'qdr-temporary-shared-storage'), array('status' => 500) ); } return new WP_REST_Response(array( 'upload_id' => $upload_id, 'chunk_index' => $chunk_index, 'status' => 'chunk_uploaded' ), 200); } /** * Finalize chunked upload. * * @since 1.0.0 * @param WP_REST_Request $request Full details about the request. * @return WP_REST_Response|WP_Error Response object on success, or WP_Error object on failure. */ public function finalize_chunked_upload($request) { // Check required parameters if (!isset($request['upload_id']) || !isset($request['total_chunks'])) { return new WP_Error( 'qdr_tss_missing_params', __('Missing required parameters.', 'qdr-temporary-shared-storage'), array('status' => 400) ); } $upload_id = $request['upload_id']; $total_chunks = (int) $request['total_chunks']; // Check for required file metadata $required_fields = array('original_file_name', 'description', 'password'); foreach ($required_fields as $field) { if (!isset($request[$field]) || empty($request[$field])) { return new WP_Error( 'qdr_tss_missing_field', sprintf(__('Missing required field: %s', 'qdr-temporary-shared-storage'), $field), array('status' => 400) ); } } // Check that all chunks are present if (!$this->file_manager->check_all_chunks($upload_id, $total_chunks)) { return new WP_Error( 'qdr_tss_missing_chunks', __('Not all chunks have been uploaded.', 'qdr-temporary-shared-storage'), array('status' => 400) ); } // Finalize upload $result = $this->file_manager->finalize_chunked_upload( $upload_id, $total_chunks, $request['original_file_name'] ); if (!$result) { return new WP_Error( 'qdr_tss_finalize_failed', __('Failed to finalize upload.', 'qdr-temporary-shared-storage'), array('status' => 500) ); } $file_path = $result['file_path']; $file_size = $result['file_size']; // Set dates $active_from = !empty($request['active_from']) ? $request['active_from'] : current_time('mysql'); $active_to = !empty($request['active_to']) ? $request['active_to'] : date('Y-m-d H:i:s', strtotime('+30 days')); // Generate a unique media ID $media_id = time() . rand(1000, 9999); // Insert into database $data = array( 'media_id' => $media_id, 'original_file_name' => sanitize_file_name($request['original_file_name']), 'description' => sanitize_textarea_field($request['description']), 'message' => isset($request['message']) ? sanitize_textarea_field($request['message']) : '', 'active_from' => $active_from, 'active_to' => $active_to, 'password' => wp_hash_password($request['password']), 'reference' => isset($request['reference']) ? sanitize_text_field($request['reference']) : '', 'upload_date' => current_time('mysql'), 'file_path' => $file_path, 'file_size' => $file_size ); $item_id = $this->db_manager->insert_item($data); if (!$item_id) { // Delete file if database insert fails $this->file_manager->delete_file($file_path); return new WP_Error( 'qdr_tss_db_failed', __('Failed to save file information.', 'qdr-temporary-shared-storage'), array('status' => 500) ); } $download_url = site_url('shared-file-download/' . $media_id); $shortcode = '[qdr_tss_download id="' . $media_id . '"]'; return new WP_REST_Response(array( 'media_id' => $media_id, 'permalink' => $download_url, 'shortcode' => $shortcode ), 201); } }