@Arh1diablo
Web мастер

Как склеить код добавления файлов в единое?

Доброго времени суток, пилю под WP один функционал ( решение которого кусками раскидан по интернету ). Задача для всех пользователей ( не зарегистрированных ), возможность загружать изображения. Изначально было сложно, но в целом разбил на этапы и все заработало:
  1. Загрузка файла в директорию
  2. Добавление файла в медиатеку WP
  3. Создание атачей


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

Страница с формой выглядит так:
<div class="wrapper">
        <input type="file" multiple="multiple" accept=".txt,image/*">
        <a href="#" class="upload_files button">Загрузить файлы</a>
        <div class="ajax-reply"></div>
    </div>


1. Загрузка файла в директорию - рабочий вариант

При нажатии на кнопку "Загрузить файлы" отправляет AJAX запрос в файл submit.php который содержит следующий рабочий код:
if( isset( $_POST['ss_file_upload'] ) ){
    // ВАЖНО! тут должны быть все проверки безопасности передаваемых файлов и вывести ошибки если нужно
    $uploaddir = './img'; // . - текущая папка где находится submit.php

    // создадим папку если её нет
    if( ! is_dir( $uploaddir ) ) mkdir( $uploaddir, 0777 );

    $files      = $_FILES; // полученные файлы
    $done_files = array();

    // переместим файлы из временной директории в указанную
    foreach( $files as $file ){
        $file_name = date('YmdHis').rand(10,999).cyrillic_translit( $file['name'] );

        if( move_uploaded_file( $file['tmp_name'], "$uploaddir/$file_name" ) ){
            $done_files[] = realpath( "$uploaddir/$file_name" );
            // 1 этап завершон, загруженный файл попал в директорию  wp-content\uploads\ss_comments\img
            // Переходим к этапу добавления этого файла в медиатеку
        }
    }
    
    $data = $done_files ? array('files' => $done_files ) : array('error' => 'Ошибка загрузки файлов.');
    
    die( json_encode( $data ) );
}


## Транслитирация кирилических символов
function cyrillic_translit( $title ){
    $iso9_table = array(
        'А' => 'A', 'Б' => 'B', 'В' => 'V', 'Г' => 'G', 'Ѓ' => 'G',
        'Ґ' => 'G', 'Д' => 'D', 'Е' => 'E', 'Ё' => 'YO', 'Є' => 'YE',
        'Ж' => 'ZH', 'З' => 'Z', 'Ѕ' => 'Z', 'И' => 'I', 'Й' => 'J',
        'Ј' => 'J', 'І' => 'I', 'Ї' => 'YI', 'К' => 'K', 'Ќ' => 'K',
        'Л' => 'L', 'Љ' => 'L', 'М' => 'M', 'Н' => 'N', 'Њ' => 'N',
        'О' => 'O', 'П' => 'P', 'Р' => 'R', 'С' => 'S', 'Т' => 'T',
        'У' => 'U', 'Ў' => 'U', 'Ф' => 'F', 'Х' => 'H', 'Ц' => 'TS',
        'Ч' => 'CH', 'Џ' => 'DH', 'Ш' => 'SH', 'Щ' => 'SHH', 'Ъ' => '',
        'Ы' => 'Y', 'Ь' => '', 'Э' => 'E', 'Ю' => 'YU', 'Я' => 'YA',
        'а' => 'a', 'б' => 'b', 'в' => 'v', 'г' => 'g', 'ѓ' => 'g',
        'ґ' => 'g', 'д' => 'd', 'е' => 'e', 'ё' => 'yo', 'є' => 'ye',
        'ж' => 'zh', 'з' => 'z', 'ѕ' => 'z', 'и' => 'i', 'й' => 'j',
        'ј' => 'j', 'і' => 'i', 'ї' => 'yi', 'к' => 'k', 'ќ' => 'k',
        'л' => 'l', 'љ' => 'l', 'м' => 'm', 'н' => 'n', 'њ' => 'n',
        'о' => 'o', 'п' => 'p', 'р' => 'r', 'с' => 's', 'т' => 't',
        'у' => 'u', 'ў' => 'u', 'ф' => 'f', 'х' => 'h', 'ц' => 'ts',
        'ч' => 'ch', 'џ' => 'dh', 'ш' => 'sh', 'щ' => 'shh', 'ъ' => '',
        'ы' => 'y', 'ь' => '', 'э' => 'e', 'ю' => 'yu', 'я' => 'ya'
    );

    $name = strtr( $title, $iso9_table );
    $name = preg_replace('~[^A-Za-z0-9\'_\-\.]~', '-', $name );
    $name = preg_replace('~\-+~', '-', $name ); // --- на -
    $name = preg_replace('~^-+|-+$~', '', $name ); // кил - на концах

    return $name;
}

Код успешно, перемещает файл в нужную директорию.

2. Добавление файла в медиатеку WP - рабочий вариант

