Файловый менеджер - Редактировать - /home/harasnat/www/labour/wp-content/plugins/events-manager/classes/uploads/em-uploads-api.php
Назад
<?php namespace EM\Uploads; use WP_REST_Response, EM_Exception; class API { public static $temp_file_expiration = 1800; public static function init() { add_action('rest_api_init', [ static::class, 'register_routes' ]); add_action('init', [ static::class, 'schedule_cleanup']); add_action('em_uploads_api_cleanup', [ static::class, 'run_cleanup']); } /** * Schedules the WP-Cron event if it is not already scheduled. */ public static function schedule_cleanup() { if ( !wp_next_scheduled('em_uploads_api_cleanup') ) { wp_schedule_event(time(), 'hourly', 'em_uploads_api_cleanup'); } } /** * Runs the cleanup process, deleting expired temporary files. */ public static function run_cleanup() { // Get the temporary upload directory (fallback to system temp dir) $temp_dir = ini_get('upload_tmp_dir') ?: sys_get_temp_dir(); if (!$temp_dir || !is_dir($temp_dir)) { return; } $files = glob($temp_dir. DIRECTORY_SEPARATOR . '*' . Uploader::$temp_suffix ); $now = time(); foreach ($files as $file) { if ( !is_file($file) ) { continue; } $file_age = $now - filemtime($file); if ( $file_age > static::$temp_file_expiration ) { unlink($file); } } } public static function register_routes() { $namespace = 'events-manager/v1'; // basic upload and revert functions, do not necessarily need overriding to act register_rest_route($namespace, '/uploads', [ 'methods' => 'POST', 'callback' => [ static::class, 'handle_upload'], 'permission_callback' => '__return_true', ]); register_rest_route($namespace, '/uploads', [ 'methods' => 'DELETE', 'callback' => [ static::class, 'handle_revert' ], 'permission_callback' => '__return_true', ]); // getting and deleting previously uploaded files, needs filter handling passed by query params register_rest_route( $namespace, '/uploads', [ 'methods' => 'GET', 'callback' => [ static::class, 'handle_load' ], 'permission_callback' => [ static::class, 'permission_callback' ], ] ); /* register_rest_route( $namespace, '/uploads', [ 'methods' => 'DELETE', 'callback' => [ static::class, 'handle_delete' ], 'permission_callback' => [ static::class, 'permission_callback' ], ] ); */ } /** * Recursively search an array for a subarray that looks like a file upload array. * * @param array $array The array to search. * @return array|null The first found file array, or null if none is found. */ public static function find_nested_upload_array(array $array) { $expected_keys = ['tmp_name', 'name', 'error', 'size', 'type']; // Check if the current array has all expected keys. if ( count( array_intersect_key( $array, array_flip( $expected_keys ) ) ) === count($expected_keys) ) { return $array; } // Recursively search in subarrays. foreach ($array as $item) { if ( is_array($item) ) { $result = static::find_nested_upload_array( $item ); if ( $result !== null ) { return $result; } } } return null; } /** * @param \WP_REST_Request $request * * @return WP_REST_Response */ public static function handle_upload( $request ) { $nonce = $request->get_header('X-EM-Nonce'); $path = urldecode($request->get_param('path')); if ( !wp_verify_nonce( sanitize_text_field($nonce), 'em_uploads_api/'.$path ) ) { return new WP_REST_Response( array( 'success' => false, 'error' => 'Invalid uploads Nonce.' ), 403 ); } if ( empty( $_FILES ) ) { return new WP_REST_Response( array( 'success' => false, 'error' => 'No file uploaded or invalid file data.' ), 400 ); } $upload_key = key( $_FILES ); // clean the $_FILES to bring a highly nested upload to the top-level, we only expect one upload and need only know the key not the whole path // examples of this could be for an attendee of event, e.g. ticket_id > attendee_id > field_name $recursive_current = function ($value) { while (is_array($value)) { $value = current($value); } return $value; }; // handle possibility of input field using an array, and make $_FILES an array for validation purposes if ( is_array($_FILES[$upload_key]['tmp_name']) ) { $file = []; foreach ($_FILES[$upload_key] as $key => $value) { $file[$key] = $recursive_current($value); $_FILES[$upload_key][$key] = [ $file[$key] ]; // for later, 'flattened' as a simple field uploaded } } else { $file = $_FILES[ $upload_key ]; foreach( $_FILES[ $upload_key ] as $key => $value ) { $_FILES[ $upload_key ][ $key ] = [ $value ]; } } // Ensure the file was properly uploaded if ( empty($file['tmp_name']) || !is_uploaded_file( $file['tmp_name'] ) ) { return new WP_REST_Response( array( 'success' => false, 'error' => 'Failed to process the uploaded file.' ), 422 ); } // allow for validation from extenral forces, either by performing a validation forcing false/true/WP_Error, or by supplying options to pass by Uploader::validate() $validate_options = apply_filters('em_uploads_api_upload_validate_options_' . $path, ['type' => ['image']], $upload_key, $file); $valid = apply_filters('em_uploads_api_upload_validate_' . $path, null, $upload_key, $file); if ( $valid === null ) { try { $valid = Uploader::validate( $upload_key, $validate_options ); } catch ( EM_Exception $e ) { $errors = $e->get_messages(); return new WP_REST_Response( array( 'success' => false, 'error' => implode(', ', $errors), 'errors' => $errors ), 422 ); } } if ( !$valid ) { return new WP_REST_Response( array( 'success' => false, 'error' => 'Failed to validate the uploaded file.' ), 422 ); } elseif ( is_wp_error($valid) ) { /* @var \WP_Error $valid */ $errors = $valid->get_error_messages(); return new WP_REST_Response( array( 'success' => false, 'error' => implode(', ', $errors), 'errors' => $errors ), 422 ); } // move the upload so it's not automaticall deleted, but can be deleted by our cronjob if ( !move_uploaded_file( $file['tmp_name'], $file['tmp_name'] . Uploader::$temp_suffix ) ) { return new WP_REST_Response( array( 'success' => false, 'error' => 'Failed to temporarily store the uploaded file.' ), 422 ); } $file_id = basename($file['tmp_name'] ); // fire hooks allowing validation, we advise specific validation via path, e.g. em_uploads_api_handle_upload/event-image $response = apply_filters('em_uploads_api_handle_upload', [ 'data' => [ 'success' => true, 'file' => array( 'id' => $file_id, 'name' => sanitize_file_name( $file['name'] ), 'size' => $file['size'], 'type' => $file['type'], ), 'nonce' => wp_create_nonce( 'em_uploads_api_file_' . $file_id ) ], 'status' => 200, 'headers' => [], ], $request); $response = apply_filters('em_uploads_api_handle_upload/' . $path, $response, $request); // return response return new WP_REST_Response( $response['data'], $response['status'], $response['headers'] ); } /** * Deletes a file that was uploaded but not yet saved. Requires nonce provided when uploaded originally. * * @param $request * * @return WP_REST_Response */ public static function handle_revert($request) { $file_id = $request->get_param('tmp_file'); $nonce = $request->get_param('nonce'); if (!wp_verify_nonce($nonce, 'em_uploads_api_file_' . $file_id)) { return new WP_REST_Response(['success' => false, 'error' => 'Invalid nonce.'], 403); } $tempUploadDir = ini_get('upload_tmp_dir') ?: sys_get_temp_dir(); // Fallback if not set $tmp_path = trailingslashit($tempUploadDir). $file_id . '-em-uploader'; if ( file_exists($tmp_path) && is_writable($tmp_path) ) { unlink($tmp_path); return new WP_REST_Response(['success' => true, 'message' =>'File deleted.'], 200); } return new WP_REST_Response(['success' => false, 'error' => 'File not found or not writable.'], 404); } public static function handle_load( $request ) { // Get the file_id parameter from the request if this is for a temp file $temp_id = $request->get_param('temp_id'); if( $temp_id ) { // Determine the temporary upload directory. $tempUploadDir = ini_get('upload_tmp_dir') ?: sys_get_temp_dir(); // Build the full file path. $file_path = trailingslashit( $tempUploadDir ) . $temp_id . '-em-uploader'; // Check if the file exists and is readable. if ( file_exists( $file_path ) && is_readable( $file_path ) ) { // Get the file contents and MIME type. $file_contents = file_get_contents( $file_path ); $mime_type = mime_content_type( $file_path ); // get filename if exists $filenames = json_decode( $request->get_header('X-Filenames') , true); $filename = !empty($filenames[$temp_id]) ? sanitize_file_name($filenames[$temp_id]['name']) : 'unknown'; // Create a WP_REST_Response object with the file contents. $response = new WP_REST_Response( $file_contents, 200 ); $response->set_headers( [ 'Content-Type' => $mime_type, 'Content-Disposition' => 'inline; filename="'. $filename .'"' ] ); /** * Use the rest_pre_serve_request filter to output the raw data. * This filter checks if the response has a Content-Type header that isn’t JSON, * and if so, echoes the raw file contents directly. */ add_filter( 'rest_pre_serve_request', function( $served, $result, $request, $server ) { if ( $result instanceof WP_REST_Response ) { $headers = $result->get_headers(); // If the Content-Type is not JSON, then serve raw data. if ( ! empty( $headers['Content-Type'] ) && false === strpos( $headers['Content-Type'], 'application/json' ) ) { // Send the headers. header( 'Content-Type: ' . $headers['Content-Type'] ); header( 'Content-Disposition: ' . $headers['Content-Disposition'] ); // Output the raw file contents. echo $result->get_data(); return true; // We've handled serving the response. } } return $served; }, 10, 4 ); return $response; } } // Return an error response if the file cannot be found. return new WP_REST_Response( [ 'success' => false, 'error' => 'File not found.' ], 404 ); } /** * @deprecated Not in use yet. * * Handles deleting a file on a form with previously uploaded data. Validates a nonce and then fires a hook if nonce passes. * * Any function hooking into this needs to verify capabilities before performing any actions on deletions. * * @param $request * * @return WP_REST_Response */ public static function handle_delete ( $request ) { $nonce = $request->get_header('nonce'); $object = $request->get_param('path'); $file_id = $request->get_param( 'id' ); $nonce_action = $object ? '/'. $object : ''; $nonce_action .= $file_id ? '/' . $file_id : ''; if ( !wp_verify_nonce( $nonce, 'em_uploads_api_file/' . $nonce_action ) ) { return new WP_REST_Response( [ 'success' => false, 'success' => false, 'error' => 'File not deleted, failed nonce.' ], 200 ); } // fire a hook and return false, WP_Error or true if deleted $result = apply_filters('em_uploads_api_delete_' . $object, false, $request->get_params(), $request ); if ( is_wp_error( $result ) ) { $response_result = false; $response_message = $result->get_error_message(); } else { $response_result = $result === true; $response_message = $response_result ? 'File deleted.' : 'File not deleted.'; } return new WP_REST_Response( [ 'success' => $response_result, 'message' => $response_message ], 200 ); } public static function permission_callback() { return true; } } API::init();
| ver. 1.4 |
Github
|
.
| PHP 8.1.33 | Генерация страницы: 0 |
proxy
|
phpinfo
|
Настройка