WPCOM_JSON_API_Endpoint::cast_and_filter_item PHP Method

cast_and_filter_item() public method

Handles fallbacks for certain values of $type when $value is not that $type Currently, only handles fallback between string <-> array (two way), from string -> false (one way), and from object -> false (one way), and string -> object (one way) Handles "child types" - array:URL, object:category array:URL means an array of URLs object:category means a hash of categories Handles object typing - object>post means an object of type post
public cast_and_filter_item ( &$return, $type, $key, $value, $types = [], $for_output = false )
    function cast_and_filter_item(&$return, $type, $key, $value, $types = array(), $for_output = false)
    {
        if (is_string($type)) {
            $type = compact('type');
        }
        switch ($type['type']) {
            case 'false':
                $return[$key] = false;
                break;
            case 'url':
                $return[$key] = (string) esc_url_raw($value);
                break;
            case 'string':
                // Fallback string -> array, or for string -> object
                if (is_array($value) || is_object($value)) {
                    if (!empty($types[0])) {
                        $next_type = array_shift($types);
                        return $this->cast_and_filter_item($return, $next_type, $key, $value, $types, $for_output);
                    }
                }
                // Fallback string -> false
                if (!is_string($value)) {
                    if (!empty($types[0]) && 'false' === $types[0]['type']) {
                        $next_type = array_shift($types);
                        return $this->cast_and_filter_item($return, $next_type, $key, $value, $types, $for_output);
                    }
                }
                $return[$key] = (string) $value;
                break;
            case 'html':
                $return[$key] = (string) $value;
                break;
            case 'safehtml':
                $return[$key] = wp_kses((string) $value, wp_kses_allowed_html());
                break;
            case 'zip':
            case 'media':
                if (is_array($value)) {
                    if (isset($value['name']) && is_array($value['name'])) {
                        // It's a $_FILES array
                        // Reformat into array of $_FILES items
                        $files = array();
                        foreach ($value['name'] as $k => $v) {
                            $files[$k] = array();
                            foreach (array_keys($value) as $file_key) {
                                $files[$k][$file_key] = $value[$file_key][$k];
                            }
                        }
                        $return[$key] = $files;
                        break;
                    }
                } else {
                    // no break - treat as 'array'
                }
                // nobreak
            // nobreak
            case 'array':
                // Fallback array -> string
                if (is_string($value)) {
                    if (!empty($types[0])) {
                        $next_type = array_shift($types);
                        return $this->cast_and_filter_item($return, $next_type, $key, $value, $types, $for_output);
                    }
                }
                if (isset($type['children'])) {
                    $children = array();
                    foreach ((array) $value as $k => $child) {
                        $this->cast_and_filter_item($children, $type['children'], $k, $child, array(), $for_output);
                    }
                    $return[$key] = (array) $children;
                    break;
                }
                $return[$key] = (array) $value;
                break;
            case 'iso 8601 datetime':
            case 'datetime':
                // (string)s
                $dates = $this->parse_date((string) $value);
                if ($for_output) {
                    $return[$key] = $this->format_date($dates[1], $dates[0]);
                } else {
                    list($return[$key], $return["{$key}_gmt"]) = $dates;
                }
                break;
            case 'float':
                $return[$key] = (double) $value;
                break;
            case 'int':
            case 'integer':
                $return[$key] = (int) $value;
                break;
            case 'bool':
            case 'boolean':
                $return[$key] = (bool) WPCOM_JSON_API::is_truthy($value);
                break;
            case 'object':
                // Fallback object -> false
                if (is_scalar($value) || is_null($value)) {
                    if (!empty($types[0]) && 'false' === $types[0]['type']) {
                        return $this->cast_and_filter_item($return, 'false', $key, $value, $types, $for_output);
                    }
                }
                if (isset($type['children'])) {
                    $children = array();
                    foreach ((array) $value as $k => $child) {
                        $this->cast_and_filter_item($children, $type['children'], $k, $child, array(), $for_output);
                    }
                    $return[$key] = (object) $children;
                    break;
                }
                if (isset($type['subtype'])) {
                    return $this->cast_and_filter_item($return, $type['subtype'], $key, $value, $types, $for_output);
                }
                $return[$key] = (object) $value;
                break;
            case 'post':
                $return[$key] = (object) $this->cast_and_filter($value, $this->post_object_format, false, $for_output);
                break;
            case 'comment':
                $return[$key] = (object) $this->cast_and_filter($value, $this->comment_object_format, false, $for_output);
                break;
            case 'tag':
            case 'category':
                $docs = array('ID' => '(int)', 'name' => '(string)', 'slug' => '(string)', 'description' => '(HTML)', 'post_count' => '(int)', 'meta' => '(object)');
                if ('category' === $type['type']) {
                    $docs['parent'] = '(int)';
                }
                $return[$key] = (object) $this->cast_and_filter($value, $docs, false, $for_output);
                break;
            case 'post_reference':
            case 'comment_reference':
                $docs = array('ID' => '(int)', 'type' => '(string)', 'title' => '(string)', 'link' => '(URL)');
                $return[$key] = (object) $this->cast_and_filter($value, $docs, false, $for_output);
                break;
            case 'geo':
                $docs = array('latitude' => '(float)', 'longitude' => '(float)', 'address' => '(string)');
                $return[$key] = (object) $this->cast_and_filter($value, $docs, false, $for_output);
                break;
            case 'author':
                $docs = array('ID' => '(int)', 'user_login' => '(string)', 'login' => '(string)', 'email' => '(string|false)', 'name' => '(string)', 'first_name' => '(string)', 'last_name' => '(string)', 'nice_name' => '(string)', 'URL' => '(URL)', 'avatar_URL' => '(URL)', 'profile_URL' => '(URL)', 'is_super_admin' => '(bool)', 'roles' => '(array:string)');
                $return[$key] = (object) $this->cast_and_filter($value, $docs, false, $for_output);
                break;
            case 'role':
                $docs = array('name' => '(string)', 'display_name' => '(string)', 'capabilities' => '(object:boolean)');
                $return[$key] = (object) $this->cast_and_filter($value, $docs, false, $for_output);
                break;
            case 'attachment':
                $docs = array('ID' => '(int)', 'URL' => '(URL)', 'guid' => '(string)', 'mime_type' => '(string)', 'width' => '(int)', 'height' => '(int)', 'duration' => '(int)');
                $return[$key] = (object) $this->cast_and_filter($value, apply_filters('wpcom_json_api_attachment_cast_and_filter', $docs), false, $for_output);
                break;
            case 'metadata':
                $docs = array('id' => '(int)', 'key' => '(string)', 'value' => '(string|false|float|int|array|object)', 'previous_value' => '(string)', 'operation' => '(string)');
                $return[$key] = (object) $this->cast_and_filter($value, apply_filters('wpcom_json_api_attachment_cast_and_filter', $docs), false, $for_output);
                break;
            case 'plugin':
                $docs = array('id' => '(safehtml) The plugin\'s ID', 'slug' => '(safehtml) The plugin\'s Slug', 'active' => '(boolean)  The plugin status.', 'update' => '(object)   The plugin update info.', 'name' => '(safehtml) The name of the plugin.', 'plugin_url' => '(url)      Link to the plugin\'s web site.', 'version' => '(safehtml) The plugin version number.', 'description' => '(safehtml) Description of what the plugin does and/or notes from the author', 'author' => '(safehtml) The plugin author\'s name', 'author_url' => '(url)      The plugin author web site address', 'network' => '(boolean)  Whether the plugin can only be activated network wide.', 'autoupdate' => '(boolean)  Whether the plugin is auto updated', 'log' => '(array:safehtml) An array of update log strings.');
                $return[$key] = (object) $this->cast_and_filter($value, apply_filters('wpcom_json_api_plugin_cast_and_filter', $docs), false, $for_output);
                break;
            case 'jetpackmodule':
                $docs = array('id' => '(string)   The module\'s ID', 'active' => '(boolean)  The module\'s status.', 'name' => '(string)   The module\'s name.', 'description' => '(safehtml) The module\'s description.', 'sort' => '(int)      The module\'s display order.', 'introduced' => '(string)   The Jetpack version when the module was introduced.', 'changed' => '(string)   The Jetpack version when the module was changed.', 'free' => '(boolean)  The module\'s Free or Paid status.', 'module_tags' => '(array)    The module\'s tags.');
                $return[$key] = (object) $this->cast_and_filter($value, apply_filters('wpcom_json_api_plugin_cast_and_filter', $docs), false, $for_output);
                break;
            case 'sharing_button':
                $docs = array('ID' => '(string)', 'name' => '(string)', 'URL' => '(string)', 'icon' => '(string)', 'enabled' => '(bool)', 'visibility' => '(string)');
                $return[$key] = (array) $this->cast_and_filter($value, $docs, false, $for_output);
                break;
            case 'sharing_button_service':
                $docs = array('ID' => '(string) The service identifier', 'name' => '(string) The service name', 'class_name' => '(string) Class name for custom style sharing button elements', 'genericon' => '(string) The Genericon unicode character for the custom style sharing button icon', 'preview_smart' => '(string) An HTML snippet of a rendered sharing button smart preview', 'preview_smart_js' => '(string) An HTML snippet of the page-wide initialization scripts used for rendering the sharing button smart preview');
                $return[$key] = (array) $this->cast_and_filter($value, $docs, false, $for_output);
                break;
            case 'taxonomy':
                $docs = array('name' => '(string) The taxonomy slug', 'label' => '(string) The taxonomy human-readable name', 'labels' => '(object) Mapping of labels for the taxonomy', 'description' => '(string) The taxonomy description', 'hierarchical' => '(bool) Whether the taxonomy is hierarchical', 'public' => '(bool) Whether the taxonomy is public', 'capabilities' => '(object) Mapping of current user capabilities for the taxonomy');
                $return[$key] = (array) $this->cast_and_filter($value, $docs, false, $for_output);
                break;
            default:
                $method_name = $type['type'] . '_docs';
                if (method_exists(WPCOM_JSON_API_Jetpack_Overrides, $method_name)) {
                    $docs = WPCOM_JSON_API_Jetpack_Overrides::$method_name();
                }
                if (!empty($docs)) {
                    $return[$key] = (object) $this->cast_and_filter($value, apply_filters('wpcom_json_api_plugin_cast_and_filter', $docs), false, $for_output);
                } else {
                    trigger_error("Unknown API casting type {$type['type']}", E_USER_WARNING);
                }
        }
    }