wpmetabox / mb-rest-api

Add custom fields to WordPress REST API
19 stars 12 forks source link

Normalize values #8

Open radeno opened 5 years ago

radeno commented 5 years ago

Because WP lacking any better classification on datas (no matter it is legacy implementation) then all API metabox response fields are not described enought.

All fields values all called with https://developer.wordpress.org/reference/functions/get_metadata/ and it has very unhappy implementation for 2 main situations when somebody else want to work with data:

  1. Lacking any information if value exists or not. Everytime is returned empty string (very big mistake) https://codex.wordpress.org/Function_Reference/get_post_custom_values returns null what is right.
  2. Every field is returned as string. No matter when field is defined as number or association and whatever other.

Both situations should be fixed easy:

adding normalization function

    protected function has_array_value($array)
    {
        return !empty(array_filter(array_values($array), function ($value) {
            return is_array($value);
        }));
    }

    protected function has_string_key($array)
    {
        return !empty(array_filter(array_keys($array), function ($key) {
            return is_string($key);
        }));
    }

    protected function normalize_value($field, $value)
    {
        if ($value == '') {
            return null;
        }

        if (is_array($value)) {
            if (empty($value)) {
                return [];
            } elseif ($this->has_array_value($value) || $this->has_string_key($value)) {
                return $value;
            } else {
                return array_map([$this, 'sanitize_value'], $field, $value);
            }
        }

        if (in_array($field['type'], $this->numeric_fields)) {
            return numfmt_parse($field);
        }

        return $value;
    }

numeric fields are all association fields, media fields, and number fields

$this->numeric_fields = array_merge($this->media_fields, ['number', 'post', 'taxonomy']);

and then just wrap it on https://github.com/wpmetabox/mb-rest-api/blob/78ffdf23f695cde295ab46caae48908a860ac405/class-mb-rest-api.php#L272 with

$values[ $field['id'] ] = $this->normalize_value($field, $field_value);

Results are:

  1. All not set and empty string fields are null
  2. Empty array is still empty array (collection)
  3. All integer stringed fields are converted to integer
  4. Objects (assoc_array) is without touch
radeno commented 5 years ago

Or even easier and extendable: Add filter on value.

rilwis commented 5 years ago

Hi @radeno

Thanks a lot for your help! Would you mind making a PR for this?

radeno commented 5 years ago

@rilwis which one? Bcause i think this is breaking change.