@Arh1diablo
Web мастер

Как разрешить авторам загружать файлы из фронтэнда в WP?

У меня есть рабочий код ajax загрузки (взятый от сюда) для WP, чтобы пользователи могли загружать файлы с темы:

PHP код + JS код

// скрипт
add_action( 'wp_footer', 'ajax_file_upload_jscode' );

// AJAX обработчик
add_action( 'wp_ajax_'.'ajax_fileload',        'ajax_file_upload_callback' );
add_action( 'wp_ajax_nopriv_'.'ajax_fileload', 'ajax_file_upload_callback' );



// JS код
function ajax_file_upload_jscode(){
    ?>
    <script>
        jQuery(document).ready(function($){

            // ссылка на файл AJAX  обработчик
            var ajaxurl = '<?= admin_url('admin-ajax.php') ?>';
            var nonce   = '<?= wp_create_nonce('uplfile') ?>';

            var files; // переменная. будет содержать данные файлов

            // заполняем переменную данными, при изменении значения поля file
            $('input[type=file]').on('change', function(){
                files = this.files;
            });

            // обработка и отправка AJAX запроса при клике на кнопку upload_files
            $('.upload_files').on( 'click', function( event ){

                event.stopPropagation(); // остановка всех текущих JS событий
                event.preventDefault();  // остановка дефолтного события для текущего элемента - клик для <a> тега

                // ничего не делаем если files пустой
                if( typeof files == 'undefined' ) return;

                // создадим данные файлов в подходящем для отправки формате
                var data = new FormData();
                $.each( files, function( key, value ){
                    data.append( key, value );
                });

                /* SiteSeed под шумок, добавил счетчик элементов которые есть с изображениями и наш счетчик стартует с кол-ва элементов класса id_imgs_count */
                data.append( 'id_imgs_count', $('.id_imgs_count').length );

                // добавим переменную идентификатор запроса
                data.append( 'action', 'ajax_fileload' );
                data.append( 'nonce', nonce );
                let pid_match = $(document.body).attr('class').match( /postid-([0-9]+)/ );
                data.append( 'post_id', pid_match ? pid_match[1] : 0 );

                var $reply = $('.ajax-reply');

                // AJAX запрос
                /*$reply.text( 'Загружаю...' );*/
                $.ajax({
                    url         : ajaxurl,
                    type        : 'POST',
                    data        : data,
                    cache       : false,
                    dataType    : 'json',
                    // отключаем обработку передаваемых данных, пусть передаются как есть
                    processData : false,
                    // отключаем установку заголовка типа запроса. Так jQuery скажет серверу что это строковой запрос
                    contentType : false,
                    // функция успешного ответа сервера
                    success     : function( respond, status, jqXHR ){
                        // ОК
                        if( respond.success ){
                            $.each( respond.data, function( key, val ){
                                $reply.append( val );
                            } );
                        }
                        // error
                        else {
                            $reply.text( 'ОШИБКА: ' + respond.error );
                        }
                    },
                    // функция ошибки ответа сервера
                    error: function( jqXHR, status, errorThrown ){
                        $reply.text( 'ОШИБКА AJAX запроса: ' + status );
                    }

                });

            });

        })
    </script>
    <?php
}

