Импорт XML-файла WordPress из functions.php

18 апр. 2013 г., 02:49:14
Просмотры: 14.1K
Голосов: 7

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

Пользователь устанавливает тему > Пользователь активирует тему > Код за кулисами загружает XML-файл и выполняет автоматический импорт его содержимого

В настоящее время для импорта XML-файла необходимо установить плагин WordPress Importer, затем вручную импортировать файл, выбрать пользователя для ассоциации контента и решить, нужно ли импортировать медиафайлы. Для моих клиентов этот шаг слишком сложен, и я хочу устранить необходимость в нем.

Я изучил код WordPress Importer, там много вызовов функций. Как можно убрать части, требующие ввода данных пользователем, и импортировать файл напрямую, используя класс и его методы? Я не совсем уверен, с чего начать.

Мои клиенты - мастера-ремонтники, и даже такая простая вещь, как импорт XML-файла, вызывает у них затруднения. У них нет времени на это, и возможны ошибки, особенно если они попытаются импортировать файл несколько раз, создав дубликаты страниц.

Заранее спасибо.

Уточнение

Кажется, есть недопонимание. Я не спрашиваю, как проверить активацию темы - это я уже реализовал. Мне нужно понять, как распарсить XML-файл и автоматически импортировать его без участия пользователя. По сути, я хочу автоматизировать работу плагина WordPress Import, который сейчас используется для ручного импорта XML-файла (выбор автора, медиафайлов и т.д.), но сделать это через functions.php.

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

2
Комментарии

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

anu anu
26 апр. 2013 г. 09:28:13

Я не прошу никого делать "работу" за меня. Тебе не стоит делать предположения, Ану, особенно когда они не соответствуют действительности. Я прошу совета о наилучшем способе реализации чего-либо в WordPress. Я достаточно долго являюсь участником этого сайта, Ану, чтобы понимать разницу между вопросом и просьбой о бесплатной работе. Ты утверждаешь, что мой вопрос недействителен, если он связан с коммерческим проектом? Мне запрещено просить помощи, если это касается сайта, за создание которого мне платят? Полагаю, 90% вопросов на этом сайте задаются фрилансерами...

Dwayne Charrington Dwayne Charrington
30 апр. 2013 г. 12:10:55
Все ответы на вопрос 4
3
20

Ваш вопрос довольно специфичен, если вы хотите "просто" автоматически импортировать некоторые записи/страницы. Существуют другие способы сделать это, помимо использования XML-файла экспорта.

Если у вас есть только текстовые записи, то вам следует использовать LOAD DATA INFILE. Сначала вам нужно экспортировать свои записи.

global $wpdb, $wp_filesystem;

$tables = array(
        'posts'    => array( 'posts', 'postmeta' ),
        'comments' => array( 'comments', 'commentmeta' ),
        'terms'    => array( 'terms', 'term_taxonomy', 'term_relationships' ),
        'users'    => array( 'user', 'usermeta' ),
        'links'    => array( 'links' ),
        'options'  => array( 'options' ),
        'other'    => array(),
        // для мультисайтов
        'multiside' => array( 'blogs', 'signups', 'site', 'sitemeta', 'sitecategories', 'registration_log', 'blog_versions' )

);

$exports = array( 'posts', 'comments', 'users' );

$exportdir = TEMPLATEPATH . '/export';