Далее отдельно на другой тестовой странице, следующий код добавляет загруженный файл в медиатеку WP

// файл должен находиться в директории загрузок WP.
$filename = '/wp-content/uploads/ss_comments/img/2020090705464965lTBMKZ.png';

// ID поста, к которому прикрепим вложение.
$parent_post_id = 123;

// Проверим тип поста, который мы будем использовать в поле 'post_mime_type'.
$filetype = wp_check_filetype( basename( $filename ), null );

// Получим путь до директории загрузок.
$wp_upload_dir = wp_upload_dir();
print_r($wp_upload_dir);

// Подготовим массив с необходимыми данными для вложения.
$attachment = array(
    'guid'           => $wp_upload_dir['url'] . '/' . basename( $filename ),
    'post_mime_type' => $filetype['type'],
    'post_title'     => preg_replace( '/\.[^.]+$/', '', basename( $filename ) ),
    'post_content'   => '',
    'post_status'    => 'inherit',
    'post_author'  => '3'
);

// Вставляем запись в базу данных.
$attach_id = wp_insert_attachment( $attachment, $filename, $parent_post_id );

set_post_thumbnail(123, $attach_id);


3. Создание атачей - рабочий вариант

// Подключим нужный файл, если он еще не подключен
// wp_generate_attachment_metadata() зависит от этого файла.
require_once (ABSPATH . 'wp-admin/includes/image.php');
require_once (ABSPATH . 'wp-admin/includes/file.php');
require_once (ABSPATH . 'wp-admin/includes/media.php');

// Создадим метаданные для вложения и обновим запись в базе данных.

$dir = wp_get_upload_dir();
$file = $dir['basedir'] . '/ss_comments/img/2020090705464965lTBMKZ.png';
print_r($file);
$attach_data = wp_generate_attachment_metadata( 282, $file );

wp_update_attachment_metadata( '282', $attach_data );


Теперь ключевой вопрос - как это склеить в единый код, в 1ом этапе пытался стыковать 2ой этап таким образом:

if( isset( $_POST['ss_file_upload'] ) ){
    // ВАЖНО! тут должны быть все проверки безопасности передавемых файлов и вывести ошибки если нужно



    $uploaddir = './img'; // . - текущая папка где находится submit.php




    // cоздадим папку если её нет
    if( ! is_dir( $uploaddir ) ) mkdir( $uploaddir, 0777 );

    $files      = $_FILES; // полученные файлы
    $done_files = array();

    // переместим файлы из временной директории в указанную
    foreach( $files as $file ){
        $file_name = date('YmdHis').rand(10,999).cyrillic_translit( $file['name'] );

        if( move_uploaded_file( $file['tmp_name'], "$uploaddir/$file_name" ) ){
            $done_files[] = realpath( "$uploaddir/$file_name" );
            // 1 этап завершон, загруженный файл попал в директорию  wp-content\uploads\ss_comments\img
            // Переходим к этапу добавления этого файла в медиатеку


                // файл должен находиться в директории загрузок WP.
                $filename = realpath( "$uploaddir/$file_name" );

                // ID поста, к которому прикрепим вложение.
                $parent_post_id = 123;

                // Проверим тип поста, который мы будем использовать в поле 'post_mime_type'.
                $filetype = wp_check_filetype( basename( $filename ), null );

                // Получим путь до директории загрузок.
                $wp_upload_dir = wp_upload_dir();
                print_r($wp_upload_dir);

                // Подготовим массив с необходимыми данными для вложения.
                $attachment = array(
                    'guid'           => $wp_upload_dir['url'] . '/' . basename( $filename ),
                    'post_mime_type' => $filetype['type'],
                    'post_title'     => preg_replace( '/\.[^.]+$/', '', basename( $filename ) ),
                    'post_content'   => '',
                    'post_status'    => 'inherit',
                    'post_author'  => '3'
                );

                // Вставляем запись в базу данных.
                $attach_id = wp_insert_attachment( $attachment, $filename, $parent_post_id );

                set_post_thumbnail(123, $attach_id);

        }
    }
    
    $data = $done_files ? array('files' => $done_files ) : array('error' => 'Ошибка загрузки файлов.');
    
    die( json_encode( $data ) );
}