// обработчик AJAX запроса
function ajax_file_upload_callback(){

    check_ajax_referer( 'uplfile', 'nonce' ); // защита

    if( empty($_FILES) )
        wp_send_json_error( 'Файлов нет...' );

    $post_id = (int) $_POST['post_id'];


    /* SiteSeed добавил счетчик,считает кол-во элементов с одним класом и добавляет кол-во в счетчик, что бы не перезатирать уже имеющиеся ID */
    $id_imgs_count = (int) $_POST['id_imgs_count'];

    // ограничим размер загружаемой картинки
    $sizedata = getimagesize( $_FILES['upfile']['tmp_name'] );
    $max_size = 2000;
    if( $sizedata[0]/*width*/ > $max_size || $sizedata[1]/*height*/ > $max_size )
        wp_send_json_error( __('Картинка не может быть больше чем '. $max_size .'px в ширину или высоту...','km') );

    // обрабатываем загрузку файла
    require_once ABSPATH . 'wp-admin/includes/image.php';
    require_once ABSPATH . 'wp-admin/includes/file.php';
    require_once ABSPATH . 'wp-admin/includes/media.php';

    // фильтр допустимых типов файлов - разрешим только картинки
    add_filter( 'upload_mimes', function( $mimes ){
        return [
            'jpg|jpeg|jpe' => 'image/jpeg',
            'gif'          => 'image/gif',
            'png'          => 'image/png',
        ];
    } );

    $uploaded_imgs = array();

    /* SiteSeed добавил счетчик, если нет значения стартуем с 0 */
    if(empty($id_imgs_count)==FALSE){
        $img_coun = $id_imgs_count++;
    } else {
        $img_coun = 0;
    }

    foreach( $_FILES as $file_id => $data ){
        $attach_id = media_handle_upload( $file_id, $post_id );

        /* SiteSeed добавил счетчик, что бы новые объекты добавлялись не затирая старые */
        $img_coun++;

        // ошибка
        if( is_wp_error( $attach_id ) )
            $uploaded_imgs[] = 'Ошибка загрузки файла `'. $data['name'] .'`: '. $attach_id->get_error_message();
        else
            $uploaded_imgs[] = '<script>
            $(".photo-block-del").on("click", function (event) {
                event.preventDefault();
            
                var imgDel_ID = $(this).attr("id");
            
                    $.ajax({
                    url: "/wp-admin/admin-ajax.php",
                    method: "post",
                    data: {
                        action: "ajax_del_photo",
                        imgDel_ID: imgDel_ID
                    },
                    success: function (response) {
                        $("#photo_move"+imgDel_ID).remove();
                    }
                });
                
            });
            </script>
            <div class="photo-block" id="photo_move'.$attach_id.'" ><a class="photo-block-del" id="'.$attach_id.'"></a><img src="'.wp_get_attachment_thumb_url( $attach_id ).'" ><input class="id_imgs'.$img_coun.' id_imgs_count" type="hidden" value="'.$attach_id.'"></div>';

    }

    wp_send_json_success( $uploaded_imgs );

}



И сам HTML

<input type="file" multiple="multiple" accept=".txt,image/*">
<a href="#" class="upload_files button">Загрузить файлы</a>
<div class="ajax-reply">
</div>


Проблема заключается в том, что администраторы могут спокойно аплодить картинки, а вот для всех других групп, выдает ошибку в консоли:

612646509294d532554617.png

Пробовал добавлять права для автора:

if (current_user_can('author') && !current_user_can('upload_files')) :
    add_action('admin_init', 'razreshit_uchasnikam_gruzit_faili');
endif;
function razreshit_uchasnikam_gruzit_faili() {
    $uchasnik= get_role('author');
    $uchasnik->add_cap('upload_files');
}
  • Вопрос задан
  • 103 просмотра
Пригласить эксперта
Ответы на вопрос 2
artzolin
@artzolin Куратор тега WordPress
php, WordPress разработка сайтов artzolin.ru
Глобальные переменные не определены вне функции, так правильно:

add_action( 'admin_init', 'razreshit_uchasnikam_gruzit_faili' );
function razreshit_uchasnikam_gruzit_faili() {
	if ( !current_user_can( 'upload_files' ) ) :
		$uchasnik = get_role( 'author' );
		$uchasnik->add_cap( 'upload_files' );
	endif;
}
Ответ написан
@Prec
Смотрите какие классы есть у body при просмотре под администратором и под остальными юзерами
Ответ написан
Комментировать
Ваш ответ на вопрос

Войдите, чтобы написать ответ

Войти через центр авторизации
Похожие вопросы