if ( ! is_dir( $exportdir ) {
    $mkdir = wp_mkdir_p( $exportdir );
    if ( false == $mkdir || ! is_dir( $exportdir ) )
        throw new Exception( 'Невозможно создать директорию для экспорта. Прерывание.' );
}

// очистка директории экспорта, иначе MySQL выдаст ошибки
$files = glob( $exportdir . '/*' );
if ( ! empty( $files ) ) {
    foreach( $files as $file )
        unlink( $file );
}

foreach ( $exports as $export ) {

    if ( ! isset( $tables[$export] ) )
        continue;

    if ( ! empty( $tables[$export] ) ) {
        foreach ( $tables[$export] as $table ) {

            $outfile =  sprintf( '%s/%s_dump.sql', $exportdir, $table );
            $sql = "SELECT * FROM {$wpdb->$table} INTO OUTFILE '%s'";
            $res = $wpdb->query( $wpdb->prepare( $sql, $outfile ) );

            if ( is_wp_error( $res ) )
                echo "<p>Не удалось экспортировать {$table} в {$outfile}</p>";
        }
    }
}

Это создаст директорию в папке вашей темы (убедитесь, что она доступна для записи!) и экспортирует записи и комментарии (с их метаданными) в файлы дампа. Используйте массив export для определения того, что вы хотите экспортировать. Я сгруппировал элементы более или менее логично (если вы хотите экспортировать записи, то вам следует также экспортировать postmeta и т.д.).

Преимущество этого решения в том, что с помощью оператора SELECT вы можете определить конкретные данные (например, только записи из определенной категории или только страницы, или только удаленные записи).

Теперь вы хотите импортировать эти данные в новый блог

global $wpdb;

$exportdir = TEMPLATEPATH . '/export';

$files = glob( $exportdir . '/*_dump.sql' );

foreach ( $files as $file ) {

    preg_match( '#/([^/]+)_dump.sql$#is', $file, $match );

    if ( ! isset( $match[1] ) )
        continue;

    $sql = "LOAD DATA LOCAL INFILE '%s' INTO TABLE {$wpdb->$match[1]};";

    $res = $wpdb->query( $wpdb->prepare( $sql, $file ) );

    if ( is_wp_error( $res ) )
        echo "<p>Не удалось импортировать данные из файла {$file} в таблицу {$wpdb->$match[1]}</p>";
}

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

Если вы хотите экспортировать также вложения, вам придется проделать немного больше работы.

(Примечание: Пожалуйста, прочитайте полный ответ и "Очень последние слова" в конце! Эта тема не для новичков, и я не буду писать предупреждения для каждой рискованной строки кода)

Плагин WordPress Importer кажется хорошим способом импортировать все данные и автоматически загрузить вложения. Давайте посмотрим, что делает этот плагин.

Сначала плагин запрашивает XML-файл для загрузки. Затем он анализирует XML-файл и запрашивает сопоставление авторов и следует ли загружать вложения.

Для автоматического запуска плагина нам нужно изменить некоторые вещи. Сначала нам нужно пропустить процесс загрузки. Это довольно просто, потому что вы можете включить XML-файл в тему и знать, где он находится. Затем нам нужно пропустить вопросы, которые появляются после загрузки XML-файла. Мы можем предопределить наши собственные значения и передать их в процесс импорта.

Начните с копии плагина. Создайте директорию в вашей теме, например autoimport, и скопируйте файлы wordpress-importer.php и parsers.php в нее. Хорошая идея — переименовать файл wordpress-importer.php во что-то вроде autoimporter.php. В функции вашей темы добавьте вызов функции для запуска автоматического импорта

/**
 * Автоматический импорт XML-файла
 */
add_action( 'after_setup_theme', 'autoimport' );

function autoimport() {
    // получаем файл
    require_once TEMPLATEPATH . '/autoimport/autoimporter.php';

    if ( ! class_exists( 'Auto_Importer' ) )
        die( 'Auto_Importer не найден' );

    // вызываем функцию
    $args = array(
        'file'        => TEMPLATEPATH . '/autoimport/import.xml',
        'map_user_id' => 1
    );

    auto_import( $args );

}

Сначала мы устанавливаем некоторые аргументы. Первое — это полный путь к XML-файлу. Второе — ID существующего пользователя. Нам нужен этот пользователь для сопоставления авторов, это пользователь, к которому будут привязаны все записи, если не нужно создавать новых авторов.

Теперь нам нужно понять, как работает плагин. Откройте переименованный файл плагина и прокрутите до конца. Там есть функция wordpress_importer_init() и вызов действия. Удалите оба, они больше не нужны. Теперь перейдите к началу файла и удалите заголовок плагина (комментарий в начале файла). После этого переименуйте класс WP_Importer во что-то вроде Auto_Importer, не забудьте изменить оператор function_exists и первый метод WP_Importer (это конструктор в стиле PHP4).

Позже мы передадим XML-файл напрямую в конструктор класса, измените первый метод на этот

var $xmlfile = '';
var $map_user_id = 0;

function Auto_Importer( $args ) {

    if ( file_exists( $args['file'] ) ) {

        // для систем Windows
        $file = str_replace( '\\', '/', $args['file'] );

        $this->xmlfile = $file;
    }

    if ( isset( $args['map_user_id'] ) )
        $this->map_user_id = $args['map_user_id'];

}

Теперь нам нужно удалить и изменить некоторые методы внутри класса. Первый метод — это метод dispatch(). Этот метод показывает, как работает класс. Он выполняет три шага. Сначала загружает XML-файл, затем обрабатывает его и, наконец, импортирует данные.

Case zero — это первый шаг, приветствие. Это то, что вы видите при первом вызове импорта. Он запрашивает файл для загрузки. Case two обрабатывает загрузку и отображает форму для параметров импорта. Case three, наконец, выполняет импорт. Другими словами: первые два шага только запрашивают данные, которые мы можем предоставить сами. Нам нужен только шаг 3 (case 2), и мы должны предоставить данные, запрошенные на первом и втором шагах.

На втором шаге вы видите вызов функции wp_import_handle_upload(). Эта функция устанавливает некоторую информацию о XML-файле. Мы не можем больше использовать эту функцию, потому что мы не загружали файл. Поэтому нам нужно скопировать и изменить функцию. Создайте новый метод внутри класса

function import_handle_upload() {

    $url = get_template_directory_uri() . str_replace( TEMPLATEPATH, '', $this->xmlfile );
    $type = 'application/xml'; // мы знаем MIME-тип нашего файла
    $file = $this->xmlfile;
    $filename = basename( $this->xmlfile );

    // Создаем массив объекта
    $object = array( 'post_title' => $filename,
            'post_content' => $url,
            'post_mime_type' => $type,
            'guid' => $url,
            'context' => 'import',
            'post_status' => 'private'
    );

    // Сохраняем данные
    $id = wp_insert_attachment( $object, $file );

    // планируем очистку через день на случай неудачного импорта или отсутствия вызова wp_import_cleanup()
    wp_schedule_single_event( time() + DAY_IN_SECONDS, 'importer_scheduled_cleanup', array( $id ) );

    return array( 'file' => $file, 'id' => $id );
}

И замените вызов функции $file = wp_import_handle_upload(); в методе handle_upload() на наш новый метод $file = $this->import_handle_upload();

Теперь мы заменили процесс загрузки нашим собственным файлом (который уже должен существовать). Продолжаем и удаляем больше ненужных методов. Методы greet(), header() и footer() больше не нужны (header и footer только выводят текст) и могут быть удалены из класса. В методе dispatch() удалите вызовы этих методов ($this->header() и $this->footer()).

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

Первая часть проста. Установите true, если вложения должны быть загружены, или false, если нет. Сопоставление авторов немного сложнее. Если разрешено создавать новых пользователей (авторов из файла импорта), создайте их. Если нет, назначьте записи существующему пользователю. Это делается в методе get_author_mapping(). Нам нужно заменить данные $_POST существующими данными. Здесь нам нужно простое решение, поэтому мы просто сопоставляем всех новых авторов с существующим, если не разрешено создавать новых пользователей. Или просто создаем всех новых пользователей. Во втором случае убедитесь, что все новые пользователи являются фиктивными. Если нет, каждый раз при их импорте они будут получать электронное письмо с логином и паролем для нового блога!! Я не объясняю каждую строку кода, вот полностью переписанный метод

function get_author_mapping( $map_users_id ) {
    if ( empty( $this->authors ) )
        return;

    $create_users = $this->allow_create_users();

    foreach ( (array) $this->authors as $i => $data ) {

        $old_login = $data['author_login'];

        // Multisite добавляет strtolower к sanitize_user. Нужно очистить здесь, чтобы избежать ошибок в process_posts.
        $santized_old_login = sanitize_user( $old_login, true );
        $old_id = isset( $this->authors[$old_login]['author_id'] ) ? intval($this->authors[$old_login]['author_id']) : false;

        if ( ! $create_users ) {
            $user = get_userdata( intval($map_users_id) );
            if ( isset( $user->ID ) ) {
                if ( $old_id )
                    $this->processed_authors[$old_id] = $user->ID;
                $this->author_mapping[$santized_old_login] = $user->ID;
            }
        } else if ( $create_users ) {
            if ( ! empty($this->authors[$i]) ) {
                $user_id = wp_create_user( $this->authors[$i]['author_login'], wp_generate_password() );
            } else if ( $this->version != '1.0' ) {
                $user_data = array(
                    'user_login' => $old_login,
                    'user_pass' => wp_generate_password(),
                    'user_email' => isset( $this->authors[$old_login]['author_email'] ) ? $this->authors[$old_login]['author_email'] : '',
                    'display_name' => $this->authors[$old_login]['author_display_name'],
                    'first_name' => isset( $this->authors[$old_login]['author_first_name'] ) ? $this->authors[$old_login]['author_first_name'] : '',
                    'last_name' => isset( $this->authors[$old_login]['author_last_name'] ) ? $this->authors[$old_login]['author_last_name'] : '',
                );
                $user_id = wp_insert_user( $user_data );
            }

            if ( ! is_wp_error( $user_id ) ) {
                if ( $old_id )
                    $this->processed_authors[$old_id] = $user_id;
                $this->author_mapping[$santized_old_login] = $user_id;
            } else {
                printf( __( 'Не удалось создать нового пользователя для %s. Их записи будут привязаны к текущему пользователю.', 'wordpress-importer' ), esc_html($this->authors[$old_login]['author_display_name']) );
                if ( defined('IMPORT_DEBUG') && IMPORT_DEBUG )
                    echo ' ' . $user_id->get_error_message();
                echo '<br />';
            }
        }

        // на всякий случай: если user_id был недействителен, используем текущего пользователя
        if ( ! isset( $this->author_mapping[$santized_old_login] ) ) {
            if ( $old_id )
                $this->processed_authors[$old_id] = (int) get_current_user_id();
            $this->author_mapping[$santized_old_login] = (int) get_current_user_id();
        }
    }
}

Осталось еще немного работы. Сначала добавим функцию auto_import()

function auto_import( $args ) {

    $defaults = array( 'file' => '', 'map_user_id' => 0);
    $args = wp_parse_args( $args, $defaults );

    $autoimport = new Auto_Importer( $args );
    $autoimport->do_import();

}

Поместите эту функцию после класса. В этой функции не хватает обработки ошибок и проверок (например, для пустого аргумента файла).

Если теперь запустить класс, вы получите много сообщений об ошибках. Первое — что класс отсутствует. Это связано с оператором if в начале.

if ( ! defined( 'WP_LOAD_IMPORTERS' ) )
    return;

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

$required = array(
    'post_exists'                     => ABSPATH . 'wp-admin/includes/post.php',
    'wp_generate_attachment_metadata' => ABSPATH . 'wp-admin/includes/image.php',
    'comment_exists'                  => ABSPATH . 'wp-admin/includes/comment.php'
);

foreach ( $required as $func => $req_file ) {
    if ( ! function_exists( $func ) )
        require_once $req_file;
}

В основном это все. Я протестировал это на локальной установке с тестовыми данными XML от WordPress. Это работает для меня, но это не идеальное решение для продакшена!

И несколько последних слов о настройке некоторых опций. Есть две опции, которые можно изменить с помощью фильтра:

add_filter( 'import_allow_create_users', function() { return false; } );
add_filter( 'import_allow_fetch_attachments', '__return_false' );

Думаю, мне не нужно это объяснять. Поместите эти фильтры в functions.php и установите true или false (первый в стиле PHP5.3, второй в стиле WP).

Очень последние слова

Я собрал все в этом гисте. Используйте на свой страх и риск! Я не несу ответственности за что-либо!. Пожалуйста, посмотрите файлы в гисте, я не объяснял здесь каждый маленький шаг.

Что я не сделал: Установил значение, например, в (теме) опциях после импорта. Иначе импорт будет запускаться каждый раз при активации темы.

Возможно, я поработаю над этим в будущем, очищу некоторые вещи и проведу больше тестов.

27 апр. 2013 г. 20:43:20
Комментарии

О боже. Это целая книга.

kaiser kaiser
28 апр. 2013 г. 21:50:31

Некоторые вещи невозможно объяснить в нескольких словах ;)

