/**
  * Used to modify the default title with custom SEO title.
  *
  * @param string $default_title Default title for current page.
  *
  * @return string Custom title with replaced tokens or default title.
  */
 public static function get_custom_title($default_title = '')
 {
     // Don't filter title for unsupported themes.
     if (self::is_conflicted_theme()) {
         return $default_title;
     }
     $page_type = self::get_page_type();
     // Keep default title if invalid page type is supplied.
     if (empty($page_type)) {
         return $default_title;
     }
     $title_formats = self::get_custom_title_formats();
     // Keep default title if user has not defined custom title for this page type.
     if (empty($title_formats[$page_type])) {
         return $default_title;
     }
     if (!Jetpack_SEO_Utils::is_enabled_jetpack_seo()) {
         return $default_title;
     }
     $custom_title = '';
     $format_array = $title_formats[$page_type];
     foreach ($format_array as $item) {
         if ('token' == $item['type']) {
             $custom_title .= self::get_token_value($item['value']);
         } else {
             $custom_title .= $item['value'];
         }
     }
     return esc_html($custom_title);
 }
 /**
  * Returns post's custom meta description if it is set, and if
  * SEO tools are enabled for current blog.
  *
  * @param WP_Post $post Source of data for custom description
  *
  * @return string Custom description or empty string
  */
 public static function get_post_custom_description($post)
 {
     if (empty($post)) {
         return '';
     }
     $custom_description = get_post_meta($post->ID, self::DESCRIPTION_META_KEY, true);
     if (empty($custom_description) || !Jetpack_SEO_Utils::is_enabled_jetpack_seo()) {
         return '';
     }
     return $custom_description;
 }
