wp-net / WordPressPCL

This is a portable library for consuimg the WordPress REST-API in (almost) any C# application
MIT License
338 stars 129 forks source link

Insert/Update meta data of custom post type #186

Open dirkil opened 4 years ago

dirkil commented 4 years ago

I use WordpressPCL to create posts for my custom post type. This works fine so far. But I also would like to insert / update meta for it. I tried it like that:

try
            {
                var metaSample = new Dictionary<string, object>()
                {
                    { "_psi_geo_plz", "61169" }
                };
                WordPressClient client = await GetClient();
                if (await client.IsValidJWToken())
                {
                    var post = new Post
                    {
                        Title = new Title("Schöne EF in Obernburg"),
                        Content = new Content("Hier steht ein Text"),

                        Type = "ps_immobilie",
                        Meta = metaSample

                    };

                    var createdPost = await client.CustomRequest.Create<Post, Post>("wp/v2/ps_immobilie", post);
                }
            }
            catch (Exception e)
            {
                Console.WriteLine("Error:" + e.Message);
            }

This creates the post as a custom post type but no meta data is set whatsoever.

I also added this to my functions.php:

function custom_field_get_post_meta_cb($object, $field_name, $request){ 
    error_log('HEUREKA - Get!');
    $metas = get_post_custom($post_id);

    foreach($metas as $key => $value) {
        if(sizeof($value) == 1) {
        $metas[$key] = $value[0];
        }
    }
    return $metas;          
}

function custom_field_update_post_meta_cb($value, $object, $field_name){
    error_log('HEUREKA - Update!');
    error_log( print_r( $value, 1 ) );
    return update_post_meta($object['id'], $field_name, $value); 
}

add_action('rest_api_init', function(){

    register_rest_field('ps_immobilie', '_psi_geo_plz', 
        array(
            'get_callback' => 'custom_field_get_post_meta_cb',
            'update_callback' => 'custom_field_update_post_meta_cb')
    ); 

});

But no success. I can see only the debug entry "HEUREKA - Get!"; the update callback is not called.

Any help with this is very much appreciated.

Regards, Dirk.

ThomasPe commented 4 years ago

Have you checked if it works when you're using the API directly (for example using Postman)?

dirkil commented 4 years ago

Excellent advice! I tried that and found out that when I enter data for my custom post type fields through the browser (when I am logged in) the data end up in a place I could not have imagined:

"author": 1,
    "featured_media": 0,
    "menu_order": 0,
    "comment_status": "open",
    "ping_status": "open",
    "template": "",
    "format": "standard",
    "meta": [],
    "cmb2": {
        "geo_metabox": {
            "_psi_geo_plz": "12345",
            "_psi_geo_ort": "",
            "_psi_geo_strasse": "",
            "_psi_geo_hausnr": "",
            "_psi_geo_land": ""
        }

I am referring to the field _psi_geo_plz for example. I would have thought it lives somewhere underneath "meta" but in fact in lives underneath "cmb2".

So, I rephrase my question: how can I set "cmb2.geo_metabox._psi_geo_plz" with WordpressPCL?

dirkil commented 4 years ago

I found out that I have to issue a HTTP POST on the following URL to update the value:

/wp-json/cmb2/v1/boxes/geo_metabox/fields/_psi_geo_plz?object_type=ps_immobilie&object_id=13784&value=44444 Is there a way to do that with WordpressPCL? This should do the trick.
ThomasPe commented 4 years ago

Check out the CustomRequest method which allows you to specifiy the path & model you'd like to use: https://github.com/wp-net/WordPressPCL/wiki/CustomRequest

dirkil commented 4 years ago

@ThomasPe Thank you for this great advice. I tried that but I still get an error and I would like you to have a look at that. It is probably something trivial but I am not able to figure it out myself.

Here is the C# code to update the field _psi_geo_plz:

`private static async Task RunSampleUpdate() { // JWT authentication var client = new WordPressClient("https:///wp-json/") { AuthMethod = AuthMethod.JWT }; await client.RequestJWToken("", "");

        try
        {
            if (await client.IsValidJWToken())
            {
                var updatedPost = await client.CustomRequest.Update<Post, Post>("cmb2/v1/boxes/geo_metabox/fields/_psi_geo_plz?object_type=post&object_id=13784&value=55555", new Post());
            }
        }
        catch (Exception e)
        {
            Console.WriteLine("Error:" + e.Message);
        }
    }

`

When I run this a JsonReaderException is thrown with the message: "Could not convert string to integer: _psi_geo_plz. Path 'id', line 1, position 610."

When I send the request following through Postman the value is updated in Wordpress. So, I reckon the Wordpress part is correct. It must be some problem in my C# code. Here is the request I send through Postman: curl --location --request POST 'https://<domain>/wp-json/cmb2/v1/boxes/geo_metabox/fields/_psi_geo_plz?object_type=post&object_id=13784&value=55555' \ --header 'Content-Type: application/json' \ --data-raw ''

I hope you can spot what I am doing wrong. Any help is very much appreciated!

Regards, Dirk.