Ralf912 Ralf912
29 апр. 2013 г. 10:51:03

Вау. Просто вау. Это один из самых детальных и впечатляющих ответов, которые я когда-либо видел на этом сайте, респект вам, чувак. Проведя полдня за чтением, я пришел к выводу, что это правильный подход. Вы дали мне много пищи для размышлений, но это определенно верный путь. Спасибо, что нашли время оставить этот ответ.

Dwayne Charrington Dwayne Charrington
29 апр. 2013 г. 12:57:21
0

Позвольте мне вновь представить здесь две вещи:

(a) "Я не спрашиваю, как... эту часть я уже разобрал..."

»» Со временем я научился принимать тот факт, что подход к решению проблем/исправлениям не обязательно требует какой-то 'видимой ассоциации' с самой проблемой.

(b) "...что мне нужно сделать, чтобы убрать части..." "...клиенты — это работники торговли, поэтому даже что-то простое, как..."

»» Зачем упрощать клиенту за счет усложнения себе? Я, конечно, мог бы предложить 'услуги' после поставки и установить удаленное соединение, чтобы сделать это за них [платно], вместо "...взлома плагина импорта...". То есть, спросите себя, действительно ли это того стоит в вашей текущей ситуации. Однако, ЕСЛИ вы готовы приложить усилия, то попробуйте код ниже. Если сможете, то:

