Загружайте изображения с одного сайта на другой в режиме мультисайта


В моей многоузловой настройке есть один сайт с правами администратора, где пользователи могут вставлять/редактировать сообщения и указывать, на каком сайте они хотят их публиковать. Это требование контракта и не может быть изменено.

РЕДАКТИРОВАТЬ: Проверьте принятый ответ на гораздо более простой подход к этому.

Основные шаги по вставке контента выполнены и должным образом работают с полной мощностью switch_to_blog(), но мы сталкиваемся с небольшим дискомфортом при загрузке файлов. Мы решили использовать загрузчик WP и, как таковой, делает медиа-библиотеку администратора простой изолированной средой для загружаемых файлов.

Итак, процесс идет следующим образом:

  1. Клиент вставляет новую запись и изображения в форму.

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

  3. Пользователь нажимает, чтобы сохранить сообщение.

  4. Система запускает wp_insert_post() на правильном сайте и получает возвращенный идентификатор записи и:

    <?php
    // functions.php inside the function triggered upon post save
    
    foreach ($files as $f) {
    restore_current_blog();
    /*
    * 5. System copies the files from the Admin Site Uploads Dir to the Selected Site Uploads Dir.
    */
    $filename = get_attached_file($f);
    $arq = get_post($f, ARRAY_A);
    
    $filedest = str_replace('blogs.dir/22/', 'blogs.dir/' . $marca . '/', $filename);
    
    if (copy($filename, $filedest)) {
            switch_to_blog($marca);
            unset($arq['ID']);
    
            /*
            * 6. System fires `wp_insert_attachment()`, `wp_generate_attachment_metadata()`
            * and `wp_update_attachment_metadata()` associating the newly moved files to the
            * returned Post ID from step 4.
            *
            */
    
            $att = wp_insert_attachment($arq, $filedest, $err);
            if ($att) {
    
                    $attach_data = wp_generate_attachment_metadata( $att, $filedest );
                    wp_update_attachment_metadata( $att,  $attach_data );
    
                        if ($f == $destaque) {
                            update_post_meta($err, '_thumbnail_id', $att);
                        }
    
            restore_current_blog();
            /*
            * 7. System deletes the old images from the Admin Media Library aka Sandbox.
            */
            $del = wp_delete_attachment( $f, true );
    
            $msg = '8. User is (should be) happy his files are properly put in place and goes on with his life.';
            } else {
                echo 'erro';
            }
        }
    }
    ?>
    

После копирования файлов по правильному пути и правильного управления вложениями мы обнаруживаем, что, хотя основной файл присутствует и прикреплен к нужному сообщению, и мы вызываем wp_generate_attachment_metadata и wp_update_attachment_metadata внутри switch_to_blog() промежуточные размеры, определенные на целевом сайте, НЕ генерируются, и поэтому функции не подключены к add_attachment.

Я подозреваю, что это имеет что-то связанное с тем, что эти действия были уволены с сайта администратора functions.php и невозможность получить доступ к функциям другого сайта.

Итак, есть ли более умный способ переместить эти изображения, как если бы они были родными для целевого сайта?

Author: moraleida, 2012-09-28

1 answers

Кто бы сказал, что решение будет таким простым...

После нескольких дней борьбы с этим, меня как-то осенило: "что, если мы switch_to_blog() внутри загрузочного iframe?" Что, если мы потребуем, чтобы пользователь сохранил сообщение перед загрузкой любых изображений?

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

1) Добавьте site_id в переменные GET, передаваемые загрузчику мультимедиа:

<script type="text/javascript">
    jQuery(function(){
            var site_id = <?php echo json_encode($siteid); ?>;
            var post_id = <?php echo json_encode($conteudo->ID); ?>;

                jQuery('.btn_incluir_imagem').click(function() {
                     formfield = jQuery('#upload_image').attr('name');
                     tb_show('', uploader+'media-upload.php?sid='+site_id+'&amp;post_id='+post_id+'&amp;type=image&amp;TB_iframe=true&amp;');
                     return false;
                });

    // More code here
    });
</script>

2) И извлеките его из iframe, сразу после подключения сценариев и стилей:

function admin_styles_scripts_media_upload(){
    // Registers and enqueues


    if($_GET['sid']) { 
        switch_to_blog($_GET['sid']);
    }

    // Any images uploaded here will be directed straight to the post_id inside site_id

}
add_action('admin_print_scripts-media-upload-popup','admin_styles_scripts_media_upload');

Этот простой трюк позволяет загружать мультимедиа с любого сайта на любой другой сайт в сети, если у вас уже есть site_id и post_id адресата. Нет необходимости вручную копировать файлы и повторно генерировать метаданные, много кода прямо в мусорное ведро, ура! :)

Кроме того, поскольку мы находимся в iframe и единственный способ выйти из него - закрыть окно, не вызывая restore_current_blog(), не вызывает никаких побочных эффектов.

 2
Author: moraleida, 2012-10-04 21:08:43