文件操作 - FileUploader.php
返回文件管理
返回主菜单
删除本文件
文件: /home/www/public/wp-content/plugins/tutor/components/FileUploader.php
编辑文件内容
<?php /** * FileUploader Component Class. * * @package Tutor\Components * @author Themeum * @link https://themeum.com * @since 4.0.0 */ namespace Tutor\Components; defined( 'ABSPATH' ) || exit; use Tutor\Components\Constants\Size; use Tutor\Components\Constants\Variant; use TUTOR\Icon; use Tutor\Components\Button; use Tutor\Components\AttachmentCard; /** * Class FileUploader * * Example Usage: * ```php * // Native single-file upload * FileUploader::make() * ->name( 'resume' ) * ->accept( '.pdf,.doc' ) * ->render(); * * // Native multiple-file upload with size/count limits * FileUploader::make() * ->name( 'course_attachments' ) * ->uploader_title( __( 'Upload Assignments', 'tutor' ) ) * ->uploader_subtitle( __( 'Supports PDF, DOCX — max 20 MB each', 'tutor' ) ) * ->accept( '.pdf,.docx' ) * ->multiple( true ) * ->max_files( 3 ) * ->max_size( 20 * 1024 * 1024 ) * ->render(); * * // Image uploader (native file input, image preview variant) * FileUploader::make() * ->variant( FileUploader::IMAGE_UPLOADER ) * ->name( 'cover_photo' ) * ->accept( '.jpg,.jpeg,.png,.webp' ) * ->render(); * * // WP Media Library — single image * FileUploader::make() * ->variant( FileUploader::IMAGE_UPLOADER ) * ->use_wp_media( true ) * ->wp_media_library_type( 'image' ) * ->wp_media_title( __( 'Select Profile Photo', 'tutor' ) ) * ->wp_media_button_text( __( 'Use This Photo', 'tutor' ) ) * ->name( 'profile_photo' ) * ->render(); * * // WP Media Library — multiple documents * FileUploader::make() * ->use_wp_media( true ) * ->multiple( true ) * ->wp_media_library_type( 'application/pdf,application/msword' ) * ->name( 'shared_files' ) * ->render(); * * // Custom icon, title, subtitle and button text * FileUploader::make() * ->name( 'resources' ) * ->uploader_icon( Icon::RESOURCES ) * ->uploader_icon_size( 32 ) * ->uploader_title( __( 'Resource Center', 'tutor' ) ) * ->uploader_subtitle( __( 'Add any relevant documents here', 'tutor' ) ) * ->uploader_button_text( __( 'Choose Resources', 'tutor' ) ) * ->render(); * * // Required upload with an ID and Alpine.js callbacks * FileUploader::make() * ->name( 'assignment_file' ) * ->id( 'assignment-upload' ) * ->required( true ) * ->accept( '.pdf' ) * ->attr( 'onFileSelect', 'handleFileSelect' ) * ->attr( 'onError', 'handleUploadError' ) * ->render(); * * // Retrieve HTML without echoing * $html = FileUploader::make()->name( 'attachment' )->get(); * ``` * * @since 4.0.0 */ class FileUploader extends BaseComponent { /** * Variant constants. * * @since 4.0.0 */ public const FILE_UPLOADER = 'file-uploader'; public const IMAGE_UPLOADER = 'image-uploader'; /** * File uploader accept attribute. * * @since 4.0.0 * * @var string */ protected $accept = '.pdf,.doc,.docx,.jpg,.jpeg,.png'; /** * File uploader max size. * * @since 4.0.0 * * @var int */ protected $max_size = null; /** * File uploader max files. * * @since 4.0.0 * * @var int|null */ protected $max_files = null; /** * File uploader icon. * * @since 4.0.0 * * @var string */ protected $uploader_icon = Icon::UPLOAD_FILE; /** * File uploader title. * * @since 4.0.0 * * @var string */ protected $uploader_title = ''; /** * File uploader subtitle. * * @since 4.0.0 * * @var string */ protected $uploader_subtitle = ''; /** * File uploader button text. * * @since 4.0.0 * * @var string */ protected $uploader_button_text = ''; /** * Component variant. * * @since 4.0.0 * * @var string */ protected $variant = self::FILE_UPLOADER; /** * Whether to use WordPress media library instead of native file input. * * @since 4.0.0 * * @var bool */ protected $use_wp_media = false; /** * Title for WordPress media modal. * * @since 4.0.0 * * @var string */ protected $wp_media_title = ''; /** * Button text for WordPress media modal. * * @since 4.0.0 * * @var string */ protected $wp_media_button_text = ''; /** * Library type filter for WordPress media (image, video, audio, application). * * @since 4.0.0 * * @var string */ protected $wp_media_library_type = ''; /** * Whether multiple option can be selected in input. * * @since 4.0.0 * * @var boolean */ protected $multiple = false; /** * InputField name attribute. * * @since 4.0.0 * * @var string */ protected $name = ''; /** * InputField ID attribute. * * @since 4.0.0 * * @var string */ protected $id = ''; /** * Whether input is required. * * @since 4.0.0 * * @var bool */ protected $required = false; /** * InputField value. * * @since 4.0.0 * * @var string */ protected $value = ''; /** * Upload icon size. * * @since 4.0.0 * * @var integer */ protected $upload_icon_size = 24; /** * Set uploader accept attribute. * * Common types: .pdf, .doc, .docx, .jpg, .jpeg, .png * For WP Media: image, video, audio, application * * @since 4.0.0 * * @param string $accept Accept attribute. * * @return $this */ public function accept( $accept ) { $this->accept = $accept; return $this; } /** * Set uploader max size. * * @since 4.0.0 * * @param int $max_size Max size in bytes. * * @return $this */ public function max_size( $max_size = null ) { if ( null === $max_size ) { $max_size = wp_max_upload_size(); } $this->max_size = $max_size; return $this; } /** * Set uploader max files. * * @since 4.0.0 * * @param int|null $max_files Maximum number of selectable files. * * @return $this */ public function max_files( $max_files = null ) { $this->max_files = null !== $max_files ? (int) $max_files : null; return $this; } /** * Set uploader icon. * * @since 4.0.0 * * @param string $icon Icon name. * * @return $this */ public function uploader_icon( $icon ) { $this->uploader_icon = $icon; return $this; } /** * Set uploader icon size. * * @since 4.0.0 * * @param int $size Icon size. * * @return $this */ public function uploader_icon_size( $size ) { $this->upload_icon_size = $size; return $this; } /** * Set uploader title. * * @since 4.0.0 * * @param string $title Title text. * * @return $this */ public function uploader_title( $title ) { $this->uploader_title = $title; return $this; } /** * Set uploader subtitle. * * @since 4.0.0 * * @param string $subtitle Subtitle text. * * @return $this */ public function uploader_subtitle( $subtitle ) { $this->uploader_subtitle = $subtitle; return $this; } /** * Set uploader button text. * * @since 4.0.0 * * @param string $button_text Button text. * * @return $this */ public function uploader_button_text( $button_text ) { $this->uploader_button_text = $button_text; return $this; } /** * Set component variant. * * @since 4.0.0 * * @param string $variant Component variant (file-uploader|image-uploader). * * @return $this */ public function variant( $variant ) { $this->variant = $variant; return $this; } /** * Set use WordPress media library. * * @since 4.0.0 * * @param bool $use_wp_media Use WP media library. * * @return $this */ public function use_wp_media( $use_wp_media = true ) { $this->use_wp_media = (bool) $use_wp_media; return $this; } /** * Set WP media title. * * @since 4.0.0 * * @param string $wp_media_title WP media title. * * @return $this */ public function wp_media_title( $wp_media_title ) { $this->wp_media_title = $wp_media_title; return $this; } /** * Set WP media button text. * * @since 4.0.0 * * @param string $wp_media_button_text WP media button text. * * @return $this */ public function wp_media_button_text( $wp_media_button_text ) { $this->wp_media_button_text = $wp_media_button_text; return $this; } /** * Set WP media library type. * * Common types: image, video, audio, application, text * * @since 4.0.0 * * @param string $wp_media_library_type WP media library type. * * @return $this */ public function wp_media_library_type( $wp_media_library_type ) { $this->wp_media_library_type = $wp_media_library_type; return $this; } /** * Set multiple. * * @since 4.0.0 * * @param bool $multiple Multiple. * * @return $this */ public function multiple( $multiple = true ) { $this->multiple = (bool) $multiple; return $this; } /** * Set input name. * * @since 4.0.0 * * @param string $name Name. * * @return $this */ public function name( $name ) { $this->name = sanitize_key( $name ); return $this; } /** * Set input ID. * * @since 4.0.0 * * @param string $id InputField ID. * * @return $this */ public function id( $id ) { $this->id = sanitize_key( $id ); return $this; } /** * Set required. * * @since 4.0.0 * * @param bool $required Required. * * @return $this */ public function required( $required = true ) { $this->required = $required; return $this; } /** * Set value. * * @since 4.0.0 * * @param string $value Value. * * @return $this */ public function value( $value ) { $this->value = $value; return $this; } /** * Get component content * * @return string */ public function get(): string { $multiple = $this->multiple; $accept = $this->accept; $max_size = $this->max_size ?? wp_max_upload_size(); $max_files = $this->max_files; $icon = $this->uploader_icon; $title = ! empty( $this->uploader_title ) ? $this->uploader_title : __( 'Drop files here or click to upload', 'tutor' ); $subtitle = ! empty( $this->uploader_subtitle ) ? $this->uploader_subtitle : ''; $button_text = ! empty( $this->uploader_button_text ) ? $this->uploader_button_text : __( 'Select Files', 'tutor' ); $on_file_select = $this->attributes['onFileSelect'] ?? 'null'; $on_error = $this->attributes['onError'] ?? 'null'; $on_file_remove = $this->attributes['onFileRemove'] ?? 'null'; $variant = $this->variant; $uploader_attributes = $this->attributes; // Remove Alpine specific attributes from HTML attributes. unset( $uploader_attributes['onFileSelect'] ); unset( $uploader_attributes['onError'] ); $this->attributes = $uploader_attributes; ob_start(); ?> <div class="tutor-file-uploader-wrapper" x-data="tutorFileUploader({ multiple: <?php echo $multiple ? 'true' : 'false'; ?>, maxFiles: <?php echo null !== $max_files ? (int) $max_files : 'undefined'; ?>, accept: '<?php echo esc_attr( $accept ); ?>', maxSize: <?php echo (int) $max_size; ?>, onFileSelect: <?php echo esc_js( $on_file_select ); ?>, onFileRemove: <?php echo esc_js( $on_file_remove ); ?>, onError: <?php echo esc_js( $on_error ); ?>, variant: '<?php echo esc_attr( $variant ); ?>', value: values.<?php echo esc_attr( $this->name ); ?>, name: '<?php echo esc_attr( $this->name ); ?>', required: <?php echo is_bool( $this->required ) ? ( $this->required ? 'true' : 'false' ) : "'" . esc_js( $this->required ) . "'"; ?>, useWPMedia: <?php echo $this->use_wp_media ? 'true' : 'false'; ?>, wpMediaTitle: '<?php echo esc_js( $this->wp_media_title ); ?>', wpMediaButtonText: '<?php echo esc_js( $this->wp_media_button_text ); ?>', wpMediaLibraryType: '<?php echo esc_js( $this->wp_media_library_type ); ?>', })" > <template x-if="imagePreview"> <div class="tutor-file-preview"> <img :src="imagePreview" alt="Preview"> <div class="tutor-file-preview-overlay"> <div class="tutor-file-preview-actions"> <?php Button::make() ->label( __( 'Delete', 'tutor' ) ) ->variant( Variant::DESTRUCTIVE ) ->size( Size::SMALL ) ->attr( 'type', 'button' ) ->attr( '@click.stop', 'removeFile()' ) ->render(); Button::make() ->label( __( 'Upload New', 'tutor' ) ) ->variant( Variant::PRIMARY ) ->size( Size::SMALL ) ->attr( 'type', 'button' ) ->attr( '@click.stop', 'openFileDialog()' ) ->render(); ?> </div> </div> </div> </template> <template x-if="variant === 'file-uploader' && selectedFiles.length > 0"> <div class="tutor-flex tutor-flex-column tutor-gap-5"> <div class="tutor-grid tutor-grid-cols-2 tutor-sm-grid-cols-1 tutor-gap-5"> <template x-for="(file, index) in selectedFiles" :key="index"> <div class="tutor-attachment-card-wrapper"> <?php AttachmentCard::make() ->title_attr( 'x-text', 'file.name' ) ->meta_attr( 'x-text', 'formatBytes(file.size)' ) ->action_attr( '@click.stop', 'removeFile(index)' ) ->render(); ?> </div> </template> </div> <div x-show="maxFiles > selectedFiles.length" class="tutor-mt-1"> <button type="button" class="tutor-btn tutor-btn-primary-soft tutor-sm-w-full" @click="openFileDialog()"> <?php $this->multiple ? esc_html_e( 'Upload More Files', 'tutor' ) : esc_html_e( 'Upload Again', 'tutor' ); ?> </button> </div> </div> </template> <!-- Upload Area --> <div x-show="!imagePreview && (variant !== 'file-uploader' || selectedFiles.length === 0)" class="tutor-file-uploader" :class="{ 'tutor-file-uploader-drag-over': isDragOver, 'tutor-file-uploader-disabled': isDisabled }" @click="openFileDialog()" @dragover.prevent="handleDragOver($event)" @dragleave.prevent="handleDragLeave($event)" @drop.prevent="handleDrop($event)" <?php echo self::IMAGE_UPLOADER === $variant ? 'data-image-uploader' : ''; ?> > <input type="file" class="tutor-file-uploader-input" :multiple="multiple" :accept="accept" :disabled="isDisabled" x-ref="fileInput" @change="handleFileSelect($event)" name="<?php echo esc_attr( $this->name ); ?>" id="<?php echo esc_attr( ! empty( $this->id ) ? $this->id : $this->name ); ?>" <?php echo $this->get_attributes_string(); // phpcs:ignore WordPress.Security.EscapeOutput.OutputNotEscaped ?> > <div class="tutor-file-uploader-icon"> <?php SvgIcon::make()->name( $icon )->size( $this->upload_icon_size )->render(); ?> </div> <div class="tutor-file-uploader-content"> <p class="tutor-file-uploader-title"><?php echo esc_html( $title ); ?></p> <?php if ( ! empty( $subtitle ) ) : ?> <p class="tutor-file-uploader-subtitle"><?php echo esc_html( $subtitle ); ?></p> <?php endif; ?> </div> <button type="button" class="tutor-btn tutor-btn-primary-soft" :disabled="isDisabled"> <?php echo esc_html( $button_text ); ?> </button> </div> </div> <?php $this->component_string = ob_get_clean(); return $this->component_string; } }
修改文件时间
将文件时间修改为当前时间的前一年
删除文件