Я согласен с chrisguitarguy и amolv выше.

Как отметил chris, способов достичь результата множество. Это лишь один из них. Хотя он может оказаться трудоемким, обратите внимание на последние пару строк перед всем остальным.

<?php 
/* Обычно я добавляю ОДНУ строку в functions.php */
require_once (TEMPLATEPATH . '/includes/whatever.php');

/* и затем в этом месте СНАЧАЛА ПРОВЕРЯЮ */
if ((is_admin() && isset($_GET['activated']) && $pagenow == 'themes.php')||(is_admin() && isset($_GET['upgrade']) && $pagenow == 'admin.php' && $_GET['page'] == 'admin-options.php')) 
{

global $wpdb, $wp_rewrite, $hey;

// создаем таблицы
your_tables();

// вставляем значения по умолчанию
your_values();

// вставляем ссылки по умолчанию
your_links();

// страницы и шаблоны
your_pages();

// создаем категорию или категории
// wp_create_categories     $categories, $post_id = ''
// wp_create_category   $cat_name, $parent

// сброс правил перезаписи
$wp_rewrite->flush_rules();

}

// создаем таблицы БД
function your_tables() {
global $wpdb, $hey;

$collate = '';
if($wpdb->supports_collation()) {
if(!empty($wpdb->charset)) $collate = "DEFAULT CHARACTER SET $wpdb->charset";
if(!empty($wpdb->collate)) $collate .= " COLLATE $wpdb->collate";
}

$sql = "CREATE TABLE IF NOT EXISTS ". $wpdb->prefix . "table1_name" ." (
`id` INT(10) NOT NULL auto_increment,
`some_name1` VARCHAR(255) NOT NULL,
`some_name2` VARCHAR(255) NOT NULL,
`some_name3` LONGTEXT,
`some_name4` LONGTEXT NOT NULL,
`some_name5` VARCHAR(255) DEFAULT NULL,
`some_name6` VARCHAR(255) DEFAULT NULL,
`some_name7` DATETIME NOT NULL DEFAULT '0000-00-00 00:00:00',
`some_name8` DATETIME NOT NULL DEFAULT '0000-00-00 00:00:00',
PRIMARY KEY id  (`id`)) $collate;";

