/**
  * Validate current user can access the post
  * 
  * @return WP_Error or post
  */
 private function validate_access($post)
 {
     $context = $post->context;
     if (!$this->is_post_type_allowed($post->post_type) && (!function_exists('is_post_freshly_pressed') || !is_post_freshly_pressed($post->ID))) {
         return new WP_Error('unknown_post', 'Unknown post', 404);
     }
     switch ($context) {
         case 'edit':
             if (!current_user_can('edit_post', $post)) {
                 return new WP_Error('unauthorized', 'User cannot edit post', 403);
             }
             break;
         case 'display':
             $can_view = $this->user_can_view_post($post);
             if (is_wp_error($can_view)) {
                 return $can_view;
             }
             break;
         default:
             return new WP_Error('invalid_context', 'Invalid API CONTEXT', 400);
     }
     return $post;
 }
 /**
  * Get a post by a specified field and value
  *
  * @param string $field
  * @param string $field_value
  * @param string $context Post use context (e.g. 'display')
  * @return array Post
  **/
 function get_post_by($field, $field_value, $context = 'display')
 {
     global $blog_id;
     /** This filter is documented in class.json-api-endpoints.php */
     $is_jetpack = true === apply_filters('is_jetpack_site', false, $blog_id);
     if (defined('GEO_LOCATION__CLASS') && class_exists(GEO_LOCATION__CLASS)) {
         $geo = call_user_func(array(GEO_LOCATION__CLASS, 'init'));
     } else {
         $geo = false;
     }
     if ('display' === $context) {
         $args = $this->query_args();
         if (isset($args['content_width']) && $args['content_width']) {
             $GLOBALS['content_width'] = (int) $args['content_width'];
         }
     }
     if (strpos($_SERVER['HTTP_USER_AGENT'], 'wp-windows8')) {
         remove_shortcode('gallery', 'gallery_shortcode');
         add_shortcode('gallery', array(&$this, 'win8_gallery_shortcode'));
     }
     switch ($field) {
         case 'name':
             $post_id = $this->get_post_id_by_name($field_value);
             if (is_wp_error($post_id)) {
                 return $post_id;
             }
             break;
         default:
             $post_id = (int) $field_value;
             break;
     }
     $post = get_post($post_id, OBJECT, $context);
     if (!$post || is_wp_error($post)) {
         return new WP_Error('unknown_post', 'Unknown post', 404);
     }
     if (!$this->is_post_type_allowed($post->post_type) && (!function_exists('is_post_freshly_pressed') || !is_post_freshly_pressed($post->ID))) {
         return new WP_Error('unknown_post', 'Unknown post', 404);
     }
     // Permissions
     $capabilities = $this->get_current_user_capabilities($post);
     switch ($context) {
         case 'edit':
             if (!$capabilities['edit_post']) {
                 return new WP_Error('unauthorized', 'User cannot edit post', 403);
             }
             break;
         case 'display':
             break;
         default:
             return new WP_Error('invalid_context', 'Invalid API CONTEXT', 400);
     }
     $can_view = $this->user_can_view_post($post->ID);
     if (!$can_view || is_wp_error($can_view)) {
         return $can_view;
     }
     $GLOBALS['post'] = $post;
     if ('display' === $context) {
         setup_postdata($post);
     }
     $response = array();
     foreach (array_keys($this->post_object_format) as $key) {
         switch ($key) {
             case 'ID':
                 // explicitly cast all output
                 $response[$key] = (int) $post->ID;
                 break;
             case 'site_ID':
                 $response[$key] = (int) $this->api->get_blog_id_for_output();
                 break;
             case 'author':
                 $response[$key] = (object) $this->get_author($post, 'edit' === $context && $capabilities['edit_post']);
                 break;
             case 'date':
                 $response[$key] = (string) $this->format_date($post->post_date_gmt, $post->post_date);
                 break;
             case 'modified':
                 $response[$key] = (string) $this->format_date($post->post_modified_gmt, $post->post_modified);
                 break;
             case 'title':
                 if ('display' === $context) {
                     $response[$key] = (string) get_the_title($post->ID);
                 } else {
                     $response[$key] = (string) htmlspecialchars_decode($post->post_title, ENT_QUOTES);
                 }
                 break;
             case 'URL':
                 if ('revision' === $post->post_type) {
                     $response[$key] = (string) esc_url_raw(get_permalink($post->post_parent));
                 } else {
                     $response[$key] = (string) esc_url_raw(get_permalink($post->ID));
                 }
                 break;
             case 'short_URL':
                 $response[$key] = (string) esc_url_raw(wp_get_shortlink($post->ID));
                 break;
             case 'content':
                 if ('display' === $context) {
                     add_filter('the_password_form', array($this, 'the_password_form'));
                     $response[$key] = (string) $this->get_the_post_content_for_display();
                     remove_filter('the_password_form', array($this, 'the_password_form'));
                 } else {
                     $response[$key] = (string) $post->post_content;
                 }
                 break;
             case 'excerpt':
                 if ('display' === $context) {
                     add_filter('the_password_form', array($this, 'the_password_form'));
                     ob_start();
                     the_excerpt();
                     $response[$key] = (string) ob_get_clean();
                     remove_filter('the_password_form', array($this, 'the_password_form'));
                 } else {
                     $response[$key] = htmlspecialchars_decode((string) $post->post_excerpt, ENT_QUOTES);
                 }
                 break;
             case 'status':
                 $response[$key] = (string) get_post_status($post->ID);
                 break;
             case 'sticky':
                 $response[$key] = (bool) is_sticky($post->ID);
                 break;
             case 'slug':
                 $response[$key] = (string) $post->post_name;
                 break;
             case 'guid':
                 $response[$key] = (string) $post->guid;
                 break;
             case 'password':
                 $response[$key] = (string) $post->post_password;
                 if ('edit' === $context) {
                     $response[$key] = htmlspecialchars_decode((string) $response[$key], ENT_QUOTES);
                 }
                 break;
             case 'parent':
                 // (object|false)
                 if ($post->post_parent) {
                     $parent = get_post($post->post_parent);
                     if ('display' === $context) {
                         $parent_title = (string) get_the_title($parent->ID);
                     } else {
                         $parent_title = (string) htmlspecialchars_decode($post->post_title, ENT_QUOTES);
                     }
                     $response[$key] = (object) array('ID' => (int) $parent->ID, 'type' => (string) $parent->post_type, 'link' => (string) $this->get_post_link($this->api->get_blog_id_for_output(), $parent->ID), 'title' => $parent_title);
                 } else {
                     $response[$key] = false;
                 }
                 break;
             case 'type':
                 $response[$key] = (string) $post->post_type;
                 break;
             case 'discussion':
                 $response[$key] = array('comments_open' => (bool) comments_open($post->ID), 'comment_status' => (string) $post->comment_status, 'pings_open' => (bool) pings_open($post->ID), 'ping_status' => (string) $post->ping_status, 'comment_count' => (int) $post->comment_count);
                 break;
             case 'likes_enabled':
                 /** This filter is documented in modules/likes.php */
                 $sitewide_likes_enabled = (bool) apply_filters('wpl_is_enabled_sitewide', !get_option('disabled_likes'));
                 $post_likes_switched = (bool) get_post_meta($post->ID, 'switch_like_status', true);
                 $post_likes_enabled = $sitewide_likes_enabled;
                 if ($post_likes_switched) {
                     $post_likes_enabled = !$post_likes_enabled;
                 }
                 $response[$key] = (bool) $post_likes_enabled;
                 break;
             case 'sharing_enabled':
                 $show = true;
                 /** This filter is documented in modules/sharedaddy/sharing-service.php */
                 $show = apply_filters('sharing_show', $show, $post);
                 $switched_status = get_post_meta($post->ID, 'sharing_disabled', false);
                 if (!empty($switched_status)) {
                     $show = false;
                 }
                 $response[$key] = (bool) $show;
                 break;
             case 'like_count':
                 $response[$key] = (int) $this->api->post_like_count($blog_id, $post->ID);
                 break;
             case 'i_like':
                 $response[$key] = (int) $this->api->is_liked($blog_id, $post->ID);
                 break;
             case 'is_reblogged':
                 $response[$key] = (int) $this->api->is_reblogged($blog_id, $post->ID);
                 break;
             case 'is_following':
                 $response[$key] = (int) $this->api->is_following($blog_id);
                 break;
             case 'global_ID':
                 $response[$key] = (string) $this->api->add_global_ID($blog_id, $post->ID);
                 break;
             case 'featured_image':
                 if ($is_jetpack && (defined('IS_WPCOM') && IS_WPCOM)) {
                     $response[$key] = get_post_meta($post->ID, '_jetpack_featured_image', true);
                 } else {
                     $image_attributes = wp_get_attachment_image_src(get_post_thumbnail_id($post->ID), 'full');
                     if (is_array($image_attributes) && isset($image_attributes[0])) {
                         $response[$key] = (string) $image_attributes[0];
                     } else {
                         $response[$key] = '';
                     }
                 }
                 break;
             case 'post_thumbnail':
                 $response[$key] = null;
                 $thumb_id = get_post_thumbnail_id($post->ID);
                 if (!empty($thumb_id)) {
                     $attachment = get_post($thumb_id);
                     if (!empty($attachment)) {
                         $featured_image_object = $this->get_attachment($attachment);
                     }
                     if (!empty($featured_image_object)) {
                         $response[$key] = (object) $featured_image_object;
                     }
                 }
                 break;
             case 'format':
                 $response[$key] = (string) get_post_format($post->ID);
                 if (!$response[$key]) {
                     $response[$key] = 'standard';
                 }
                 break;
             case 'geo':
                 // (object|false)
                 if (!$geo) {
                     $response[$key] = false;
                 } else {
                     $geo_data = $geo->get_geo('post', $post->ID);
                     $response[$key] = false;
                     if ($geo_data) {
                         $geo_data = array_intersect_key($geo_data, array('latitude' => true, 'longitude' => true, 'address' => true, 'public' => true));
                         if ($geo_data) {
                             $response[$key] = (object) array('latitude' => isset($geo_data['latitude']) ? (double) $geo_data['latitude'] : 0, 'longitude' => isset($geo_data['longitude']) ? (double) $geo_data['longitude'] : 0, 'address' => isset($geo_data['address']) ? (string) $geo_data['address'] : '');
                         } else {
                             $response[$key] = false;
                         }
                         // Private
                         if (!isset($geo_data['public']) || !$geo_data['public']) {
                             if ('edit' !== $context || !$capabilities['edit_post']) {
                                 // user can't access
                                 $response[$key] = false;
                             }
                         }
                     }
                 }
                 break;
             case 'menu_order':
                 $response[$key] = (int) $post->menu_order;
                 break;
             case 'page_template':
                 $response[$key] = (string) get_post_meta($post->ID, '_wp_page_template', true);
                 break;
             case 'publicize_URLs':
                 $publicize_URLs = array();
                 $publicize = get_post_meta($post->ID, 'publicize_results', true);
                 if ($publicize) {
                     foreach ($publicize as $service => $data) {
                         switch ($service) {
                             case 'twitter':
                                 foreach ($data as $datum) {
                                     $publicize_URLs[] = esc_url_raw("https://twitter.com/{$datum['user_id']}/status/{$datum['post_id']}");
                                 }
                                 break;
                             case 'fb':
                                 foreach ($data as $datum) {
                                     $publicize_URLs[] = esc_url_raw("https://www.facebook.com/permalink.php?story_fbid={$datum['post_id']}&id={$datum['user_id']}");
                                 }
                                 break;
                         }
                     }
                 }
                 $response[$key] = (array) $publicize_URLs;
                 break;
             case 'tags':
                 $response[$key] = array();
                 $terms = wp_get_post_tags($post->ID);
                 foreach ($terms as $term) {
                     if (!empty($term->name)) {
                         $response[$key][$term->name] = $this->format_taxonomy($term, 'post_tag', 'display');
                     }
                 }
                 $response[$key] = (object) $response[$key];
                 break;
             case 'categories':
                 $response[$key] = array();
                 $terms = wp_get_object_terms($post->ID, 'category', array('fields' => 'all'));
                 foreach ($terms as $term) {
                     if (!empty($term->name)) {
                         $response[$key][$term->name] = $this->format_taxonomy($term, 'category', 'display');
                     }
                 }
                 $response[$key] = (object) $response[$key];
                 break;
             case 'attachments':
                 $response[$key] = array();
                 $_attachments = new WP_Query(array('post_parent' => $post->ID, 'post_status' => 'inherit', 'post_type' => 'attachment', 'posts_per_page' => '20'));
                 foreach ($_attachments->posts as $attachment) {
                     $response[$key][$attachment->ID] = $this->get_media_item_v1_1($attachment->ID);
                 }
                 $response['attachment_count'] = $_attachments->found_posts;
                 $response[$key] = (object) $response[$key];
                 break;
             case 'metadata':
                 // (array|false)
                 $metadata = array();
                 foreach ((array) has_meta($post_id) as $meta) {
                     // Don't expose protected fields.
                     $show = false;
                     if ($this->is_metadata_public($meta['meta_key'])) {
                         $show = true;
                     }
                     if (current_user_can('edit_post_meta', $post_id, $meta['meta_key'])) {
                         $show = true;
                     }
                     if (!$show) {
                         continue;
                     }
                     $metadata[] = array('id' => $meta['meta_id'], 'key' => $meta['meta_key'], 'value' => maybe_unserialize($meta['meta_value']));
                 }
                 if (!empty($metadata)) {
                     $response[$key] = $metadata;
                 } else {
                     $response[$key] = false;
                 }
                 break;
             case 'meta':
                 $response[$key] = (object) array('links' => (object) array('self' => (string) $this->get_post_link($this->api->get_blog_id_for_output(), $post->ID), 'help' => (string) $this->get_post_link($this->api->get_blog_id_for_output(), $post->ID, 'help'), 'site' => (string) $this->get_site_link($this->api->get_blog_id_for_output()), 'replies' => (string) $this->get_post_link($this->api->get_blog_id_for_output(), $post->ID, 'replies/'), 'likes' => (string) $this->get_post_link($this->api->get_blog_id_for_output(), $post->ID, 'likes/')));
                 break;
             case 'capabilities':
                 $response[$key] = $capabilities;
                 break;
         }
     }
     // WPCOM_JSON_API_Post_Endpoint::find_featured_worthy_media( $post );
     // $response['featured_media'] = self::find_featured_media( $response );
     unset($GLOBALS['post']);
     return $response;
 }