Beispiel #3
0
 public function meta_tags()
 {
     global $wp_query;
     $period = '';
     $template = '';
     $meta = array();
     /**
      * Can be used to specify a list of themes that set their own meta tags.
      *
      * If current site is using one of the themes listed as conflicting, inserting Jetpack SEO
      * meta tags will be prevented.
      *
      * @module seo-tools
      *
      * @since 4.4.0
      *
      * @param array List of conflicted theme names. Defaults to empty array.
      */
     $conflicted_themes = apply_filters('jetpack_seo_meta_tags_conflicted_themes', array());
     if (isset($conflicted_themes[get_option('template')])) {
         return;
     }
     /**
      * Can be used to insert custom site host that will used for meta title.
      *
      * @module seo-tools
      *
      * @since 4.4.0
      *
      * @param string Name of the site host. Defaults to empty string.
      */
     $site_host = apply_filters('jetpack_seo_site_host', '');
     $meta['title'] = sprintf(_x('%1$s', 'Site Title', 'jetpack'), get_bloginfo('title'));
     if (!empty($site_host)) {
         $meta['title'] = sprintf(_x('%1$s on %2$s', 'Site Title on WordPress', 'jetpack'), get_bloginfo('title'), $site_host);
     }
     $front_page_meta = Jetpack_SEO_Utils::get_front_page_meta_description();
     $description = $front_page_meta ? $front_page_meta : get_bloginfo('description');
     $meta['description'] = trim($description);
     // Try to target things if we're on a "specific" page of any kind.
     if (is_singular()) {
         $meta['title'] = sprintf(_x('%1$s | %2$s', 'Post Title | Site Title on WordPress', 'jetpack'), get_the_title(), $meta['title']);
         // Business users can overwrite the description.
         if (!(is_front_page() && Jetpack_SEO_Utils::get_front_page_meta_description())) {
             $description = Jetpack_SEO_Posts::get_post_description(get_post());
             if ($description) {
                 $description = wp_trim_words(strip_shortcodes(wp_kses($description, array())));
                 $meta['description'] = $description;
             }
         }
     } elseif (is_author()) {
         $obj = get_queried_object();
         $meta['title'] = sprintf(_x('Posts by %1$s | %2$s', 'Posts by Author Name | Blog Title on WordPress', 'jetpack'), $obj->display_name, $meta['title']);
         $meta['description'] = sprintf(_x('Read all of the posts by %1$s on %2$s', 'Read all of the posts by Author Name on Blog Title', 'jetpack'), $obj->display_name, get_bloginfo('title'));
     } elseif (is_tag() || is_category() || is_tax()) {
         $obj = get_queried_object();
         $meta['title'] = sprintf(_x('Posts about %1$s on %2$s', 'Posts about Category on Blog Title', 'jetpack'), single_term_title('', false), get_bloginfo('title'));
         $description = get_term_field('description', $obj->term_id, $obj->taxonomy, 'raw');
         if (!is_wp_error($description) && '' != $description) {
             $meta['description'] = wp_trim_words($description);
         } else {
             $authors = $this->get_authors();
             $meta['description'] = wp_sprintf(_x('Posts about %1$s written by %2$l', 'Posts about Category written by John and Bob', 'jetpack'), single_term_title('', false), $authors);
         }
     } elseif (is_date()) {
         if (is_year()) {
             $period = get_query_var('year');
             $template = _nx('%1$s post published by %2$l in the year %3$s', '%1$s posts published by %2$l in the year %3$s', count($wp_query->posts), '10 posts published by John in the year 2012', 'jetpack');
         } elseif (is_month()) {
             $period = date('F Y', mktime(0, 0, 0, get_query_var('monthnum'), 1, get_query_var('year')));
             $template = _nx('%1$s post published by %2$l during %3$s', '%1$s posts published by %2$l during %3$s', count($wp_query->posts), '10 posts publishes by John during May 2012', 'jetpack');
         } elseif (is_day()) {
             $period = date('F j, Y', mktime(0, 0, 0, get_query_var('monthnum'), get_query_var('day'), get_query_var('year')));
             $template = _nx('%1$s post published by %2$l on %3$s', '%1$s posts published by %2$l on %3$s', count($wp_query->posts), '10 posts published by John on May 30, 2012', 'jetpack');
         }
         $meta['title'] = sprintf(_x('Posts from %1$s on %2$s', 'Posts from May 2012 on Blog Title', 'jetpack'), $period, get_bloginfo('title'));
         $authors = $this->get_authors();
         $meta['description'] = wp_sprintf($template, count($wp_query->posts), $authors, $period);
     }
     $custom_title = Jetpack_SEO_Titles::get_custom_title();
     if (!empty($custom_title)) {
         $meta['title'] = $custom_title;
     }
     /**
      * Can be used to edit the default SEO tools meta tags.
      *
      * @module seo-tools
      *
      * @since 4.4.0
      *
      * @param array Array that consists of meta name and meta content pairs.
      */
     $meta = apply_filters('jetpack_seo_meta_tags', $meta);
     // Output them
     foreach ($meta as $name => $content) {
         if (!empty($content)) {
             echo '<meta name="' . esc_attr($name) . '" content="' . esc_attr($content) . '" />' . "\n";
         }
     }
 }
 function write_post($path, $blog_id, $post_id)
 {
     $new = $this->api->ends_with($path, '/new');
     $args = $this->query_args();
     // unhook publicize, it's hooked again later -- without this, skipping services is impossible
     if (defined('IS_WPCOM') && IS_WPCOM) {
         remove_action('save_post', array($GLOBALS['publicize_ui']->publicize, 'async_publicize_post'), 100, 2);
         add_action('rest_api_inserted_post', array($GLOBALS['publicize_ui']->publicize, 'async_publicize_post'));
     }
     if ($new) {
         $input = $this->input(true);
         if ('revision' === $input['type']) {
             if (!isset($input['parent'])) {
                 return new WP_Error('invalid_input', 'Invalid request input', 400);
             }
             $input['status'] = 'inherit';
             // force inherit for revision type
             $input['slug'] = $input['parent'] . '-autosave-v1';
         } elseif (!isset($input['title']) && !isset($input['content']) && !isset($input['excerpt'])) {
             return new WP_Error('invalid_input', 'Invalid request input', 400);
         }
         // default to post
         if (empty($input['type'])) {
             $input['type'] = 'post';
         }
         $post_type = get_post_type_object($input['type']);
         if (!$this->is_post_type_allowed($input['type'])) {
             return new WP_Error('unknown_post_type', 'Unknown post type', 404);
         }
         if (!empty($input['author'])) {
             $author_id = $this->parse_and_set_author($input['author'], $input['type']);
             unset($input['author']);
             if (is_wp_error($author_id)) {
                 return $author_id;
             }
         }
         if ('publish' === $input['status']) {
             if (!current_user_can($post_type->cap->publish_posts)) {
                 if (current_user_can($post_type->cap->edit_posts)) {
                     $input['status'] = 'pending';
                 } else {
                     return new WP_Error('unauthorized', 'User cannot publish posts', 403);
                 }
             }
         } else {
             if (!current_user_can($post_type->cap->edit_posts)) {
                 return new WP_Error('unauthorized', 'User cannot edit posts', 403);
             }
         }
     } else {
         $input = $this->input(false);
         if (!is_array($input) || !$input) {
             return new WP_Error('invalid_input', 'Invalid request input', 400);
         }
         if (isset($input['status']) && 'trash' === $input['status'] && !current_user_can('delete_post', $post_id)) {
             return new WP_Error('unauthorized', 'User cannot delete post', 403);
         }
         $post = get_post($post_id);
         $_post_type = !empty($input['type']) ? $input['type'] : $post->post_type;
         $post_type = get_post_type_object($_post_type);
         if (!$post || is_wp_error($post)) {
             return new WP_Error('unknown_post', 'Unknown post', 404);
         }
         if (!current_user_can('edit_post', $post->ID)) {
             return new WP_Error('unauthorized', 'User cannot edit post', 403);
         }
         if (!empty($input['author'])) {
             $author_id = $this->parse_and_set_author($input['author'], $_post_type);
             unset($input['author']);
             if (is_wp_error($author_id)) {
                 return $author_id;
             }
         }
         if (isset($input['status']) && 'publish' === $input['status'] && 'publish' !== $post->post_status && !current_user_can('publish_post', $post->ID)) {
             $input['status'] = 'pending';
         }
         $last_status = $post->post_status;
         $new_status = isset($input['status']) ? $input['status'] : $last_status;
         // Make sure that drafts get the current date when transitioning to publish if not supplied in the post.
         $date_in_past = strtotime($post->post_date_gmt) < time();
         if ('publish' === $new_status && 'draft' === $last_status && !isset($input['date_gmt']) && $date_in_past) {
             $input['date_gmt'] = gmdate('Y-m-d H:i:s');
         }
     }
     if (function_exists('wpcom_switch_to_locale')) {
         // fixes calypso-pre-oss #12476: respect blog locale when creating the post slug
         wpcom_switch_to_locale(get_blog_lang_code($blog_id));
     }
     // If date was set, $this->input will set date_gmt, date still needs to be adjusted for the blog's offset
     if (isset($input['date_gmt'])) {
         $gmt_offset = get_option('gmt_offset');
         $time_with_offset = strtotime($input['date_gmt']) + $gmt_offset * HOUR_IN_SECONDS;
         $input['date'] = date('Y-m-d H:i:s', $time_with_offset);
     }
     if (!empty($author_id) && get_current_user_id() != $author_id) {
         if (!current_user_can($post_type->cap->edit_others_posts)) {
             return new WP_Error('unauthorized', "User is not allowed to publish others' posts.", 403);
         } elseif (!user_can($author_id, $post_type->cap->edit_posts)) {
             return new WP_Error('unauthorized', 'Assigned author cannot publish post.', 403);
         }
     }
     if (!is_post_type_hierarchical($post_type->name) && 'revision' !== $post_type->name) {
         unset($input['parent']);
     }
     $tax_input = array();
     foreach (array('categories' => 'category', 'tags' => 'post_tag') as $key => $taxonomy) {
         if (!isset($input[$key])) {
             continue;
         }
         $tax_input[$taxonomy] = array();
         $is_hierarchical = is_taxonomy_hierarchical($taxonomy);
         if (is_array($input[$key])) {
             $terms = $input[$key];
         } else {
             $terms = explode(',', $input[$key]);
         }
         foreach ($terms as $term) {
             /**
              * `curl --data 'category[]=123'` should be interpreted as a category ID,
              * not a category whose name is '123'.
              *
              * Consequence: To add a category/tag whose name is '123', the client must
              * first look up its ID.
              */
             $term = (string) $term;
             // ctype_digit compat
             if (ctype_digit($term)) {
                 $term = (int) $term;
             }
             $term_info = term_exists($term, $taxonomy);
             if (!$term_info) {
                 // A term ID that doesn't already exist. Ignore it: we don't know what name to give it.
                 if (is_int($term)) {
                     continue;
                 }
                 // only add a new tag/cat if the user has access to
                 $tax = get_taxonomy($taxonomy);
                 // see https://core.trac.wordpress.org/ticket/26409
                 if ('category' === $taxonomy && !current_user_can($tax->cap->edit_terms)) {
                     continue;
                 } else {
                     if (!current_user_can($tax->cap->assign_terms)) {
                         continue;
                     }
                 }
                 $term_info = wp_insert_term($term, $taxonomy);
             }
             if (!is_wp_error($term_info)) {
                 if ($is_hierarchical) {
                     // Categories must be added by ID
                     $tax_input[$taxonomy][] = (int) $term_info['term_id'];
                 } else {
                     // Tags must be added by name
                     if (is_int($term)) {
                         $term = get_term($term, $taxonomy);
                         $tax_input[$taxonomy][] = $term->name;
                     } else {
                         $tax_input[$taxonomy][] = $term;
                     }
                 }
             }
         }
     }
     if (isset($input['categories']) && empty($tax_input['category']) && 'revision' !== $post_type->name) {
         $tax_input['category'][] = get_option('default_category');
     }
     unset($input['tags'], $input['categories']);
     $insert = array();
     if (!empty($input['slug'])) {
         $insert['post_name'] = $input['slug'];
         unset($input['slug']);
     }
     if (isset($input['comments_open'])) {
         $insert['comment_status'] = true === $input['comments_open'] ? 'open' : 'closed';
     }
     if (isset($input['pings_open'])) {
         $insert['ping_status'] = true === $input['pings_open'] ? 'open' : 'closed';
     }
     unset($input['comments_open'], $input['pings_open']);
     if (isset($input['menu_order'])) {
         $insert['menu_order'] = $input['menu_order'];
         unset($input['menu_order']);
     }
     $publicize = isset($input['publicize']) ? $input['publicize'] : null;
     unset($input['publicize']);
     $publicize_custom_message = isset($input['publicize_message']) ? $input['publicize_message'] : null;
     unset($input['publicize_message']);
     if (isset($input['featured_image'])) {
         $featured_image = trim($input['featured_image']);
         $delete_featured_image = empty($featured_image);
         unset($input['featured_image']);
     }
     $metadata = isset($input['metadata']) ? $input['metadata'] : null;
     unset($input['metadata']);
     $likes = isset($input['likes_enabled']) ? $input['likes_enabled'] : null;
     unset($input['likes_enabled']);
     $sharing = isset($input['sharing_enabled']) ? $input['sharing_enabled'] : null;
     unset($input['sharing_enabled']);
     $sticky = isset($input['sticky']) ? $input['sticky'] : null;
     unset($input['sticky']);
     foreach ($input as $key => $value) {
         $insert["post_{$key}"] = $value;
     }
     if (!empty($author_id)) {
         $insert['post_author'] = absint($author_id);
     }
     if (!empty($tax_input)) {
         $insert['tax_input'] = $tax_input;
     }
     $has_media = isset($input['media']) && $input['media'] ? count($input['media']) : false;
     $has_media_by_url = isset($input['media_urls']) && $input['media_urls'] ? count($input['media_urls']) : false;
     if ($new) {
         if (isset($input['content']) && !has_shortcode($input['content'], 'gallery') && ($has_media || $has_media_by_url)) {
             switch ($has_media + $has_media_by_url) {
                 case 0:
                     // No images - do nothing.
                     break;
                 case 1:
                     // 1 image - make it big
                     $insert['post_content'] = $input['content'] = "[gallery size=full columns=1]\n\n" . $input['content'];
                     break;
                 default:
                     // Several images - 3 column gallery
                     $insert['post_content'] = $input['content'] = "[gallery]\n\n" . $input['content'];
                     break;
             }
         }
         $post_id = wp_insert_post(add_magic_quotes($insert), true);
     } else {
         $insert['ID'] = $post->ID;
         // wp_update_post ignores date unless edit_date is set
         // See: http://codex.wordpress.org/Function_Reference/wp_update_post#Scheduling_posts
         // See: https://core.trac.wordpress.org/browser/tags/3.9.2/src/wp-includes/post.php#L3302
         if (isset($input['date_gmt']) || isset($input['date'])) {
             $insert['edit_date'] = true;
         }
         $post_id = wp_update_post((object) $insert);
     }
     if (!$post_id || is_wp_error($post_id)) {
         return $post_id;
     }
     // make sure this post actually exists and is not an error of some kind (ie, trying to load media in the posts endpoint)
     $post_check = $this->get_post_by('ID', $post_id, $args['context']);
     if (is_wp_error($post_check)) {
         return $post_check;
     }
     if ($has_media) {
         $this->api->trap_wp_die('upload_error');
         foreach ($input['media'] as $media_item) {
             $_FILES['.api.media.item.'] = $media_item;
             // check for WP_Error if we ever actually need $media_id
             $media_id = media_handle_upload('.api.media.item.', $post_id);
         }
         $this->api->trap_wp_die(null);
         unset($_FILES['.api.media.item.']);
     }
     if ($has_media_by_url) {
         foreach ($input['media_urls'] as $url) {
             $this->handle_media_sideload($url, $post_id);
         }
     }
     // Set like status for the post
     /** This filter is documented in modules/likes.php */
     $sitewide_likes_enabled = (bool) apply_filters('wpl_is_enabled_sitewide', !get_option('disabled_likes'));
     if ($new) {
         if ($sitewide_likes_enabled) {
             if (false === $likes) {
                 update_post_meta($post_id, 'switch_like_status', 1);
             } else {
                 delete_post_meta($post_id, 'switch_like_status');
             }
         } else {
             if ($likes) {
                 update_post_meta($post_id, 'switch_like_status', 1);
             } else {
                 delete_post_meta($post_id, 'switch_like_status');
             }
         }
     } else {
         if (isset($likes)) {
             if ($sitewide_likes_enabled) {
                 if (false === $likes) {
                     update_post_meta($post_id, 'switch_like_status', 1);
                 } else {
                     delete_post_meta($post_id, 'switch_like_status');
                 }
             } else {
                 if (true === $likes) {
                     update_post_meta($post_id, 'switch_like_status', 1);
                 } else {
                     delete_post_meta($post_id, 'switch_like_status');
                 }
             }
         }
     }
     // Set sharing status of the post
     if ($new) {
         $sharing_enabled = isset($sharing) ? (bool) $sharing : true;
         if (false === $sharing_enabled) {
             update_post_meta($post_id, 'sharing_disabled', 1);
         }
     } else {
         if (isset($sharing) && true === $sharing) {
             delete_post_meta($post_id, 'sharing_disabled');
         } else {
             if (isset($sharing) && false == $sharing) {
                 update_post_meta($post_id, 'sharing_disabled', 1);
             }
         }
     }
     if (isset($sticky)) {
         if (true === $sticky) {
             stick_post($post_id);
         } else {
             unstick_post($post_id);
         }
     }
     // WPCOM Specific (Jetpack's will get bumped elsewhere
     // Tracks how many posts are published and sets meta
     // so we can track some other cool stats (like likes & comments on posts published)
     if (defined('IS_WPCOM') && IS_WPCOM) {
         if ($new && 'publish' == $input['status'] || !$new && isset($last_status) && 'publish' != $last_status && isset($new_status) && 'publish' == $new_status) {
             /** This action is documented in modules/widgets/social-media-icons.php */
             do_action('jetpack_bump_stats_extras', 'api-insights-posts', $this->api->token_details['client_id']);
             update_post_meta($post_id, '_rest_api_published', 1);
             update_post_meta($post_id, '_rest_api_client_id', $this->api->token_details['client_id']);
         }
     }
     // We ask the user/dev to pass Publicize services he/she wants activated for the post, but Publicize expects us
     // to instead flag the ones we don't want to be skipped. proceed with said logic.
     // any posts coming from Path (client ID 25952) should also not publicize
     if ($publicize === false || isset($this->api->token_details['client_id']) && 25952 == $this->api->token_details['client_id']) {
         // No publicize at all, skip all by ID
         foreach ($GLOBALS['publicize_ui']->publicize->get_services('all') as $name => $service) {
             delete_post_meta($post_id, $GLOBALS['publicize_ui']->publicize->POST_SKIP . $name);
             $service_connections = $GLOBALS['publicize_ui']->publicize->get_connections($name);
             if (!$service_connections) {
                 continue;
             }
             foreach ($service_connections as $service_connection) {
                 update_post_meta($post_id, $GLOBALS['publicize_ui']->publicize->POST_SKIP . $service_connection->unique_id, 1);
             }
         }
     } else {
         if (is_array($publicize) && count($publicize) > 0) {
             foreach ($GLOBALS['publicize_ui']->publicize->get_services('all') as $name => $service) {
                 /*
                  * We support both indexed and associative arrays:
                  * * indexed are to pass entire services
                  * * associative are to pass specific connections per service
                  *
                  * We do support mixed arrays: mixed integer and string keys (see 3rd example below).
                  *
                  * EG: array( 'twitter', 'facebook') will only publicize to those, ignoring the other available services
                  * 		Form data: publicize[]=twitter&publicize[]=facebook
                  * EG: array( 'twitter' => '(int) $pub_conn_id_0, (int) $pub_conn_id_3', 'facebook' => (int) $pub_conn_id_7 ) will publicize to two Twitter accounts, and one Facebook connection, of potentially many.
                  * 		Form data: publicize[twitter]=$pub_conn_id_0,$pub_conn_id_3&publicize[facebook]=$pub_conn_id_7
                  * EG: array( 'twitter', 'facebook' => '(int) $pub_conn_id_0, (int) $pub_conn_id_3' ) will publicize to all available Twitter accounts, but only 2 of potentially many Facebook connections
                  * 		Form data: publicize[]=twitter&publicize[facebook]=$pub_conn_id_0,$pub_conn_id_3
                  */
                 // Delete any stale SKIP value for the service by name. We'll add it back by ID.
                 delete_post_meta($post_id, $GLOBALS['publicize_ui']->publicize->POST_SKIP . $name);
                 // Get the user's connections
                 $service_connections = $GLOBALS['publicize_ui']->publicize->get_connections($name);
                 // if the user doesn't have any connections for this service, move on
                 if (!$service_connections) {
                     continue;
                 }
                 if (!in_array($name, $publicize) && !array_key_exists($name, $publicize)) {
                     // Skip the whole service by adding each connection ID
                     foreach ($service_connections as $service_connection) {
                         update_post_meta($post_id, $GLOBALS['publicize_ui']->publicize->POST_SKIP . $service_connection->unique_id, 1);
                     }
                 } else {
                     if (!empty($publicize[$name])) {
                         // Seems we're being asked to only push to [a] specific connection[s].
                         // Explode the list on commas, which will also support a single passed ID
                         $requested_connections = explode(',', preg_replace('/[\\s]*/', '', $publicize[$name]));
                         // Flag the connections we can't match with the requested list to be skipped.
                         foreach ($service_connections as $service_connection) {
                             if (!in_array($service_connection->meta['connection_data']->id, $requested_connections)) {
                                 update_post_meta($post_id, $GLOBALS['publicize_ui']->publicize->POST_SKIP . $service_connection->unique_id, 1);
                             } else {
                                 delete_post_meta($post_id, $GLOBALS['publicize_ui']->publicize->POST_SKIP . $service_connection->unique_id);
                             }
                         }
                     } else {
                         // delete all SKIP values; it's okay to publish to all connected IDs for this service
                         foreach ($service_connections as $service_connection) {
                             delete_post_meta($post_id, $GLOBALS['publicize_ui']->publicize->POST_SKIP . $service_connection->unique_id);
                         }
                     }
                 }
             }
         }
     }
     if (!is_null($publicize_custom_message)) {
         if (empty($publicize_custom_message)) {
             delete_post_meta($post_id, $GLOBALS['publicize_ui']->publicize->POST_MESS);
         } else {
             update_post_meta($post_id, $GLOBALS['publicize_ui']->publicize->POST_MESS, trim($publicize_custom_message));
         }
     }
     if (!empty($insert['post_format'])) {
         if ('default' !== strtolower($insert['post_format'])) {
             set_post_format($post_id, $insert['post_format']);
         } else {
             set_post_format($post_id, get_option('default_post_format'));
         }
     }
     if (isset($featured_image)) {
         $this->parse_and_set_featured_image($post_id, $delete_featured_image, $featured_image);
     }
     if (!empty($metadata)) {
         foreach ((array) $metadata as $meta) {
             $meta = (object) $meta;
             // Custom meta description can only be set on sites that have a business subscription.
             if (Jetpack_SEO_Posts::DESCRIPTION_META_KEY == $meta->key && !Jetpack_SEO_Utils::is_enabled_jetpack_seo()) {
                 return new WP_Error('unauthorized', __('SEO tools are not enabled for this site.', 'jetpack'), 403);
             }
             $existing_meta_item = new stdClass();
             if (empty($meta->operation)) {
                 $meta->operation = 'update';
             }
             if (!empty($meta->value)) {
                 if ('true' == $meta->value) {
                     $meta->value = true;
                 }
                 if ('false' == $meta->value) {
                     $meta->value = false;
                 }
             }
             if (!empty($meta->id)) {
                 $meta->id = absint($meta->id);
                 $existing_meta_item = get_metadata_by_mid('post', $meta->id);
             }
             $unslashed_meta_key = wp_unslash($meta->key);
             // should match what the final key will be
             $meta->key = wp_slash($meta->key);
             $unslashed_existing_meta_key = wp_unslash($existing_meta_item->meta_key);
             $existing_meta_item->meta_key = wp_slash($existing_meta_item->meta_key);
             // make sure that the meta id passed matches the existing meta key
             if (!empty($meta->id) && !empty($meta->key)) {
                 $meta_by_id = get_metadata_by_mid('post', $meta->id);
                 if ($meta_by_id->meta_key !== $meta->key) {
                     continue;
                     // skip this meta
                 }
             }
             switch ($meta->operation) {
                 case 'delete':
                     if (!empty($meta->id) && !empty($existing_meta_item->meta_key) && current_user_can('delete_post_meta', $post_id, $unslashed_existing_meta_key)) {
                         delete_metadata_by_mid('post', $meta->id);
                     } elseif (!empty($meta->key) && !empty($meta->previous_value) && current_user_can('delete_post_meta', $post_id, $unslashed_meta_key)) {
                         delete_post_meta($post_id, $meta->key, $meta->previous_value);
                     } elseif (!empty($meta->key) && current_user_can('delete_post_meta', $post_id, $unslashed_meta_key)) {
                         delete_post_meta($post_id, $meta->key);
                     }
                     break;
                 case 'add':
                     if (!empty($meta->id) || !empty($meta->previous_value)) {
                         continue;
                     } elseif (!empty($meta->key) && !empty($meta->value) && current_user_can('add_post_meta', $post_id, $unslashed_meta_key) || WPCOM_JSON_API_Metadata::is_public($meta->key)) {
                         add_post_meta($post_id, $meta->key, $meta->value);
                     }
                     break;
                 case 'update':
                     if (!isset($meta->value)) {
                         continue;
                     } elseif (!empty($meta->id) && !empty($existing_meta_item->meta_key) && (current_user_can('edit_post_meta', $post_id, $unslashed_existing_meta_key) || WPCOM_JSON_API_Metadata::is_public($meta->key))) {
                         update_metadata_by_mid('post', $meta->id, $meta->value);
                     } elseif (!empty($meta->key) && !empty($meta->previous_value) && (current_user_can('edit_post_meta', $post_id, $unslashed_meta_key) || WPCOM_JSON_API_Metadata::is_public($meta->key))) {
                         update_post_meta($post_id, $meta->key, $meta->value, $meta->previous_value);
                     } elseif (!empty($meta->key) && (current_user_can('edit_post_meta', $post_id, $unslashed_meta_key) || WPCOM_JSON_API_Metadata::is_public($meta->key))) {
                         update_post_meta($post_id, $meta->key, $meta->value);
                     }
                     break;
             }
         }
     }
     /**
      * Fires when a post is created via the REST API.
      *
      * @module json-api
      *
      * @since 2.3.0
      *
      * @param int $post_id Post ID.
      * @param array $insert Data used to build the post.
      * @param string $new New post URL suffix.
      */
     do_action('rest_api_inserted_post', $post_id, $insert, $new);
     $return = $this->get_post_by('ID', $post_id, $args['context']);
     if (!$return || is_wp_error($return)) {
         return $return;
     }
     if (isset($input['type']) && 'revision' === $input['type']) {
         $return['preview_nonce'] = wp_create_nonce('post_preview_' . $input['parent']);
     }
     if (isset($sticky)) {
         // workaround for sticky test occasionally failing, maybe a race condition with stick_post() above
         $return['sticky'] = true === $sticky;
     }
     /** This action is documented in json-endpoints/class.wpcom-json-api-site-settings-endpoint.php */
     do_action('wpcom_json_api_objects', 'posts');
     return $return;
 }
 function get_jetpack_seo_front_page_description()
 {
     return Jetpack_SEO_Utils::get_front_page_meta_description();
 }
 /**
  * Updates site settings for authorized users
  *
  * @return (array)
  */
 public function update_settings()
 {
     // $this->input() retrieves posted arguments whitelisted and casted to the $request_format
     // specs that get passed in when this class is instantiated
     /**
      * Filters the settings to be updated on the site.
      *
      * @module json-api
      *
      * @since 3.6.0
      *
      * @param array $input Associative array of site settings to be updated.
      */
     $input = apply_filters('rest_api_update_site_settings', $this->input());
     $jetpack_relatedposts_options = array();
     $sharing_options = array();
     $updated = array();
     foreach ($input as $key => $value) {
         if (!is_array($value)) {
             $value = trim($value);
         }
         $value = wp_unslash($value);
         switch ($key) {
             case 'default_ping_status':
             case 'default_comment_status':
                 // settings are stored as closed|open
                 $coerce_value = $value ? 'open' : 'closed';
                 if (update_option($key, $coerce_value)) {
                     $updated[$key] = $value;
                 }
                 break;
             case 'jetpack_protect_whitelist':
                 if (function_exists('jetpack_protect_save_whitelist')) {
                     $result = jetpack_protect_save_whitelist($value);
                     if (is_wp_error($result)) {
                         return $result;
                     }
                     $updated[$key] = jetpack_protect_format_whitelist();
                 }
                 break;
             case 'jetpack_sync_non_public_post_stati':
                 Jetpack_Options::update_option('sync_non_public_post_stati', $value);
                 break;
             case 'jetpack_relatedposts_enabled':
             case 'jetpack_relatedposts_show_thumbnails':
             case 'jetpack_relatedposts_show_headline':
                 if (!$this->jetpack_relatedposts_supported()) {
                     break;
                 }
                 if ('jetpack_relatedposts_enabled' === $key && method_exists('Jetpack', 'is_module_active') && $this->jetpack_relatedposts_supported()) {
                     $before_action = Jetpack::is_module_active('related-posts');
                     if ($value) {
                         Jetpack::activate_module('related-posts', false, false);
                     } else {
                         Jetpack::deactivate_module('related-posts');
                     }
                     $after_action = Jetpack::is_module_active('related-posts');
                     if ($after_action == $before_action) {
                         break;
                     }
                 }
                 $just_the_key = substr($key, 21);
                 $jetpack_relatedposts_options[$just_the_key] = $value;
                 break;
             case 'social_notifications_like':
             case 'social_notifications_reblog':
             case 'social_notifications_subscribe':
                 // settings are stored as on|off
                 $coerce_value = $value ? 'on' : 'off';
                 if (update_option($key, $coerce_value)) {
                     $updated[$key] = $value;
                 }
                 break;
             case 'wga':
                 if (!isset($value['code']) || !preg_match('/^$|^UA-[\\d-]+$/i', $value['code'])) {
                     return new WP_Error('invalid_code', 'Invalid UA ID');
                 }
                 $wga = get_option('wga', array());
                 $wga['code'] = $value['code'];
                 // maintain compatibility with wp-google-analytics
                 if (update_option('wga', $wga)) {
                     $updated[$key] = $value;
                 }
                 $enabled_or_disabled = $wga['code'] ? 'enabled' : 'disabled';
                 /** This action is documented in modules/widgets/social-media-icons.php */
                 do_action('jetpack_bump_stats_extras', 'google-analytics', $enabled_or_disabled);
                 $business_plugins = WPCOM_Business_Plugins::instance();
                 $business_plugins->activate_plugin('wp-google-analytics');
                 break;
             case 'jetpack_testimonial':
             case 'jetpack_portfolio':
             case 'jetpack_comment_likes_enabled':
                 // settings are stored as 1|0
                 $coerce_value = (int) $value;
                 if (update_option($key, $coerce_value)) {
                     $updated[$key] = (bool) $value;
                 }
                 break;
             case 'jetpack_testimonial_posts_per_page':
             case 'jetpack_portfolio_posts_per_page':
                 // settings are stored as numeric
                 $coerce_value = (int) $value;
                 if (update_option($key, $coerce_value)) {
                     $updated[$key] = $coerce_value;
                 }
                 break;
                 // Sharing options
             // Sharing options
             case 'sharing_button_style':
             case 'sharing_show':
             case 'sharing_open_links':
                 $sharing_options[preg_replace('/^sharing_/', '', $key)] = $value;
                 break;
             case 'sharing_label':
                 $sharing_options[$key] = $value;
                 break;
                 // Keyring token option
             // Keyring token option
             case 'eventbrite_api_token':
                 // These options can only be updated for sites hosted on WordPress.com
                 if (defined('IS_WPCOM') && IS_WPCOM) {
                     if (empty($value) || WPCOM_JSON_API::is_falsy($value)) {
                         if (delete_option($key)) {
                             $updated[$key] = null;
                         }
                     } else {
                         if (update_option($key, $value)) {
                             $updated[$key] = (int) $value;
                         }
                     }
                 }
                 break;
             case 'holidaysnow':
                 if (empty($value) || WPCOM_JSON_API::is_falsy($value)) {
                     if (function_exists('jetpack_holiday_snow_option_name') && delete_option(jetpack_holiday_snow_option_name())) {
                         $updated[$key] = false;
                     }
                 } else {
                     if (function_exists('jetpack_holiday_snow_option_name') && update_option(jetpack_holiday_snow_option_name(), 'letitsnow')) {
                         $updated[$key] = true;
                     }
                 }
                 break;
             case 'timezone_string':
                 // Map UTC+- timezones to gmt_offsets and set timezone_string to empty
                 // https://github.com/WordPress/WordPress/blob/4.4.2/wp-admin/options.php#L175
                 if (!empty($value) && preg_match('/^UTC[+-]/', $value)) {
                     $gmt_offset = preg_replace('/UTC\\+?/', '', $value);
                     if (update_option('gmt_offset', $gmt_offset)) {
                         $updated['gmt_offset'] = $gmt_offset;
                     }
                     $value = '';
                 }
                 // Always set timezone_string either with the given value or with an
                 // empty string
                 if (update_option($key, $value)) {
                     $updated[$key] = $value;
                 }
                 break;
             case 'site_icon':
                 // settings are stored as deletable numeric (all empty
                 // values as delete intent), validated as media image
                 if (empty($value) || WPCOM_JSON_API::is_falsy($value)) {
                     if (delete_option($key)) {
                         $updated[$key] = null;
                     }
                 } else {
                     if (is_numeric($value)) {
                         $coerce_value = (int) $value;
                         if (wp_attachment_is_image($coerce_value) && update_option($key, $coerce_value)) {
                             $updated[$key] = $coerce_value;
                         }
                     }
                 }
                 break;
             case Jetpack_SEO_Utils::FRONT_PAGE_META_OPTION:
                 if (!Jetpack_SEO_Utils::is_enabled_jetpack_seo() && !Jetpack_SEO_Utils::has_grandfathered_front_page_meta()) {
                     return new WP_Error('unauthorized', __('SEO tools are not enabled for this site.', 'jetpack'), 403);
                 }
                 if (!is_string($value)) {
                     return new WP_Error('invalid_input', __('Invalid SEO meta description value.', 'jetpack'), 400);
                 }
                 $new_description = Jetpack_SEO_Utils::update_front_page_meta_description($value);
                 if (!empty($new_description)) {
                     $updated[$key] = $new_description;
                 }
                 break;
             case Jetpack_SEO_Titles::TITLE_FORMATS_OPTION:
                 if (!Jetpack_SEO_Utils::is_enabled_jetpack_seo()) {
                     return new WP_Error('unauthorized', __('SEO tools are not enabled for this site.', 'jetpack'), 403);
                 }
                 if (!Jetpack_SEO_Titles::are_valid_title_formats($value)) {
                     return new WP_Error('invalid_input', __('Invalid SEO title format.', 'jetpack'), 400);
                 }
                 $new_title_formats = Jetpack_SEO_Titles::update_title_formats($value);
                 if (!empty($new_title_formats)) {
                     $updated[$key] = $new_title_formats;
                 }
                 break;
             case 'verification_services_codes':
                 $verification_codes = jetpack_verification_validate($value);
                 if (update_option('verification_services_codes', $verification_codes)) {
                     $updated[$key] = $verification_codes;
                 }
                 break;
             default:
                 //allow future versions of this endpoint to support additional settings keys
                 if (has_filter('site_settings_endpoint_update_' . $key)) {
                     /**
                      * Filter current site setting value to be updated.
                      *
                      * @module json-api
                      *
                      * @since 3.9.3
                      *
                      * @param mixed $response_item A single site setting value.
                      */
                     $value = apply_filters('site_settings_endpoint_update_' . $key, $value);
                     $updated[$key] = $value;
                     continue;
                 }
                 // no worries, we've already whitelisted and casted arguments above
                 if (update_option($key, $value)) {
                     $updated[$key] = $value;
                 }
         }
     }
     if (count($jetpack_relatedposts_options)) {
         // track new jetpack_relatedposts options against old
         $old_relatedposts_options = Jetpack_Options::get_option('relatedposts');
         if (Jetpack_Options::update_option('relatedposts', $jetpack_relatedposts_options)) {
             foreach ($jetpack_relatedposts_options as $key => $value) {
                 if ($value !== $old_relatedposts_options[$key]) {
                     $updated['jetpack_relatedposts_' . $key] = $value;
                 }
             }
         }
     }
     if (!empty($sharing_options) && class_exists('Sharing_Service')) {
         $ss = new Sharing_Service();
         // Merge current values with updated, since Sharing_Service expects
         // all values to be included when updating
         $current_sharing_options = $ss->get_global_options();
         foreach ($current_sharing_options as $key => $val) {
             if (!isset($sharing_options[$key])) {
                 $sharing_options[$key] = $val;
             }
         }
         $updated_social_options = $ss->set_global_options($sharing_options);
         if (isset($input['sharing_button_style'])) {
             $updated['sharing_button_style'] = (string) $updated_social_options['button_style'];
         }
         if (isset($input['sharing_label'])) {
             // Sharing_Service won't report label as updated if set to default
             $updated['sharing_label'] = (string) $sharing_options['sharing_label'];
         }
         if (isset($input['sharing_show'])) {
             $updated['sharing_show'] = (array) $updated_social_options['show'];
         }
         if (isset($input['sharing_open_links'])) {
             $updated['sharing_open_links'] = (string) $updated_social_options['open_links'];
         }
     }
     return array('updated' => $updated);
 }
 /**
  * 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();
     $fields = null;
     if ('display' === $context && !empty($this->api->query['fields'])) {
         $fields = array_fill_keys(array_map('trim', explode(',', $this->api->query['fields'])), true);
     }
     foreach (array_keys($this->post_object_format) as $key) {
         if ($fields !== null && !isset($fields[$key])) {
             continue;
         }
         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->links->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 'comments_open':
                 $response[$key] = (bool) comments_open($post->ID);
                 break;
             case 'pings_open':
                 $response[$key] = (bool) pings_open($post->ID);
                 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 'comment_count':
                 $response[$key] = (int) $post->comment_count;
                 break;
             case 'like_count':
                 $response[$key] = (int) $this->api->post_like_count($blog_id, $post->ID);
                 break;
             case 'i_like':
                 $response[$key] = (bool) $this->api->is_liked($blog_id, $post->ID);
                 break;
             case 'is_reblogged':
                 $response[$key] = (bool) $this->api->is_reblogged($blog_id, $post->ID);
                 break;
             case 'is_following':
                 $response[$key] = (bool) $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 '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 = get_posts(array('post_parent' => $post->ID, 'post_status' => 'inherit', 'post_type' => 'attachment', 'posts_per_page' => 100));
                 foreach ($_attachments as $attachment) {
                     $response[$key][$attachment->ID] = $this->get_attachment($attachment);
                 }
                 $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 (WPCOM_JSON_API_Metadata::is_public($meta['meta_key'])) {
                         $show = true;
                     }
                     if (current_user_can('edit_post_meta', $post_id, $meta['meta_key'])) {
                         $show = true;
                     }
                     // Only business plan subscribers can view custom meta description.
                     if (Jetpack_SEO_Posts::DESCRIPTION_META_KEY == $meta->key && !Jetpack_SEO_Utils::is_enabled_jetpack_seo()) {
                         $show = false;
                     }
                     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->links->get_post_link($this->api->get_blog_id_for_output(), $post->ID), 'help' => (string) $this->links->get_post_link($this->api->get_blog_id_for_output(), $post->ID, 'help'), 'site' => (string) $this->links->get_site_link($this->api->get_blog_id_for_output()), 'replies' => (string) $this->links->get_post_link($this->api->get_blog_id_for_output(), $post->ID, 'replies/'), 'likes' => (string) $this->links->get_post_link($this->api->get_blog_id_for_output(), $post->ID, 'likes/')));
                 break;
             case 'current_user_can':
                 $response[$key] = $capabilities;
                 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;
 }
 public function get_metadata()
 {
     $metadata = array();
     foreach ((array) has_meta($this->post->ID) as $meta) {
         // Don't expose protected fields.
         $meta_key = $meta['meta_key'];
         $show = !WPCOM_JSON_API_Metadata::is_internal_only($meta_key) && (WPCOM_JSON_API_Metadata::is_public($meta_key) || current_user_can('edit_post_meta', $this->post->ID, $meta_key));
         // Only business plan subscribers can view custom meta description
         if (Jetpack_SEO_Posts::DESCRIPTION_META_KEY == $meta_key && !Jetpack_SEO_Utils::is_enabled_jetpack_seo()) {
             $show = false;
         }
         if ($show) {
             $metadata[] = array('id' => $meta['meta_id'], 'key' => $meta['meta_key'], 'value' => maybe_unserialize($meta['meta_value']));
         }
     }
     if (!empty($metadata)) {
         return $metadata;
     } else {
         return false;
     }
 }