web-dev-qa-db-ja.com

ナビゲーションメニューメタのインポートに失敗する

私は、ユーザーの役割に基づいてメニュー項目を表示/非表示にできるNav Menu Rolesプラグインの作者です。通常のWordPressプラグイン/インポートツールを使用している場合、メニューアイテムメタがインポートされないことが私の注意を引きました。

各メニュー項目は基本的にデータベース内の単なる投稿であり、私は投稿メタとしてデータを保存しています。エクスポートされたXMLに表示されます。これは私がローカルで行ったテストエクスポートのサンプルです。

<item>
    <title>Art &amp; Design</title>
    <link>http://localhost/blog/2013/01/13/263/</link>
    <pubDate>Mon, 14 Jan 2013 03:36:16 +0000</pubDate>
    <dc:creator>helga</dc:creator>
    <guid isPermaLink="false">http://localhost/blog/2013/01/13/263/</guid>
    <description></description>
    <content:encoded><![CDATA[]]></content:encoded>
    <excerpt:encoded><![CDATA[]]></excerpt:encoded>
    <wp:post_id>263</wp:post_id>
    <wp:post_date>2013-01-13 22:36:16</wp:post_date>
    <wp:post_date_gmt>2013-01-14 03:36:16</wp:post_date_gmt>
    <wp:comment_status>open</wp:comment_status>
    <wp:ping_status>open</wp:ping_status>
    <wp:post_name>263</wp:post_name>
    <wp:status>publish</wp:status>
    <wp:post_parent>0</wp:post_parent>
    <wp:menu_order>1</wp:menu_order>
    <wp:post_type>nav_menu_item</wp:post_type>
    <wp:post_password></wp:post_password>
    <wp:is_sticky>0</wp:is_sticky>
    <category domain="nav_menu" nicename="main-menu"><![CDATA[Main Menu]]></category>
    <wp:postmeta>
        <wp:meta_key>_menu_item_type</wp:meta_key>
        <wp:meta_value><![CDATA[taxonomy]]></wp:meta_value>
    </wp:postmeta>
    <wp:postmeta>
        <wp:meta_key>_menu_item_menu_item_parent</wp:meta_key>
        <wp:meta_value><![CDATA[0]]></wp:meta_value>
    </wp:postmeta>
    <wp:postmeta>
        <wp:meta_key>_menu_item_object_id</wp:meta_key>
        <wp:meta_value><![CDATA[6]]></wp:meta_value>
    </wp:postmeta>
    <wp:postmeta>
        <wp:meta_key>_menu_item_object</wp:meta_key>
        <wp:meta_value><![CDATA[category]]></wp:meta_value>
    </wp:postmeta>
    <wp:postmeta>
        <wp:meta_key>_menu_item_target</wp:meta_key>
        <wp:meta_value><![CDATA[]]></wp:meta_value>
    </wp:postmeta>
    <wp:postmeta>
        <wp:meta_key>_menu_item_classes</wp:meta_key>
        <wp:meta_value><![CDATA[a:1:{i:0;s:6:"design";}]]></wp:meta_value>
    </wp:postmeta>
    <wp:postmeta>
        <wp:meta_key>_menu_item_xfn</wp:meta_key>
        <wp:meta_value><![CDATA[]]></wp:meta_value>
    </wp:postmeta>
    <wp:postmeta>
        <wp:meta_key>_menu_item_url</wp:meta_key>
        <wp:meta_value><![CDATA[]]></wp:meta_value>
    </wp:postmeta>
    <wp:postmeta>
        <wp:meta_key>_nav_menu_role</wp:meta_key>
        <wp:meta_value><![CDATA[a:2:{i:0;s:13:"administrator";i:1;s:12:"shop_manager";}]]></wp:meta_value>
    </wp:postmeta>
</item>

しかしインポート時には、メタキー_nav_menu_roleはデータベースにも表示されません。私はローカルにマルチサイトを運営していますが、この問題を私の注意を引くようにしたユーザーはそうではありません。このプラグインを使っている人全員のためにこの問題を解決したいのですが、どこから見ればいいのか困惑しています。シリアル化/非シリアル化で問題になる可能性があると思いましたが、キーは破損しているわけではなく、インポート後も存在しません。

UPDATE:私はインポータープラグインを調査しました、そしてメニュー項目のために、プラグインは伝統的な定義済みのメタだけをインポートします。クラス'。

5
helgatheviking

問題は最終的にWordPress Importerプラグインにありました。私はそれをハックすることができました(そして開発者に改善を提案しました)が、私は私自身のカスタムインポーターを書くことによってこれを回避するつもりです。 (.XMLファイルを再アップロードするのは)最も便利な方法ではありませんが、ユーザーが複雑なメニューを持っている場合は、メタ値を失うよりも優れています。

