OCT
2

WPCustomFieldsEditor書き直し

Published:2008-10-02 01:18:04 UTC

先日WPCustomFieldsEditorが正常に動作しないというコメントがあり、良い機会なのでBugFixも兼ねてWordPressとXML-RPC APIを通じて遣り取りを行う部分を書き直してみました。これまでは文字列連結でリクエスト用のXMLを捻り出してなんとか凌いでいたのですが、WindowsLive.Writer.CoreServices.dllにXML-RPC Clientライブラリがあるのを見つけたので、今回はそのお世話になることに。WLWのプラグインを作る分には怒られないんじゃないかな・・・?

で、以下が書き直した後のOnPostPublishメソッドのソースコード。

        public override void OnPostPublish(IWin32Window dialogOwner, IProperties properties, IPublishingContext publishingContext, bool publish) {

            PostEditorForm postEditorForm = getPostEditorForm(dialogOwner);
            Blog blog = new Blog(postEditorForm.CurrentBlogId);
            PropertyInfo propInfo = blog.GetType().GetProperty("BlogClient", BindingFlags.NonPublic | BindingFlags.Instance);
            IBlogClient blogClient = (IBlogClient)propInfo.GetValue(blog, null);

            WordPressClient xmlRpcClient = blogClient as WordPressClient;
            if (xmlRpcClient != null && !publishingContext.PostInfo.IsPage) {

                const string userAgent = "WPCustomFieldEditor";

                XmlRpcString postId = new XmlRpcString(publishingContext.PostInfo.Id);
                XmlRpcString userName = new XmlRpcString(xmlRpcClient.Username);
                XmlRpcString password = new XmlRpcString(xmlRpcClient.Password);

                HttpRequestFilter filter = delegate(System.Net.HttpWebRequest request) {
                };
                XmlRpcClient client = new XmlRpcClient(blog.PostApiUrl, userAgent, filter, xmlRpcClient.Options.CharacterSet);
                XmlRpcMethodResponse res = client.CallMethod("metaWeblog.getPost", postId, userName, password);
                if (res.FaultOccurred) {
                    showErrorMessage(dialogOwner, res.FaultString);
                    return;
                }

                XmlNodeList customFieldsNodes = res.Response.SelectNodes("//struct/member[name="custom_fields"]/value/array/data/value/struct");

                CustomField[] customFields = new CustomField[customFieldsNodes.Count];
                for (int i = 0; i < customFieldsNodes.Count; i++) {
                    XmlNode item = customFieldsNodes[i];
                    customFields[i] = new CustomField();
                    customFields[i].Id = item.SelectSingleNode("member[name="id"]/value/string").InnerText;
                    customFields[i].Key = item.SelectSingleNode("member[name="key"]/value/string").InnerText;
                    customFields[i].Value = item.SelectSingleNode("member[name="value"]/value/string").InnerText;
                }

                WPCustomFieldsEditor fieldEditor = new WPCustomFieldsEditor(customFields, this.Options);
                DialogResult result = fieldEditor.ShowDialog(dialogOwner);
                if (result == DialogResult.OK) {

                    Func getRpcMemberValue = delegate(string name) {
                        return res.Response.SelectSingleNode("//struct/member[name="" + name + ""]/value/*").InnerText;
                    };

                    XmlRpcStruct[] cv = new XmlRpcStruct[fieldEditor.CustomFields.Length];
                    for (int i = 0; i < cv.Length; i++) {
                        CustomField sourceItem = fieldEditor.CustomFields[i];
                        List<XmlRpcMember> structMember = new List<XmlRpcMember>();
                        if(!string.IsNullOrEmpty(sourceItem.Id)){
                            structMember.Add(new XmlRpcMember("id", sourceItem.Id));
                        }
                        if(!string.IsNullOrEmpty(sourceItem.Key)){
                            structMember.Add(new XmlRpcMember("key", sourceItem.Key));
                        }
                        structMember.Add(new XmlRpcMember("value", sourceItem.Value));
                        cv[i] = new XmlRpcStruct(structMember.ToArray());
                    }

                    XmlRpcStruct content = new XmlRpcStruct(new XmlRpcMember[]{
                        new XmlRpcMember("title",getRpcMemberValue("title")),
                        new XmlRpcMember("description",getRpcMemberValue("description")),
                        new XmlRpcMember("mt_text_more",getRpcMemberValue("mt_text_more")),
                        new XmlRpcMember("mt_allow_comments",getRpcMemberValue("mt_allow_comments")),
                        new XmlRpcMember("mt_allow_pings",getRpcMemberValue("mt_allow_pings")),
                        new XmlRpcMember("mt_keywords",getRpcMemberValue("mt_keywords")),
                        new XmlRpcMember("wp_slug",getRpcMemberValue("wp_slug")),
                        new XmlRpcMember("wp_password",getRpcMemberValue("wp_password")),
                        new XmlRpcMember("wp_author_id",getRpcMemberValue("wp_author_id")),
                        new XmlRpcMember("mt_excerpt",getRpcMemberValue("mt_excerpt")),
                        new XmlRpcMember("mt_keywords",getRpcMemberValue("mt_keywords")),
                        new XmlRpcMember("custom_fields",new XmlRpcArray(cv))
                        });
                    XmlRpcBoolean isPublish = new XmlRpcBoolean(publish);
                    
                    res = client.CallMethod("metaWeblog.editPost", postId, userName, password, content, isPublish);
                    if (res.FaultOccurred) {
                        showErrorMessage(dialogOwner, res.FaultString);
                        return;
                    }
                }


            }


        }

WLWによるエントリの投稿が終わった後に呼び出され、サーバーからその投稿されたエントリのデータを取得し(20行目付近)、それに基づいてカスタムフィールドのデータを付加したエントリのデータを作成して投げ直すという流れ。