$wpdb->query($sql);


$sql = "CREATE TABLE IF NOT EXISTS ". $wpdb->prefix . "table2_name" ." (
`meta_id` INT(10) NOT NULL AUTO_INCREMENT,
`some_name1` INT(10) NOT NULL,
`some_name2` INT(10) NOT NULL,
`some_name3` VARCHAR(255) NOT NULL,
`some_name4` INT(10) NOT NULL,
PRIMARY KEY id  (`meta_id`)) $collate;";

$wpdb->query($sql);

// и так далее

/* Вставляем данные по умолчанию/ВСЕ данные в таблицы */
// НО СНАЧАЛА ПРОВЕРЬТЕ, ЕСТЬ ЛИ ДАННЫЕ. ЕСЛИ = ДА, НЕ ВСТАВЛЯЙТЕ НИЧЕГО

$sql = "SELECT field_id " . "FROM " . $wpdb->prefix . "table1_name LIMIT 1";

$wpdb->get_results($sql);

if($wpdb->num_rows == 0) {

// далее будет больше кода
// сейчас мне нужно идти

} 

?>

ПРИМЕЧАНИЕ

  • Если вы работаете с WP какое-то время, излишне напоминать СНАЧАЛА СОЗДАЙТЕ РЕЗЕРВНУЮ КОПИЮ БД.

  • phpMyAdmin обладает огромной мощью и позволяет легко аккуратно все испортить.

  • Хотя требуемые усилия могут показаться пугающими на первый взгляд, если все сделать правильно, это может работать как часы ф ...

