SAL_Site

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.

Defined (1)

The class is defined in the following location(s).

/sal/class.json-api-site-base.php  
  1. abstract class SAL_Site { 
  2. public $blog_id; 
  3. public $platform; 
  4.  
  5. public function __construct( $blog_id, $platform ) { 
  6. $this->blog_id = $blog_id; 
  7. $this->platform = $platform; 
  8.  
  9. public function get_id() { 
  10. return $this->blog_id; 
  11.  
  12. public function get_name() { 
  13. return (string) htmlspecialchars_decode( get_bloginfo( 'name' ), ENT_QUOTES ); 
  14.  
  15. public function get_description() { 
  16. return (string) htmlspecialchars_decode( get_bloginfo( 'description' ), ENT_QUOTES ); 
  17.  
  18. public function get_url() { 
  19. return (string) home_url(); 
  20.  
  21. public function get_post_count() { 
  22. return (int) wp_count_posts( 'post' )->publish; 
  23.  
  24. abstract public function has_videopress(); 
  25.  
  26. abstract public function upgraded_filetypes_enabled(); 
  27.  
  28. abstract public function is_mapped_domain(); 
  29.  
  30. abstract public function is_redirect(); 
  31.  
  32. abstract public function featured_images_enabled(); 
  33.  
  34. abstract public function has_wordads(); 
  35.  
  36. abstract public function get_frame_nonce(); 
  37.  
  38. abstract public function allowed_file_types(); 
  39.  
  40. abstract public function get_post_formats(); 
  41.  
  42. abstract public function is_private(); 
  43.  
  44. abstract public function is_following(); 
  45.  
  46. abstract public function get_subscribers_count(); 
  47.  
  48. abstract public function get_locale(); 
  49.  
  50. abstract public function is_jetpack(); 
  51.  
  52. abstract public function get_jetpack_modules(); 
  53.  
  54. abstract public function is_vip(); 
  55.  
  56. abstract public function is_multisite(); 
  57.  
  58. abstract public function is_single_user_site(); 
  59.  
  60. abstract public function get_plan(); 
  61.  
  62. abstract public function get_ak_vp_bundle_enabled(); 
  63.  
  64. abstract public function get_jetpack_seo_front_page_description(); 
  65.  
  66. abstract public function get_jetpack_seo_title_formats(); 
  67.  
  68. abstract public function get_verification_services_codes(); 
  69.  
  70. abstract public function before_render(); 
  71.  
  72. abstract public function after_render( &$response ); 
  73.  
  74. // TODO - factor this out? Seems an odd thing to have on a site 
  75. abstract public function after_render_options( &$options ); 
  76.  
  77. // wrap a WP_Post object with SAL methods 
  78. abstract public function wrap_post( $post, $context ); 
  79.  
  80.  
  81. public function get_post_by_id( $post_id, $context ) { 
  82. $post = get_post( $post_id, OBJECT, $context ); 
  83.  
  84. if ( ! $post ) { 
  85. return new WP_Error( 'unknown_post', 'Unknown post', 404 ); 
  86.  
  87. $wrapped_post = $this->wrap_post( $post, $context ); 
  88.  
  89. // validate access 
  90. return $this->validate_access( $wrapped_post ); 
  91.  
  92. /** 
  93. * Validate current user can access the post 
  94. *  
  95. * @return WP_Error or post 
  96. */ 
  97. private function validate_access( $post ) { 
  98. $context = $post->context; 
  99.  
  100. if ( ! $this->is_post_type_allowed( $post->post_type )  
  101. &&  
  102. ( ! function_exists( 'is_post_freshly_pressed' ) || ! is_post_freshly_pressed( $post->ID ) ) ) { 
  103. return new WP_Error( 'unknown_post', 'Unknown post', 404 ); 
  104.  
  105. switch ( $context ) { 
  106. case 'edit' : 
  107. if ( ! current_user_can( 'edit_post', $post ) ) { 
  108. return new WP_Error( 'unauthorized', 'User cannot edit post', 403 ); 
  109. break; 
  110. case 'display' : 
  111. $can_view = $this->user_can_view_post( $post ); 
  112. if ( is_wp_error( $can_view ) ) { 
  113. return $can_view; 
  114. break; 
  115. default : 
  116. return new WP_Error( 'invalid_context', 'Invalid API CONTEXT', 400 ); 
  117.  
  118. return $post; 
  119.  
  120. // copied from class.json-api-endpoints.php 
  121. private function is_post_type_allowed( $post_type ) { 
  122. // if the post type is empty, that's fine, WordPress will default to post 
  123. if ( empty( $post_type ) ) 
  124. return true; 
  125.  
  126. // allow special 'any' type 
  127. if ( 'any' == $post_type ) 
  128. return true; 
  129.  
  130. // check for allowed types 
  131. if ( in_array( $post_type, $this->_get_whitelisted_post_types() ) ) 
  132. return true; 
  133.  
  134. return false; 
  135.  
  136. // copied from class.json-api-endpoints.php 
  137. /** 
  138. * Gets the whitelisted post types that JP should allow access to. 
  139. * @return array Whitelisted post types. 
  140. */ 
  141. private function _get_whitelisted_post_types() { 
  142. $allowed_types = array( 'post', 'page', 'revision' ); 
  143.  
  144. /** 
  145. * Filter the post types Jetpack has access to, and can synchronize with WordPress.com. 
  146. * @module json-api 
  147. * @since 2.2.3 
  148. * @param array $allowed_types Array of whitelisted post types. Default to `array( 'post', 'page', 'revision' )`. 
  149. */ 
  150. $allowed_types = apply_filters( 'rest_api_allowed_post_types', $allowed_types ); 
  151.  
  152. return array_unique( $allowed_types ); 
  153.  
  154. // copied and modified a little from class.json-api-endpoints.php 
  155. private function user_can_view_post( $post ) { 
  156. if ( !$post || is_wp_error( $post ) ) { 
  157. return false; 
  158.  
  159. if ( 'inherit' === $post->post_status ) { 
  160. $parent_post = get_post( $post->post_parent ); 
  161. $post_status_obj = get_post_status_object( $parent_post->post_status ); 
  162. } else { 
  163. $post_status_obj = get_post_status_object( $post->post_status ); 
  164.  
  165. $authorized = ( 
  166. $post_status_obj->public || 
  167. ( is_user_logged_in() &&  
  168. ( $post_status_obj->protected && current_user_can( 'edit_post', $post->ID ) ) || 
  169. ( $post_status_obj->private && current_user_can( 'read_post', $post->ID ) ) || 
  170. ( 'trash' === $post->post_status && current_user_can( 'edit_post', $post->ID ) ) || 
  171. 'auto-draft' === $post->post_status 
  172. )  
  173. )  
  174. ); 
  175.  
  176. if ( ! $authorized ) { 
  177. return new WP_Error( 'unauthorized', 'User cannot view post', 403 ); 
  178.  
  179. if ( 
  180. -1 == get_option( 'blog_public' ) && 
  181. /** 
  182. * Filter access to a specific post. 
  183. * @module json-api 
  184. * @since 3.4.0 
  185. * @param bool current_user_can( 'read_post', $post->ID ) Can the current user access the post. 
  186. * @param WP_Post $post Post data. 
  187. */ 
  188. ! apply_filters( 
  189. 'wpcom_json_api_user_can_view_post',  
  190. current_user_can( 'read_post', $post->ID ),  
  191. $post 
  192. ) { 
  193. return new WP_Error( 'unauthorized', 'User cannot view post', array( 'status_code' => 403, 'error' => 'private_blog' ) ); 
  194.  
  195. if ( strlen( $post->post_password ) && !current_user_can( 'edit_post', $post->ID ) ) { 
  196. return new WP_Error( 'unauthorized', 'User cannot view password protected post', array( 'status_code' => 403, 'error' => 'password_protected' ) ); 
  197.  
  198. return true; 
  199.  
  200. /** 
  201. * Get post ID by name 
  202. * Attempts to match name on post title and page path 
  203. * @param string $name 
  204. * @return int|object Post ID on success, WP_Error object on failure 
  205. */ 
  206. public function get_post_id_by_name( $name ) { 
  207. $name = sanitize_title( $name ); 
  208.  
  209. if ( ! $name ) { 
  210. return new WP_Error( 'invalid_post', 'Invalid post', 400 ); 
  211.  
  212. $posts = get_posts( array( 
  213. 'name' => $name,  
  214. 'numberposts' => 1,  
  215. 'post_type' => $this->_get_whitelisted_post_types(),  
  216. ) ); 
  217.  
  218. if ( ! $posts || ! isset( $posts[0]->ID ) || ! $posts[0]->ID ) { 
  219. $page = get_page_by_path( $name ); 
  220.  
  221. if ( ! $page ) { 
  222. return new WP_Error( 'unknown_post', 'Unknown post', 404 ); 
  223.  
  224. return $page->ID; 
  225.  
  226. return (int) $posts[0]->ID; 
  227.  
  228. /** 
  229. * Get post by name 
  230. * Attempts to match name on post title and page path 
  231. * @param string $name 
  232. * @param string $context (display or edit) 
  233. * @return object Post object on success, WP_Error object on failure 
  234. **/ 
  235. public function get_post_by_name( $name, $context ) { 
  236. $post_id = $this->get_post_id_by_name( $name ); 
  237. if ( is_wp_error( $post_id ) ) { 
  238. return $post_id; 
  239.  
  240. return $this->get_post_by_id( $post_id, $context ); 
  241.  
  242. function user_can_manage() { 
  243. current_user_can( 'manage_options' ); 
  244.  
  245. function get_xmlrpc_url() { 
  246. $xmlrpc_scheme = apply_filters( 'wpcom_json_api_xmlrpc_scheme', parse_url( get_option( 'home' ), PHP_URL_SCHEME ) ); 
  247. return site_url( 'xmlrpc.php', $xmlrpc_scheme ); 
  248.  
  249. function get_registered_date() { 
  250. if ( function_exists( 'get_blog_details' ) ) { 
  251. $blog_details = get_blog_details(); 
  252. if ( ! empty( $blog_details->registered ) ) { 
  253. return WPCOM_JSON_API_Date::format_date( $blog_details->registered ); 
  254.  
  255. return '0000-00-00T00:00:00+00:00'; 
  256.  
  257. function get_capabilities() { 
  258. return array( 
  259. 'edit_pages' => current_user_can( 'edit_pages' ),  
  260. 'edit_posts' => current_user_can( 'edit_posts' ),  
  261. 'edit_others_posts' => current_user_can( 'edit_others_posts' ),  
  262. 'edit_others_pages' => current_user_can( 'edit_others_pages' ),  
  263. 'delete_posts' => current_user_can( 'delete_posts' ),  
  264. 'delete_others_posts' => current_user_can( 'delete_others_posts' ),  
  265. 'edit_theme_options' => current_user_can( 'edit_theme_options' ),  
  266. 'edit_users' => current_user_can( 'edit_users' ),  
  267. 'list_users' => current_user_can( 'list_users' ),  
  268. 'manage_categories' => current_user_can( 'manage_categories' ),  
  269. 'manage_options' => current_user_can( 'manage_options' ),  
  270. 'promote_users' => current_user_can( 'promote_users' ),  
  271. 'publish_posts' => current_user_can( 'publish_posts' ),  
  272. 'upload_files' => current_user_can( 'upload_files' ),  
  273. 'view_stats' => stats_is_blog_user( $this->blog_id ) 
  274. ); 
  275.  
  276. function is_visible() { 
  277. if ( is_user_logged_in() ) { 
  278. $current_user = wp_get_current_user(); 
  279. $visible = (array) get_user_meta( $current_user->ID, 'blog_visibility', true ); 
  280.  
  281. $is_visible = true; 
  282. if ( isset( $visible[ $this->blog_id ] ) ) { 
  283. $is_visible = (bool) $visible[ $this->blog_id ]; 
  284.  
  285. // null and true are visible 
  286. return $is_visible; 
  287.  
  288. return null; 
  289.  
  290. function get_logo() { 
  291.  
  292. // Set an empty response array. 
  293. $logo_setting = array( 
  294. 'id' => (int) 0,  
  295. 'sizes' => array(),  
  296. 'url' => '',  
  297. ); 
  298.  
  299. // Get current site logo values. 
  300. $logo = get_option( 'site_logo' ); 
  301.  
  302. // Update the response array if there's a site logo currenty active. 
  303. if ( $logo && 0 != $logo['id'] ) { 
  304. $logo_setting['id'] = $logo['id']; 
  305. $logo_setting['url'] = $logo['url']; 
  306.  
  307. foreach ( $logo['sizes'] as $size => $properties ) { 
  308. $logo_setting['sizes'][ $size ] = $properties; 
  309.  
  310. return $logo_setting; 
  311.  
  312. function get_timezone() { 
  313. return (string) get_option( 'timezone_string' ); 
  314.  
  315. function get_gmt_offset() { 
  316. return (float) get_option( 'gmt_offset' ); 
  317.  
  318. function get_login_url() { 
  319. return wp_login_url(); 
  320.  
  321. function get_admin_url() { 
  322. return get_admin_url(); 
  323.  
  324. function get_unmapped_url() { 
  325. return get_site_url( get_current_blog_id() ); 
  326.  
  327. function get_theme_slug() { 
  328. return get_option( 'stylesheet' ); 
  329.  
  330. function get_header_image() { 
  331. return get_theme_mod( 'header_image_data' ); 
  332.  
  333. function get_background_color() { 
  334. return get_theme_mod( 'background_color' ); 
  335.  
  336. function get_image_default_link_type() { 
  337. return get_option( 'image_default_link_type' ); 
  338.  
  339. function get_image_thumbnail_width() { 
  340. return (int) get_option( 'thumbnail_size_w' );  
  341.  
  342. function get_image_thumbnail_height() { 
  343. return (int) get_option( 'thumbnail_size_h' ); 
  344. }  
  345.  
  346. function get_image_thumbnail_crop() { 
  347. return get_option( 'thumbnail_crop' ); 
  348.  
  349. function get_image_medium_width() { 
  350. return (int) get_option( 'medium_size_w' ); 
  351.  
  352. function get_image_medium_height() { 
  353. return (int) get_option( 'medium_size_h' );  
  354.  
  355. function get_image_large_width() { 
  356. return (int) get_option( 'large_size_w' ); 
  357.  
  358. function get_image_large_height() { 
  359. return (int) get_option( 'large_size_h' ); 
  360.  
  361. function get_permalink_structure() { 
  362. return get_option( 'permalink_structure' ); 
  363.  
  364. function get_default_post_format() { 
  365. return get_option( 'default_post_format' );  
  366.  
  367. function get_default_category() { 
  368. return (int) get_option( 'default_category' ); 
  369.  
  370. function get_show_on_front() { 
  371. return get_option( 'show_on_front' ); 
  372.  
  373. function is_custom_front_page() { 
  374. return ( 'page' === $this->get_show_on_front() ); 
  375.  
  376. function get_default_likes_enabled() { 
  377. return (bool) apply_filters( 'wpl_is_enabled_sitewide', ! get_option( 'disabled_likes' ) ); 
  378.  
  379. function get_default_sharing_status() { 
  380. $default_sharing_status = false; 
  381. if ( class_exists( 'Sharing_Service' ) ) { 
  382. $ss = new Sharing_Service(); 
  383. $blog_services = $ss->get_blog_services(); 
  384. $default_sharing_status = ! empty( $blog_services['visible'] ); 
  385. return (bool) $default_sharing_status; 
  386.  
  387. function get_default_comment_status() { 
  388. return 'closed' !== get_option( 'default_comment_status' ); 
  389.  
  390. function default_ping_status() { 
  391. return 'closed' !== get_option( 'default_ping_status' );  
  392.  
  393. function is_publicize_permanently_disabled() { 
  394. $publicize_permanently_disabled = false; 
  395. if ( function_exists( 'is_publicize_permanently_disabled' ) ) { 
  396. $publicize_permanently_disabled = is_publicize_permanently_disabled( $this->blog_id ); 
  397. return $publicize_permanently_disabled;  
  398.  
  399. function get_page_on_front() { 
  400. return (int) get_option( 'page_on_front' ); 
  401.  
  402. function get_page_for_posts() { 
  403. return (int) get_option( 'page_for_posts' ); 
  404.  
  405. function is_headstart() { 
  406. return get_option( 'headstart' ); 
  407.  
  408. function get_wordpress_version() { 
  409. global $wp_version; 
  410. return $wp_version;