| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631 |
- <?php
- require_once dirname( __FILE__ ) . '/class.json-api-date.php';
- require_once dirname( __FILE__ ) . '/class.json-api-post-base.php';
- /**
- * Base class for the Site Abstraction Layer (SAL)
- * Note that this is the site "as seen by user $user_id with token $token", which
- * is why we pass the token to the platform; these site instances are value objects
- * to be used in the context of a single request for a single user.
- * Also note that at present this class _assumes_ you've "switched to"
- * the site in question, and functions like `get_bloginfo( 'name' )` will
- * therefore return the correct value
- **/
- abstract class SAL_Site {
- public $blog_id;
- public $platform;
- public function __construct( $blog_id, $platform ) {
- $this->blog_id = $blog_id;
- $this->platform = $platform;
- }
- public function get_id() {
- return $this->blog_id;
- }
- public function get_name() {
- return (string) htmlspecialchars_decode( get_bloginfo( 'name' ), ENT_QUOTES );
- }
- public function get_description() {
- return (string) htmlspecialchars_decode( get_bloginfo( 'description' ), ENT_QUOTES );
- }
- public function get_url() {
- return (string) home_url();
- }
- public function get_post_count() {
- return (int) wp_count_posts( 'post' )->publish;
- }
- public function get_quota() {
- return null;
- }
- abstract public function has_videopress();
- abstract public function upgraded_filetypes_enabled();
- abstract public function is_mapped_domain();
- abstract public function is_redirect();
- abstract public function is_headstart_fresh();
- abstract public function featured_images_enabled();
- abstract public function has_wordads();
- abstract public function get_frame_nonce();
- abstract public function allowed_file_types();
- abstract public function get_post_formats();
- abstract public function is_private();
- abstract public function is_following();
- abstract public function get_subscribers_count();
- abstract public function get_locale();
- abstract public function is_jetpack();
- abstract public function get_jetpack_modules();
- abstract public function is_vip();
- abstract public function is_multisite();
- abstract public function is_single_user_site();
- abstract public function get_plan();
- abstract public function get_ak_vp_bundle_enabled();
- abstract public function get_podcasting_archive();
- abstract public function get_jetpack_seo_front_page_description();
- abstract public function get_jetpack_seo_title_formats();
- abstract public function get_verification_services_codes();
- abstract public function before_render();
- abstract public function after_render( &$response );
- // TODO - factor this out? Seems an odd thing to have on a site
- abstract public function after_render_options( &$options );
- // wrap a WP_Post object with SAL methods
- abstract public function wrap_post( $post, $context );
- abstract protected function is_a8c_publication( $post_id );
- public function is_automated_transfer() {
- /**
- * Filter if a site is an automated-transfer site.
- *
- * @module json-api
- *
- * @since 6.4.0
- *
- * @param bool is_automated_transfer( $this->blog_id )
- * @param int $blog_id Blog identifier.
- */
- return apply_filters(
- 'jetpack_site_automated_transfer',
- false,
- $this->blog_id
- );
- }
- public function is_wpcom_store() {
- return false;
- }
- public function woocommerce_is_active() {
- return false;
- }
- public function get_post_by_id( $post_id, $context ) {
- // Remove the skyword tracking shortcode for posts returned via the API.
- remove_shortcode( 'skyword-tracking' );
- add_shortcode( 'skyword-tracking', '__return_empty_string' );
- $post = get_post( $post_id, OBJECT, $context );
- if ( ! $post ) {
- return new WP_Error( 'unknown_post', 'Unknown post', 404 );
- }
- $wrapped_post = $this->wrap_post( $post, $context );
- // validate access
- return $this->validate_access( $wrapped_post );
- }
- /**
- * 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 )
- && ! $this->is_a8c_publication( $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;
- }
- public function current_user_can_access_post_type( $post_type, $context ) {
- $post_type_object = $this->get_post_type_object( $post_type );
- if ( ! $post_type_object ) {
- return false;
- }
- switch( $context ) {
- case 'edit':
- return current_user_can( $post_type_object->cap->edit_posts );
- case 'display':
- return $post_type_object->public || current_user_can( $post_type_object->cap->read_private_posts );
- default:
- return false;
- }
- }
- protected function get_post_type_object( $post_type ) {
- return get_post_type_object( $post_type );
- }
- // copied from class.json-api-endpoints.php
- public function is_post_type_allowed( $post_type ) {
- // if the post type is empty, that's fine, WordPress will default to post
- if ( empty( $post_type ) ) {
- return true;
- }
- // allow special 'any' type
- if ( 'any' == $post_type ) {
- return true;
- }
- // check for allowed types
- if ( in_array( $post_type, $this->get_whitelisted_post_types() ) ) {
- return true;
- }
- if ( $post_type_object = get_post_type_object( $post_type ) ) {
- if ( ! empty( $post_type_object->show_in_rest ) ) {
- return $post_type_object->show_in_rest;
- }
- if ( ! empty( $post_type_object->publicly_queryable ) ) {
- return $post_type_object->publicly_queryable;
- }
- }
- return ! empty( $post_type_object->public );
- }
- // copied from class.json-api-endpoints.php
- /**
- * Gets the whitelisted post types that JP should allow access to.
- *
- * @return array Whitelisted post types.
- */
- public function get_whitelisted_post_types() {
- $allowed_types = array( 'post', 'page', 'revision' );
- /**
- * Filter the post types Jetpack has access to, and can synchronize with WordPress.com.
- *
- * @module json-api
- *
- * @since 2.2.3
- *
- * @param array $allowed_types Array of whitelisted post types. Default to `array( 'post', 'page', 'revision' )`.
- */
- $allowed_types = apply_filters( 'rest_api_allowed_post_types', $allowed_types );
- return array_unique( $allowed_types );
- }
- // copied and modified a little from class.json-api-endpoints.php
- private function user_can_view_post( $post ) {
- if ( !$post || is_wp_error( $post ) ) {
- return false;
- }
- if ( 'inherit' === $post->post_status ) {
- $parent_post = get_post( $post->post_parent );
- $post_status_obj = get_post_status_object( $parent_post->post_status );
- } else {
- $post_status_obj = get_post_status_object( $post->post_status );
- }
- $authorized = (
- $post_status_obj->public ||
- ( is_user_logged_in() &&
- (
- ( $post_status_obj->protected && current_user_can( 'edit_post', $post->ID ) ) ||
- ( $post_status_obj->private && current_user_can( 'read_post', $post->ID ) ) ||
- ( 'trash' === $post->post_status && current_user_can( 'edit_post', $post->ID ) ) ||
- 'auto-draft' === $post->post_status
- )
- )
- );
- if ( ! $authorized ) {
- return new WP_Error( 'unauthorized', 'User cannot view post', 403 );
- }
- if (
- -1 == get_option( 'blog_public' ) &&
- /**
- * Filter access to a specific post.
- *
- * @module json-api
- *
- * @since 3.4.0
- *
- * @param bool current_user_can( 'read_post', $post->ID ) Can the current user access the post.
- * @param WP_Post $post Post data.
- */
- ! apply_filters(
- 'wpcom_json_api_user_can_view_post',
- current_user_can( 'read_post', $post->ID ),
- $post
- )
- ) {
- return new WP_Error( 'unauthorized', 'User cannot view post', array( 'status_code' => 403, 'error' => 'private_blog' ) );
- }
- if ( strlen( $post->post_password ) && !current_user_can( 'edit_post', $post->ID ) ) {
- return new WP_Error( 'unauthorized', 'User cannot view password protected post', array( 'status_code' => 403, 'error' => 'password_protected' ) );
- }
- return true;
- }
- /**
- * Get post ID by name
- *
- * Attempts to match name on post title and page path
- *
- * @param string $name
- *
- * @return int|object Post ID on success, WP_Error object on failure
- */
- public function get_post_id_by_name( $name ) {
- $name = sanitize_title( $name );
- if ( ! $name ) {
- return new WP_Error( 'invalid_post', 'Invalid post', 400 );
- }
- $posts = get_posts( array(
- 'name' => $name,
- 'numberposts' => 1,
- 'post_type' => $this->get_whitelisted_post_types(),
- ) );
- if ( ! $posts || ! isset( $posts[0]->ID ) || ! $posts[0]->ID ) {
- $page = get_page_by_path( $name );
- if ( ! $page ) {
- return new WP_Error( 'unknown_post', 'Unknown post', 404 );
- }
- return $page->ID;
- }
- return (int) $posts[0]->ID;
- }
- /**
- * Get post by name
- *
- * Attempts to match name on post title and page path
- *
- * @param string $name
- * @param string $context (display or edit)
- *
- * @return object Post object on success, WP_Error object on failure
- **/
- public function get_post_by_name( $name, $context ) {
- $post_id = $this->get_post_id_by_name( $name );
- if ( is_wp_error( $post_id ) ) {
- return $post_id;
- }
- return $this->get_post_by_id( $post_id, $context );
- }
- function user_can_manage() {
- current_user_can( 'manage_options' );
- }
- function get_xmlrpc_url() {
- $xmlrpc_scheme = apply_filters( 'wpcom_json_api_xmlrpc_scheme', parse_url( get_option( 'home' ), PHP_URL_SCHEME ) );
- return site_url( 'xmlrpc.php', $xmlrpc_scheme );
- }
- function get_registered_date() {
- if ( function_exists( 'get_blog_details' ) ) {
- $blog_details = get_blog_details();
- if ( ! empty( $blog_details->registered ) ) {
- return WPCOM_JSON_API_Date::format_date( $blog_details->registered );
- }
- }
- return '0000-00-00T00:00:00+00:00';
- }
- function get_capabilities() {
- return array(
- 'edit_pages' => current_user_can( 'edit_pages' ),
- 'edit_posts' => current_user_can( 'edit_posts' ),
- 'edit_others_posts' => current_user_can( 'edit_others_posts' ),
- 'edit_others_pages' => current_user_can( 'edit_others_pages' ),
- 'delete_posts' => current_user_can( 'delete_posts' ),
- 'delete_others_posts' => current_user_can( 'delete_others_posts' ),
- 'edit_theme_options' => current_user_can( 'edit_theme_options' ),
- 'edit_users' => current_user_can( 'edit_users' ),
- 'list_users' => current_user_can( 'list_users' ),
- 'manage_categories' => current_user_can( 'manage_categories' ),
- 'manage_options' => current_user_can( 'manage_options' ),
- 'moderate_comments' => current_user_can( 'moderate_comments' ),
- 'activate_wordads' => wpcom_get_blog_owner() === (int) get_current_user_id(),
- 'promote_users' => current_user_can( 'promote_users' ),
- 'publish_posts' => current_user_can( 'publish_posts' ),
- 'upload_files' => current_user_can( 'upload_files' ),
- 'delete_users' => current_user_can( 'delete_users' ),
- 'remove_users' => current_user_can( 'remove_users' ),
- 'view_stats' => stats_is_blog_user( $this->blog_id )
- );
- }
- function is_visible() {
- if ( is_user_logged_in() ) {
- $current_user = wp_get_current_user();
- $visible = (array) get_user_meta( $current_user->ID, 'blog_visibility', true );
- $is_visible = true;
- if ( isset( $visible[ $this->blog_id ] ) ) {
- $is_visible = (bool) $visible[ $this->blog_id ];
- }
- // null and true are visible
- return $is_visible;
- }
- return null;
- }
- function get_logo() {
- // Set an empty response array.
- $logo_setting = array(
- 'id' => (int) 0,
- 'sizes' => array(),
- 'url' => '',
- );
- // Get current site logo values.
- $logo = get_option( 'site_logo' );
- // Update the response array if there's a site logo currenty active.
- if ( $logo && 0 != $logo['id'] ) {
- $logo_setting['id'] = $logo['id'];
- $logo_setting['url'] = $logo['url'];
- foreach ( $logo['sizes'] as $size => $properties ) {
- $logo_setting['sizes'][ $size ] = $properties;
- }
- }
- return $logo_setting;
- }
- function get_timezone() {
- return (string) get_option( 'timezone_string' );
- }
- function get_gmt_offset() {
- return (float) get_option( 'gmt_offset' );
- }
- function get_login_url() {
- return wp_login_url();
- }
- function get_admin_url() {
- return get_admin_url();
- }
- function get_unmapped_url() {
- return get_site_url( get_current_blog_id() );
- }
- function get_theme_slug() {
- return get_option( 'stylesheet' );
- }
- function get_header_image() {
- return get_theme_mod( 'header_image_data' );
- }
- function get_background_color() {
- return get_theme_mod( 'background_color' );
- }
- function get_image_default_link_type() {
- return get_option( 'image_default_link_type' );
- }
- function get_image_thumbnail_width() {
- return (int) get_option( 'thumbnail_size_w' );
- }
- function get_image_thumbnail_height() {
- return (int) get_option( 'thumbnail_size_h' );
- }
- function get_image_thumbnail_crop() {
- return get_option( 'thumbnail_crop' );
- }
- function get_image_medium_width() {
- return (int) get_option( 'medium_size_w' );
- }
- function get_image_medium_height() {
- return (int) get_option( 'medium_size_h' );
- }
- function get_image_large_width() {
- return (int) get_option( 'large_size_w' );
- }
- function get_image_large_height() {
- return (int) get_option( 'large_size_h' );
- }
- function get_permalink_structure() {
- return get_option( 'permalink_structure' );
- }
- function get_default_post_format() {
- return get_option( 'default_post_format' );
- }
- function get_default_category() {
- return (int) get_option( 'default_category' );
- }
- function get_show_on_front() {
- return get_option( 'show_on_front' );
- }
- function is_custom_front_page() {
- return ( 'page' === $this->get_show_on_front() );
- }
- function get_default_likes_enabled() {
- return (bool) apply_filters( 'wpl_is_enabled_sitewide', ! get_option( 'disabled_likes' ) );
- }
- function get_default_sharing_status() {
- $default_sharing_status = false;
- if ( class_exists( 'Sharing_Service' ) ) {
- $ss = new Sharing_Service();
- $blog_services = $ss->get_blog_services();
- $default_sharing_status = ! empty( $blog_services['visible'] );
- }
- return (bool) $default_sharing_status;
- }
- function get_default_comment_status() {
- return 'closed' !== get_option( 'default_comment_status' );
- }
- function default_ping_status() {
- return 'closed' !== get_option( 'default_ping_status' );
- }
- function is_publicize_permanently_disabled() {
- $publicize_permanently_disabled = false;
- if ( function_exists( 'is_publicize_permanently_disabled' ) ) {
- $publicize_permanently_disabled = is_publicize_permanently_disabled( $this->blog_id );
- }
- return $publicize_permanently_disabled;
- }
- function get_page_on_front() {
- return (int) get_option( 'page_on_front' );
- }
- function get_page_for_posts() {
- return (int) get_option( 'page_for_posts' );
- }
- function is_headstart() {
- return get_option( 'headstart' );
- }
- function get_wordpress_version() {
- global $wp_version;
- return $wp_version;
- }
- function is_domain_only() {
- $options = get_option( 'options' );
- return ! empty ( $options['is_domain_only'] ) ? (bool) $options['is_domain_only'] : false;
- }
- function get_blog_public() {
- return (int) get_option( 'blog_public' );
- }
- function has_pending_automated_transfer() {
- /**
- * Filter if a site is in pending automated transfer state.
- *
- * @module json-api
- *
- * @since 6.4.0
- *
- * @param bool has_site_pending_automated_transfer( $this->blog_id )
- * @param int $blog_id Blog identifier.
- */
- return apply_filters(
- 'jetpack_site_pending_automated_transfer',
- false,
- $this->blog_id
- );
- }
- function signup_is_store() {
- return $this->get_design_type() === 'store';
- }
- function get_roles() {
- return new WP_Roles();
- }
- function get_design_type() {
- $options = get_option( 'options' );
- return empty( $options[ 'designType'] ) ? null : $options[ 'designType' ];
- }
- function get_site_goals() {
- $options = get_option( 'options' );
- return empty( $options[ 'siteGoals'] ) ? null : $options[ 'siteGoals' ];
- }
- }
|