もっとテストが必要ですが、次のバージョンで私のプラグインに追加する予定です。

メニュー項目メタのカスタムインポーター

問題は最終的にWordPress Importerプラグインにありました。私はそれをハックすることができました(そして開発者に改善を提案しました)が、私は私自身のカスタムインポーターを書くことによってこれを回避するつもりです。 (.XMLファイルを再アップロードするのは)最も便利な方法ではありませんが、ユーザーが複雑なメニューを持っている場合は、メタ値を失うよりも優れています。

もっとテストが必要ですが、次のバージョンで私のプラグインに追加する予定です。

メニュー項目メタのカスタムインポーター

<?php
/**
 * Nav Menu Roles Importer - import menu item meta
 *
 */

if ( ! defined( 'ABSPATH' ) ) exit; // Exit if accessed directly

if ( class_exists( 'WP_Importer' ) ) {
    class Nav_Menu_Roles_Import extends WP_Importer {

    var $max_wxr_version = 1.2; // max. supported WXR version

    var $id; // WXR attachment ID

    // information to import from WXR file
    var $version;
    var $posts = array();
    var $base_url = '';


        /**
         * __construct function.
         *
         * @access public
         * @return void
         */
        public function __construct() {
            $this->import_page = 'nav_menu_roles';
        }

    /**
     * Registered callback function for the WordPress Importer
     *
     * Manages the three separate stages of the WXR import process
     */
    function dispatch() {
        $this->header();

        $step = empty( $_GET['step'] ) ? 0 : (int) $_GET['step'];
        switch ( $step ) {
            case 0:
                $this->greet();
                break;
            case 1:
                check_admin_referer( 'import-upload' );
                if ( $this->handle_upload() ) {
                    $file = get_attached_file( $this->id );
                    set_time_limit(0);
                    $this->import( $file );
                }
                break;
        }

        $this->footer();
    }

    /**
     * The main controller for the actual import stage.
     *
     * @param string $file Path to the WXR file for importing
     */
    function import( $file ) {
        add_filter( 'import_post_meta_key', array( $this, 'is_valid_meta_key' ) );
        add_filter( 'http_request_timeout', array( &$this, 'bump_request_timeout' ) );

        $this->import_start( $file );

        wp_suspend_cache_invalidation( true );
        $this->process_nav_menu_meta();
        wp_suspend_cache_invalidation( false );

        $this->import_end();
    }

    /**
     * Parses the WXR file and prepares us for the task of processing parsed data
     *
     * @param string $file Path to the WXR file for importing
     */
    function import_start( $file ) {
        if ( ! is_file($file) ) {
            echo '<p><strong>' . __( 'Sorry, there has been an error.', 'nav-menu-roles' ) . '</strong><br />';
            echo __( 'The file does not exist, please try again.', 'nav-menu-roles' ) . '</p>';
            $this->footer();
            die();
        }

        $import_data = $this->parse( $file );

        if ( is_wp_error( $import_data ) ) {
            echo '<p><strong>' . __( 'Sorry, there has been an error.', 'nav-menu-roles' ) . '</strong><br />';
            echo esc_html( $import_data->get_error_message() ) . '</p>';
            $this->footer();
            die();
        }

        $this->version = $import_data['version'];
        $this->posts = $import_data['posts'];
        $this->base_url = esc_url( $import_data['base_url'] );

        wp_defer_term_counting( true );
        wp_defer_comment_counting( true );

        do_action( 'import_start' );
    }

    /**
     * Performs post-import cleanup of files and the cache
     */
    function import_end() {
        wp_import_cleanup( $this->id );

        wp_cache_flush();
        foreach ( get_taxonomies() as $tax ) {
            delete_option( "{$tax}_children" );
            _get_term_hierarchy( $tax );
        }

        wp_defer_term_counting( false );
        wp_defer_comment_counting( false );

        echo '<p>' . __( 'All done.', 'nav-menu-roles' ) . ' <a href="' . admin_url() . '">' . __( 'Have fun!', 'nav-menu-roles' ) . '</a>' . '</p>';

        do_action( 'import_end' );
    }

    /**
     * Handles the WXR upload and initial parsing of the file to prepare for
     * displaying author import options
     *
     * @return bool False if error uploading or invalid file, true otherwise
     */
    function handle_upload() {
        $file = wp_import_handle_upload();

        if ( isset( $file['error'] ) ) {
            echo '<p><strong>' . __( 'Sorry, there has been an error.', 'nav-menu-roles' ) . '</strong><br />';
            echo esc_html( $file['error'] ) . '</p>';
            return false;
        } else if ( ! file_exists( $file['file'] ) ) {
            echo '<p><strong>' . __( 'Sorry, there has been an error.', 'nav-menu-roles' ) . '</strong><br />';
            printf( __( 'The export file could not be found at <code>%s</code>. It is likely that this was caused by a permissions problem.', 'nav-menu-roles' ), esc_html( $file['file'] ) );
            echo '</p>';
            return false;
        }

        $this->id = (int) $file['id'];
        $import_data = $this->parse( $file['file'] );
        if ( is_wp_error( $import_data ) ) {
            echo '<p><strong>' . __( 'Sorry, there has been an error.', 'nav-menu-roles' ) . '</strong><br />';
            echo esc_html( $import_data->get_error_message() ) . '</p>';
            return false;
        }

        $this->version = $import_data['version'];
        if ( $this->version > $this->max_wxr_version ) {
            echo '<div class="error"><p><strong>';
            printf( __( 'This WXR file (version %s) may not be supported by this version of the importer. Please consider updating.', 'nav-menu-roles' ), esc_html($import_data['version']) );
            echo '</strong></p></div>';
        }

        return true;
    }



    /**
     * Create new posts based on import information
     *
     * Posts marked as having a parent which doesn't exist will become top level items.
     * Doesn't create a new post if: the post type doesn't exist, the given post ID
     * is already noted as imported or a post with the same title and date already exists.
     * Note that new/updated terms, comments and meta are imported for the last of the above.
     */
    function process_nav_menu_meta() {
        foreach ( $this->posts as $post ) {

            // we only want to deal with the nav_menu_item posts
            if ( 'nav_menu_item' != $post['post_type'] || ! empty( $post['post_id'] ) )
                continue;

            // ok we've got a nav_menu_item
            $post_id = (int) $post['post_id'];

            // add/update post meta
            if ( isset( $post['postmeta'] ) ) {
                foreach ( $post['postmeta'] as $meta ) {
                    $key = apply_filters( 'import_post_meta_key', $meta['key'] );
                    $value = false;


                    if ( $key ) {
                        // export gets meta straight from the DB so could have a serialized string
                        if ( ! $value )
                            $value = maybe_unserialize( $meta['value'] );

                        update_post_meta( $post_id, $key, $value );
                        do_action( 'import_post_meta', $post_id, $key, $value );

                    }
                }
            }
        }

        unset( $this->posts );
    }




    /**
     * Parse a WXR file
     *
     * @param string $file Path to WXR file for parsing
     * @return array Information gathered from the WXR file
     */
    function parse( $file ) {
        $parser = new WXR_Parser();
        return $parser->parse( $file );
    }

    // Display import page title
    function header() {
        echo '<div class="wrap">';
        screen_icon();
        echo '<h2>' . __( 'Import Nav Menu Roles', 'nav-menu-roles' ) . '</h2>';

        $updates = get_plugin_updates();
        $basename = plugin_basename(__FILE__);
        if ( isset( $updates[$basename] ) ) {
            $update = $updates[$basename];
            echo '<div class="error"><p><strong>';
            printf( __( 'A new version of this importer is available. Please update to version %s to ensure compatibility with newer export files.', 'nav-menu-roles' ), $update->update->new_version );
            echo '</strong></p></div>';
        }
    }

    // Close div.wrap
    function footer() {
        echo '</div>';
    }

    /**
     * Display introductory text and file upload form
     */
    function greet() {
        echo '<div class="narrow">';
        echo '<p>'.__( 'Re-Upload your normal WordPress eXtended RSS (WXR) file and we&#8217;ll import the Nav Menu Roles and any other missing post meta for the Nav Menu items.', 'nav-menu-roles' ).'</p>';
        echo '<p>'.__( 'Choose a WXR (.xml) file to upload, then click Upload file and import.', 'nav-menu-roles' ).'</p>';
        wp_import_upload_form( 'admin.php?import=nav_menu_roles&amp;step=1' );
        echo '</div>';
    }

    /**
     * Decide if the given meta key maps to information we will want to import
     *
     * @param string $key The meta key to check
     * @return string|bool The key if we do want to import, false if not
     */
    function is_valid_meta_key( $key ) {
        // skip attachment metadata since we'll regenerate it from scratch
        // skip _edit_lock as not relevant for import
        if ( in_array( $key, array( '_wp_attached_file', '_wp_attachment_metadata', '_edit_lock' ) ) )
            return false;
        return $key;
    }


    /**
     * Added to http_request_timeout filter to force timeout at 60 seconds during import
     * @return int 60
     */
    function bump_request_timeout() {
        return 60;
    }

    // return the difference in length between two strings
    function cmpr_strlen( $a, $b ) {
        return strlen($b) - strlen($a);
    }


    } // end class
} // end if
0
helgatheviking