wp_unique_filename() WordPress Function
The wp_unique_filename() function is used to generate a unique filename for a given file. This function is used by the WordPress media uploader to ensure that each file has a unique name when it is uploaded to the server.
wp_unique_filename( string $dir, string $filename, callable $unique_filename_callback = null ) #
Get a filename that is sanitized and unique for the given directory.
Description
If the filename is not unique, then a number will be added to the filename before the extension, and will continue adding numbers until the filename is unique.
The callback function allows the caller to use their own method to create unique file names. If defined, the callback should take three arguments:
- directory, base filename, and extension – and return a unique filename.
Parameters
- $dir
(string)(Required)Directory.
- $filename
(string)(Required)File name.
- $unique_filename_callback
(callable)(Optional)Callback.
Default value: null
Return
(string) New filename, if given wasn't unique.
Source
File: wp-includes/functions.php
2522 2523 2524 2525 2526 2527 2528 2529 2530 2531 2532 2533 2534 2535 2536 2537 2538 2539 2540 2541 2542 2543 2544 2545 2546 2547 2548 2549 2550 2551 2552 2553 2554 2555 2556 2557 2558 2559 2560 2561 2562 2563 2564 2565 2566 2567 2568 2569 2570 2571 2572 2573 2574 2575 2576 2577 2578 2579 2580 2581 2582 2583 2584 2585 2586 2587 2588 2589 2590 2591 2592 2593 2594 2595 2596 2597 2598 2599 2600 2601 2602 2603 2604 2605 2606 2607 2608 2609 2610 2611 2612 2613 2614 2615 2616 2617 2618 2619 2620 2621 2622 2623 2624 2625 2626 2627 2628 2629 2630 2631 2632 2633 2634 2635 2636 2637 2638 2639 2640 2641 2642 2643 2644 2645 2646 2647 2648 2649 2650 2651 2652 2653 2654 2655 2656 2657 2658 2659 2660 2661 2662 2663 2664 2665 2666 2667 2668 2669 2670 2671 2672 2673 2674 2675 2676 2677 2678 2679 2680 2681 2682 2683 2684 2685 2686 2687 2688 2689 2690 2691 2692 2693 2694 2695 2696 2697 2698 2699 2700 2701 2702 2703 2704 2705 2706 2707 2708 2709 2710 2711 2712 2713 2714 2715 2716 2717 2718 2719 2720 2721 2722 2723 2724 2725 2726 2727 2728 2729 2730 2731 2732 2733 2734 2735 2736 2737 2738 2739 2740 2741 2742 2743 2744 2745 2746 2747 2748 2749 2750 2751 2752 2753 2754 2755 2756 2757 2758 2759 2760 2761 2762 2763 2764 2765 2766 2767 2768 | function wp_unique_filename( $dir , $filename , $unique_filename_callback = null ) { // Sanitize the file name before we begin processing. $filename = sanitize_file_name( $filename ); $ext2 = null; // Initialize vars used in the wp_unique_filename filter. $number = '' ; $alt_filenames = array (); // Separate the filename into a name and extension. $ext = pathinfo ( $filename , PATHINFO_EXTENSION ); $name = pathinfo ( $filename , PATHINFO_BASENAME ); if ( $ext ) { $ext = '.' . $ext ; } // Edge case: if file is named '.ext', treat as an empty name. if ( $name === $ext ) { $name = '' ; } /* * Increment the file number until we have a unique file to save in $dir. * Use callback if supplied. */ if ( $unique_filename_callback && is_callable ( $unique_filename_callback ) ) { $filename = call_user_func( $unique_filename_callback , $dir , $name , $ext ); } else { $fname = pathinfo ( $filename , PATHINFO_FILENAME ); // Always append a number to file names that can potentially match image sub-size file names. if ( $fname && preg_match( '/-(?:\d+x\d+|scaled|rotated)$/' , $fname ) ) { $number = 1; // At this point the file name may not be unique. This is tested below and the $number is incremented. $filename = str_replace ( "{$fname}{$ext}" , "{$fname}-{$number}{$ext}" , $filename ); } /* * Get the mime type. Uploaded files were already checked with wp_check_filetype_and_ext() * in _wp_handle_upload(). Using wp_check_filetype() would be sufficient here. */ $file_type = wp_check_filetype( $filename ); $mime_type = $file_type [ 'type' ]; $is_image = ( ! empty ( $mime_type ) && 0 === strpos ( $mime_type , 'image/' ) ); $upload_dir = wp_get_upload_dir(); $lc_filename = null; $lc_ext = strtolower ( $ext ); $_dir = trailingslashit( $dir ); /* * If the extension is uppercase add an alternate file name with lowercase extension. * Both need to be tested for uniqueness as the extension will be changed to lowercase * for better compatibility with different filesystems. Fixes an inconsistency in WP < 2.9 * where uppercase extensions were allowed but image sub-sizes were created with * lowercase extensions. */ if ( $ext && $lc_ext !== $ext ) { $lc_filename = preg_replace( '|' . preg_quote( $ext ) . '$|' , $lc_ext , $filename ); } /* * Increment the number added to the file name if there are any files in $dir * whose names match one of the possible name variations. */ while ( file_exists ( $_dir . $filename ) || ( $lc_filename && file_exists ( $_dir . $lc_filename ) ) ) { $new_number = (int) $number + 1; if ( $lc_filename ) { $lc_filename = str_replace ( array ( "-{$number}{$lc_ext}" , "{$number}{$lc_ext}" ), "-{$new_number}{$lc_ext}" , $lc_filename ); } if ( '' === "{$number}{$ext}" ) { $filename = "{$filename}-{$new_number}" ; } else { $filename = str_replace ( array ( "-{$number}{$ext}" , "{$number}{$ext}" ), "-{$new_number}{$ext}" , $filename ); } $number = $new_number ; } // Change the extension to lowercase if needed. if ( $lc_filename ) { $filename = $lc_filename ; } /* * Prevent collisions with existing file names that contain dimension-like strings * (whether they are subsizes or originals uploaded prior to #42437). */ $files = array (); $count = 10000; // The (resized) image files would have name and extension, and will be in the uploads dir. if ( $name && $ext && @ is_dir ( $dir ) && false !== strpos ( $dir , $upload_dir [ 'basedir' ] ) ) { /** * Filters the file list used for calculating a unique filename for a newly added file. * * Returning an array from the filter will effectively short-circuit retrieval * from the filesystem and return the passed value instead. * * @since 5.5.0 * * @param array|null $files The list of files to use for filename comparisons. * Default null (to retrieve the list from the filesystem). * @param string $dir The directory for the new file. * @param string $filename The proposed filename for the new file. */ $files = apply_filters( 'pre_wp_unique_filename_file_list' , null, $dir , $filename ); if ( null === $files ) { // List of all files and directories contained in $dir. $files = @scandir( $dir ); } if ( ! empty ( $files ) ) { // Remove "dot" dirs. $files = array_diff ( $files , array ( '.' , '..' ) ); } if ( ! empty ( $files ) ) { $count = count ( $files ); /* * Ensure this never goes into infinite loop as it uses pathinfo() and regex in the check, * but string replacement for the changes. */ $i = 0; while ( $i <= $count && _wp_check_existing_file_names( $filename , $files ) ) { $new_number = (int) $number + 1; // If $ext is uppercase it was replaced with the lowercase version after the previous loop. $filename = str_replace ( array ( "-{$number}{$lc_ext}" , "{$number}{$lc_ext}" ), "-{$new_number}{$lc_ext}" , $filename ); $number = $new_number ; $i ++; } } } /* * Check if an image will be converted after uploading or some existing image sub-size file names may conflict * when regenerated. If yes, ensure the new file name will be unique and will produce unique sub-sizes. */ if ( $is_image ) { /** This filter is documented in wp-includes/class-wp-image-editor.php */ $output_formats = apply_filters( 'image_editor_output_format' , array (), $_dir . $filename , $mime_type ); $alt_types = array (); if ( ! empty ( $output_formats [ $mime_type ] ) ) { // The image will be converted to this format/mime type. $alt_mime_type = $output_formats [ $mime_type ]; // Other types of images whose names may conflict if their sub-sizes are regenerated. $alt_types = array_keys ( array_intersect ( $output_formats , array ( $mime_type , $alt_mime_type ) ) ); $alt_types [] = $alt_mime_type ; } elseif ( ! empty ( $output_formats ) ) { $alt_types = array_keys ( array_intersect ( $output_formats , array ( $mime_type ) ) ); } // Remove duplicates and the original mime type. It will be added later if needed. $alt_types = array_unique ( array_diff ( $alt_types , array ( $mime_type ) ) ); foreach ( $alt_types as $alt_type ) { $alt_ext = wp_get_default_extension_for_mime_type( $alt_type ); if ( ! $alt_ext ) { continue ; } $alt_ext = ".{$alt_ext}" ; $alt_filename = preg_replace( '|' . preg_quote( $lc_ext ) . '$|' , $alt_ext , $filename ); $alt_filenames [ $alt_ext ] = $alt_filename ; } if ( ! empty ( $alt_filenames ) ) { /* * Add the original filename. It needs to be checked again * together with the alternate filenames when $number is incremented. */ $alt_filenames [ $lc_ext ] = $filename ; // Ensure no infinite loop. $i = 0; while ( $i <= $count && _wp_check_alternate_file_names( $alt_filenames , $_dir , $files ) ) { $new_number = (int) $number + 1; foreach ( $alt_filenames as $alt_ext => $alt_filename ) { $alt_filenames [ $alt_ext ] = str_replace ( array ( "-{$number}{$alt_ext}" , "{$number}{$alt_ext}" ), "-{$new_number}{$alt_ext}" , $alt_filename ); } /* * Also update the $number in (the output) $filename. * If the extension was uppercase it was already replaced with the lowercase version. */ $filename = str_replace ( array ( "-{$number}{$lc_ext}" , "{$number}{$lc_ext}" ), "-{$new_number}{$lc_ext}" , $filename ); $number = $new_number ; $i ++; } } } } /** * Filters the result when generating a unique file name. * * @since 4.5.0 * @since 5.8.1 The `$alt_filenames` and `$number` parameters were added. * * @param string $filename Unique file name. * @param string $ext File extension. Example: ".png". * @param string $dir Directory path. * @param callable|null $unique_filename_callback Callback function that generates the unique file name. * @param string[] $alt_filenames Array of alternate file names that were checked for collisions. * @param int|string $number The highest number that was used to make the file name unique * or an empty string if unused. */ return apply_filters( 'wp_unique_filename' , $filename , $ext , $dir , $unique_filename_callback , $alt_filenames , $number ); } |
Expand full source codeCollapse full source codeView on TracView on GitHub
Changelog
Version | Description |
---|---|
2.5.0 | Introduced. |