[wp-trac] [WordPress Trac] #43392: Support associative array type in register_meta()

WordPress Trac noreply at wordpress.org
Fri Feb 23 14:36:38 UTC 2018


#43392: Support associative array type in register_meta()
-------------------------+-----------------------------
 Reporter:  diegoliv     |      Owner:
     Type:  enhancement  |     Status:  new
 Priority:  normal       |  Milestone:  Awaiting Review
Component:  General      |    Version:  4.9.4
 Severity:  normal       |   Keywords:
  Focuses:  rest-api     |
-------------------------+-----------------------------
 Currently, `register_meta()` is used to expose meta data by setting
 `show_in_rest => true`. If you want to work with custom metadata on
 Gutenberg (by setting an attribute with `source: 'meta'`), you need to use
 `register_meta()`. Now, this function also has the parameter `type`, where
 you set the metadata object type. Currently, allowed types are simple
 things like `integer` or `string`.

 While I was working with Gutenberg, I felt the need to create nested
 attributes (that would translate into JSON objects). Here is an example:


 {{{
 attributes: {
     navigationStyles: {
         type: 'object',
         default: {
             fontSize: {
                 type: 'number',
                 default: 10,
             },
             fontColor: {
                 type: 'string',
                 default: '#ccc',
             },
         },
         source: 'meta',
         meta: 'navigation_styles',
     },
 },
 }}}

 Now, when Gutenberg tries to save this attribute on the database, the
 attribute will be a JSON object, which will translate into an associative
 array to be handled in PHP. But, currently, there's no support for
 registering a metadata with `register_meta()` that will be an associative
 array:

 {{{#!php
 <?php
 function blocks_meta_init(){
         register_meta('post', 'navigation_styles', array(
                 'show_in_rest' => true,
                 'type' => 'array', // not possible at the moment
         ));
 }

 add_action('init', 'blocks_blocks_meta_init');
 }}}

 If you try to do that, the REST API will fail to save the metadata. My
 current workaround for this use case is to just register the meta as a
 `string`, and handle the formatting of the metadata using
 `sanitize_callback`:

 {{{#!php
 <?php
 function blocks_meta_init(){
         register_meta('post', 'navigation_styles', array(
                 'show_in_rest' => true,
                 'type' => 'string',
                 'sanitize_callback' => 'blocks_sanitize_attr'
         ));
 }

 add_action('init', 'blocks_blocks_meta_init');

 function blocks_sanitize_attr( $meta_value, $meta_key, $meta_type ){
         return serialize( json_decode( $meta_value ) );
 }
 }}}

 This works, but has several limitations:

 * You need to turn your javascript object into a string
 (`JSON.stringify`)if you want to store it on the database.
 * You need to handle sanitization yourself
 * If you get the metadata using `get_post_meta()`, it won't apply
 `maybe_unserialize()` before returning the metadata, you need to do it
 yourself.

 I propose that we support the `'type' => 'array'` with `register_meta()`.
 This way, we'll have a proper way to store arrays or JSON objects as
 associative arrays. This would make the REST API more flexible, and
 project Gutenberg would also benefit by making attributes more flexible
 than they currently are.

--
Ticket URL: <https://core.trac.wordpress.org/ticket/43392>
WordPress Trac <https://core.trac.wordpress.org/>
WordPress publishing platform


More information about the wp-trac mailing list