## Транслитирация кирилических символов
function cyrillic_translit( $title ){
    $iso9_table = array(
        'А' => 'A', 'Б' => 'B', 'В' => 'V', 'Г' => 'G', 'Ѓ' => 'G',
        'Ґ' => 'G', 'Д' => 'D', 'Е' => 'E', 'Ё' => 'YO', 'Є' => 'YE',
        'Ж' => 'ZH', 'З' => 'Z', 'Ѕ' => 'Z', 'И' => 'I', 'Й' => 'J',
        'Ј' => 'J', 'І' => 'I', 'Ї' => 'YI', 'К' => 'K', 'Ќ' => 'K',
        'Л' => 'L', 'Љ' => 'L', 'М' => 'M', 'Н' => 'N', 'Њ' => 'N',
        'О' => 'O', 'П' => 'P', 'Р' => 'R', 'С' => 'S', 'Т' => 'T',
        'У' => 'U', 'Ў' => 'U', 'Ф' => 'F', 'Х' => 'H', 'Ц' => 'TS',
        'Ч' => 'CH', 'Џ' => 'DH', 'Ш' => 'SH', 'Щ' => 'SHH', 'Ъ' => '',
        'Ы' => 'Y', 'Ь' => '', 'Э' => 'E', 'Ю' => 'YU', 'Я' => 'YA',
        'а' => 'a', 'б' => 'b', 'в' => 'v', 'г' => 'g', 'ѓ' => 'g',
        'ґ' => 'g', 'д' => 'd', 'е' => 'e', 'ё' => 'yo', 'є' => 'ye',
        'ж' => 'zh', 'з' => 'z', 'ѕ' => 'z', 'и' => 'i', 'й' => 'j',
        'ј' => 'j', 'і' => 'i', 'ї' => 'yi', 'к' => 'k', 'ќ' => 'k',
        'л' => 'l', 'љ' => 'l', 'м' => 'm', 'н' => 'n', 'њ' => 'n',
        'о' => 'o', 'п' => 'p', 'р' => 'r', 'с' => 's', 'т' => 't',
        'у' => 'u', 'ў' => 'u', 'ф' => 'f', 'х' => 'h', 'ц' => 'ts',
        'ч' => 'ch', 'џ' => 'dh', 'ш' => 'sh', 'щ' => 'shh', 'ъ' => '',
        'ы' => 'y', 'ь' => '', 'э' => 'e', 'ю' => 'yu', 'я' => 'ya'
    );

    $name = strtr( $title, $iso9_table );
    $name = preg_replace('~[^A-Za-z0-9\'_\-\.]~', '-', $name );
    $name = preg_replace('~\-+~', '-', $name ); // --- на -
    $name = preg_replace('~^-+|-+$~', '', $name ); // кил - на концах

    return $name;
}


Однако AJAX ругается :
<br />
<b>Fatal error</b>:  Call to undefined function wp_check_filetype() in <b>C:\OpenServer\domains\site.ru\wp-content\uploads\ss_comments\submit.php</b> on line <b>37</b><br />


Подскажите, как состыковать код в единый ?
Заранее благодарен !
  • Вопрос задан
  • 115 просмотров
Решения вопроса 1
@Arh1diablo Автор вопроса
Web мастер
Я просто идиотина :|
Решил немного отдохнуть т.к. глаза уже асинхронно моргают, забил кальянчик, сижу чилю, ютуб не смотрется, мысли о коде, думаю ну ладно гляну еще раз мануал, пробегаю глазами, дочитал до конца и поперхнулся дымом. В конце мануала черным по русски написано :
AJAX Загрузка файлов: пример для WordPress
я такой, что ?
AJAX Загрузка файлов: пример для WordPress
что, что ?*!
AJAX Загрузка файлов: >>>пример для WordPress<<<
И там такой небольшой спойлер с раскрывающимся готовым решением под WP, листаю выше, а там:
AJAX Загрузка файлов: общий пример

Сижу я с флешбеками из дней потраченных в пустую, а рядом дымится говно и палки ( кстати наломанные костыли ).

В общем ребят, для тех кому понадобиться загрузить файлы в библиотеку WP для всех и не будет желания сражаться с ветреными мельницами вот код:

<?php

// форма
add_action( 'the_content', 'ajax_file_upload_html' );

// скрипт
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' );

// HTML код формы
function ajax_file_upload_html( $text ){
	// выходим не наша страница...
	if( $GLOBALS['post']->post_name !== 'ajax_file_upload' )
		return $text;

	return $text .= '
		<input type="file" multiple="multiple" accept="image/*">
		<button class="upload_files">Загрузить файл</button>
		<div class="ajax-reply"></div>
	';
}

// 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 );
				});

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

				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( '<p>'+ val +'</p>' );
							} );
						}
						// 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'];

	// ограничим размер загружаемой картинки
	$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();

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

		// ошибка
		if( is_wp_error( $attach_id ) )
			$uploaded_imgs[] = 'Ошибка загрузки файла `'. $data['name'] .'`: '. $attach_id->get_error_message();
		else
			$uploaded_imgs[] = wp_get_attachment_url( $attach_id );
	}

	wp_send_json_success( $uploaded_imgs );

}


Ссылка на источник.

P.S. Все работает !
Ответ написан
Комментировать
Пригласить эксперта
Ответы на вопрос 1
Я не знаток вордпресса
Но эта ошибка говорит о том, что в вашем файле функция wp_check_filetype не определена.
И ajax тут не причем

Может попробовать require / include, или сделать на примере других модулей?
Там же наверняка как - то подключаются пространства имён, файлы и тп
Ответ написан
Ваш ответ на вопрос

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

Похожие вопросы