И наконец

Как поместить 2000 строк данных за 20 секунд в последние 2 строки внутри этих 2 фигурных скобок?

phpMyAdmin » Выберите БД слева »» Выберите ВСЕ ТАБЛИЦЫ справа »» Экспорт ▼

➝ Пользовательский: показать все опции
➝ Просмотр вывода как текст = ВКЛ
➝ Сохранить вывод в файл = ВЫКЛ
➝ Сжатие = НЕТ
➝ Формат = SQL
➝ Дамп таблицы = СТРУКТУРА & ДАННЫЕ
➝ Добавить DROP TABLE... = ВЫКЛ (Важно!)
➝ Используемый синтаксис = "оба из вышеперечисленных"

»» ВПЕРЕД!
  • Со следующего экрана я могу скопировать часть 'СТРУКТУРА' в $sql = "...." для your_tables() и часть 'ДАННЫЕ' в $sql для your_data()

  • Для остальных значений по умолчанию WP я использую update_option(...) & update_post_meta(...)

26 апр. 2013 г. 15:55:56
1

Для тем не существует эквивалента хука register_activation_hook, который есть у плагинов — есть лишь несколько костылей. Почему? Потому что тема — это оболочка. В теме должна содержаться только функциональность, связанная с отображением контента, но не сам контент.

Что касается реализации: используйте пример выше для однократного выполнения callback-функции. Импортер WordPress работает с XML-файлами, и в PHP существует множество различных способов парсинга XML. Выберите подходящий, обработайте файл и сделайте с ним то, что вам нужно.

18 апр. 2013 г. 03:46:54
Комментарии

Спасибо, Крис. Проблема не в поиске подходящего хука для определения момента активации темы (эту часть я уже разобрал), а в поиске способа автоматически импортировать XML-файл в WordPress. У меня есть XML-файл в папке моей темы под названием "importxml". В идеале я хотел бы использовать существующий импортер WordPress, убрать ручные действия и загрузить мой XML-файл без необходимости участия пользователя.

Dwayne Charrington Dwayne Charrington
18 апр. 2013 г. 03:53:48
2

В файле functions.php можно проверить условие:

if( isset($_GET['activated']) && 'themes.php' == $GLOBALS['pagenow']) )
{ 
  // проверка дубликатов 
   // вызов класса импорта 
   // код импорта xml 
   // выполнение любых необходимых действий 
}

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

26 апр. 2013 г. 06:42:41
Комментарии

Спасибо за ответ, amolv. Однако, я спрашиваю не о том, как проверить, активирована ли тема (это я уже делаю). Мне скорее нужно узнать, как автоматически обработать и импортировать XML-файл без участия пользователя.

Dwayne Charrington Dwayne Charrington
26 апр. 2013 г. 08:33:10

В плагине wordpress-importer достаточно разобраться всего в 2 файлах, чтобы понять, как это реализовано. Просто скопируйте эти файлы в тему, используйте класс WP_Import и вызовите функцию import, передав путь к файлу в качестве параметра — вот и всё.

amolv amolv
26 апр. 2013 г. 10:11:31