summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
Diffstat (limited to 'plugins/jetpack/_inc/lib/core-api/wpcom-fields/post-fields-publicize-connections.php')
-rw-r--r--plugins/jetpack/_inc/lib/core-api/wpcom-fields/post-fields-publicize-connections.php337
1 files changed, 337 insertions, 0 deletions
diff --git a/plugins/jetpack/_inc/lib/core-api/wpcom-fields/post-fields-publicize-connections.php b/plugins/jetpack/_inc/lib/core-api/wpcom-fields/post-fields-publicize-connections.php
new file mode 100644
index 00000000..1aa8ec86
--- /dev/null
+++ b/plugins/jetpack/_inc/lib/core-api/wpcom-fields/post-fields-publicize-connections.php
@@ -0,0 +1,337 @@
+<?php
+
+/**
+ * Add per-post Publicize Connection data.
+ *
+ * { # Post Object
+ * ...
+ * jetpack_publicize_connections: { # Defined below in this file. See schema for more detail.
+ * id: (string) Connection unique_id
+ * service_name: (string) Service slug
+ * display_name: (string) User name/display name of user/connection on Service
+ * enabled: (boolean) Is this connection slated to be shared to? context=edit only
+ * done: (boolean) Is this post (or connection) done sharing? context=edit only
+ * toggleable: (boolean) Can the current user change the `enabled` setting for this Connection+Post? context=edit only
+ * }
+ * ...
+ * meta: { # Not defined in this file. Handled in modules/publicize/publicize.php via `register_meta()`
+ * jetpack_publicize_message: (string) The message to use instead of the post's title when sharing.
+ * }
+ * ...
+ * }
+ *
+ * @since 6.8.0
+ */
+class WPCOM_REST_API_V2_Post_Publicize_Connections_Field extends WPCOM_REST_API_V2_Field_Controller {
+ protected $object_type = 'post';
+ protected $field_name = 'jetpack_publicize_connections';
+
+ public $memoized_updates = array();
+
+ /**
+ * Registers the jetpack_publicize_connections field. Called
+ * automatically on `rest_api_init()`.
+ */
+ public function register_fields() {
+ $this->object_type = get_post_types_by_support( 'publicize' );
+
+ foreach ( $this->object_type as $post_type ) {
+ // Adds meta support for those post types that don't already have it.
+ // Only runs during REST API requests, so it doesn't impact UI.
+ if ( ! post_type_supports( $post_type, 'custom-fields' ) ) {
+ add_post_type_support( $post_type, 'custom-fields' );
+ }
+
+ add_filter( 'rest_pre_insert_' . $post_type, array( $this, 'rest_pre_insert' ), 10, 2 );
+ add_action( 'rest_insert_' . $post_type, array( $this, 'rest_insert' ), 10, 3 );
+ }
+
+ parent::register_fields();
+ }
+
+ /**
+ * Defines data structure and what elements are visible in which contexts
+ */
+ public function get_schema() {
+ return array(
+ '$schema' => 'http://json-schema.org/draft-04/schema#',
+ 'title' => 'jetpack-publicize-post-connections',
+ 'type' => 'array',
+ 'context' => array( 'view', 'edit' ),
+ 'items' => $this->post_connection_schema(),
+ 'default' => array(),
+ );
+ }
+
+ private function post_connection_schema() {
+ return array(
+ '$schema' => 'http://json-schema.org/draft-04/schema#',
+ 'title' => 'jetpack-publicize-post-connection',
+ 'type' => 'object',
+ 'properties' => array(
+ 'id' => array(
+ 'description' => __( 'Unique identifier for the Publicize Connection', 'jetpack' ),
+ 'type' => 'string',
+ 'context' => array( 'view', 'edit' ),
+ 'readonly' => true,
+ ),
+ 'service_name' => array(
+ 'description' => __( 'Alphanumeric identifier for the Publicize Service', 'jetpack' ),
+ 'type' => 'string',
+ 'context' => array( 'view', 'edit' ),
+ 'readonly' => true,
+ ),
+ 'display_name' => array(
+ 'description' => __( 'Username of the connected account', 'jetpack' ),
+ 'type' => 'string',
+ 'context' => array( 'view', 'edit' ),
+ 'readonly' => true,
+ ),
+ 'enabled' => array(
+ 'description' => __( 'Whether to share to this connection', 'jetpack' ),
+ 'type' => 'boolean',
+ 'context' => array( 'edit' ),
+ ),
+ 'done' => array(
+ 'description' => __( 'Whether Publicize has already finished sharing for this post', 'jetpack' ),
+ 'type' => 'boolean',
+ 'context' => array( 'edit' ),
+ 'readonly' => true,
+ ),
+ 'toggleable' => array(
+ 'description' => __( 'Whether `enable` can be changed for this post/connection', 'jetpack' ),
+ 'type' => 'boolean',
+ 'context' => array( 'edit' ),
+ 'readonly' => true,
+ ),
+ ),
+ );
+ }
+
+ /**
+ * @param int $post_id
+ * @return true|WP_Error
+ */
+ function permission_check( $post_id ) {
+ global $publicize;
+
+ if ( $publicize->current_user_can_access_publicize_data( $post_id ) ) {
+ return true;
+ }
+
+ return new WP_Error(
+ 'invalid_user_permission_publicize',
+ __( 'Sorry, you are not allowed to access Publicize data for this post.', 'jetpack' ),
+ array( 'status' => rest_authorization_required_code() )
+ );
+ }
+
+ /**
+ * Getter permission check
+ *
+ * @param array $post_array Response data from Post Endpoint
+ * @return true|WP_Error
+ */
+ function get_permission_check( $post_array, $request ) {
+ return $this->permission_check( isset( $post_array['id'] ) ? $post_array['id'] : 0 );
+
+ }
+
+ /**
+ * Setter permission check
+ *
+ * @param WP_Post $post
+ * @return true|WP_Error
+ */
+ public function update_permission_check( $value, $post, $request ) {
+ return $this->permission_check( isset( $post->ID ) ? $post->ID : 0 );
+ }
+
+ /**
+ * Getter: Retrieve current list of connected social accounts for a given post.
+ *
+ * @see Publicize::get_filtered_connection_data()
+ *
+ * @param array $post_array Response from Post Endpoint
+ * @param WP_REST_Request
+ *
+ * @return array List of connections
+ */
+ public function get( $post_array, $request ) {
+ global $publicize;
+
+ $schema = $this->post_connection_schema();
+ $properties = array_keys( $schema['properties'] );
+
+ $connections = $publicize->get_filtered_connection_data( $post_array['id'] );
+
+ $output_connections = array();
+ foreach ( $connections as $connection ) {
+ $output_connection = array();
+ foreach ( $properties as $property ) {
+ if ( isset( $connection[ $property ] ) ) {
+ $output_connection[ $property ] = $connection[ $property ];
+ }
+ }
+
+ $output_connection['id'] = (string) $connection['unique_id'];
+
+ $output_connections[] = $output_connection;
+ }
+
+ return $output_connections;
+ }
+
+ /**
+ * Prior to updating the post, first calculate which Services to
+ * Publicize to and which to skip.
+ *
+ * @param object $post Post data to insert/update.
+ * @param WP_REST_Request $request
+ * @return Filtered $post
+ */
+ public function rest_pre_insert( $post, $request ) {
+ if ( ! isset( $request['jetpack_publicize_connections'] ) ) {
+ return $post;
+ }
+
+ $permission_check = $this->update_permission_check( $request['jetpack_publicize_connections'], $post, $request );
+
+ if ( is_wp_error( $permission_check ) ) {
+ return $permission_check;
+ }
+
+ // memoize
+ $this->get_meta_to_update( $request['jetpack_publicize_connections'], isset( $post->ID ) ? $post->ID : 0 );
+
+ return $post;
+ }
+
+ /**
+ * After creating a new post, update our cached data to reflect
+ * the new post ID.
+ *
+ * @param WP_Post $post
+ * @param WP_REST_Request $request
+ * @param bool $is_new
+ */
+ public function rest_insert( $post, $request, $is_new ) {
+ if ( ! $is_new ) {
+ // An existing post was edited - no need to update
+ // our cache - we started out knowing the correct
+ // post ID.
+ return;
+ }
+
+ if ( ! isset( $request['jetpack_publicize_connections'] ) ) {
+ return;
+ }
+
+ if ( ! isset( $this->memoized_updates[0] ) ) {
+ return;
+ }
+
+ $this->memoized_updates[ $post->ID ] = $this->memoized_updates[0];
+ unset( $this->memoized_updates[0] );
+ }
+
+ protected function get_meta_to_update( $requested_connections, $post_id = 0 ) {
+ global $publicize;
+
+ if ( isset( $this->memoized_updates[$post_id] ) ) {
+ return $this->memoized_updates[$post_id];
+ }
+
+ $available_connections = $publicize->get_filtered_connection_data( $post_id );
+
+ $changed_connections = array();
+
+ // Build lookup mappings
+ $available_connections_by_unique_id = array();
+ $available_connections_by_service_name = array();
+ foreach ( $available_connections as $available_connection ) {
+ $available_connections_by_unique_id[ $available_connection['unique_id'] ] = $available_connection;
+
+ if ( ! isset( $available_connections_by_service_name[ $available_connection['service_name'] ] ) ) {
+ $available_connections_by_service_name[ $available_connection['service_name'] ] = array();
+ }
+ $available_connections_by_service_name[ $available_connection['service_name'] ][] = $available_connection;
+ }
+
+ // Handle { service_name: $service_name, enabled: (bool) }
+ foreach ( $requested_connections as $requested_connection ) {
+ if ( ! isset( $requested_connection['service_name'] ) ) {
+ continue;
+ }
+
+ if ( ! isset( $available_connections_by_service_name[ $requested_connection['service_name'] ] ) ) {
+ continue;
+ }
+
+ foreach ( $available_connections_by_service_name[ $requested_connection['service_name'] ] as $available_connection ) {
+ $changed_connections[ $available_connection['unique_id'] ] = $requested_connection['enabled'];
+ }
+ }
+
+ // Handle { id: $id, enabled: (bool) }
+ // These override the service_name settings
+ foreach ( $requested_connections as $requested_connection ) {
+ if ( ! isset( $requested_connection['id'] ) ) {
+ continue;
+ }
+
+ if ( ! isset( $available_connections_by_unique_id[ $requested_connection['id'] ] ) ) {
+ continue;
+ }
+
+ $changed_connections[ $requested_connection['id'] ] = $requested_connection['enabled'];
+ }
+
+ // Set all changed connections to their new value
+ foreach ( $changed_connections as $unique_id => $enabled ) {
+ $connection = $available_connections_by_unique_id[ $unique_id ];
+
+ if ( $connection['done'] || ! $connection['toggleable'] ) {
+ continue;
+ }
+
+ $available_connections_by_unique_id[ $unique_id ]['enabled'] = $enabled;
+ }
+
+ $meta_to_update = array();
+ // For all connections, ensure correct post_meta
+ foreach ( $available_connections_by_unique_id as $unique_id => $available_connection ) {
+ if ( $available_connection['enabled'] ) {
+ $meta_to_update[$publicize->POST_SKIP . $unique_id] = null;
+ } else {
+ $meta_to_update[$publicize->POST_SKIP . $unique_id] = 1;
+ }
+ }
+
+ $this->memoized_updates[$post_id] = $meta_to_update;
+
+ return $meta_to_update;
+ }
+
+ /**
+ * Update the connections slated to be shared to.
+ *
+ * @param array $requested_connections
+ * Items are either `{ id: (string) }` or `{ service_name: (string) }`
+ * @param WP_Post $post
+ * @param WP_REST_Request
+ */
+ public function update( $requested_connections, $post, $request ) {
+ foreach ( $this->get_meta_to_update( $requested_connections, $post->ID ) as $meta_key => $meta_value ) {
+ if ( is_null( $meta_value ) ) {
+ delete_post_meta( $post->ID, $meta_key );
+ } else {
+ update_post_meta( $post->ID, $meta_key, $meta_value );
+ }
+ }
+ }
+}
+
+if ( Jetpack::is_module_active( 'publicize' ) ) {
+ wpcom_rest_api_v2_load_plugin( 'WPCOM_REST_API_V2_Post_Publicize_Connections_Field' );
+} \ No newline at end of file