Completed
Push — try/publicize-gutenberg-block-... ( e9ca35...f13e36 )
by Marin
1075:14 queued 1023:28
created

rest_get_publicize_available_services()   A

Complexity

Conditions 1
Paths 1

Size

Total Lines 9

Duplication

Lines 0
Ratio 0 %

Importance

Changes 0
Metric Value
cc 1
nc 1
nop 0
dl 0
loc 9
rs 9.9666
c 0
b 0
f 0
1
<?php
2
/**
3
 * Does setup for Publicize in Gutenberg
4
 *
5
 * Enqueues UI resources and completes REST setup for enabling
6
 * Publicize in Gutenberg.
7
 *
8
 * @package Jetpack
9
 * @subpackage Publicize
10
 * @since 5.9.1
11
 */
12
13
/**
14
 * Class to set up Gutenberg editor support.
15
 *
16
 * @since 5.9.1
17
 */
18
class Jetpack_Publicize_Gutenberg {
19
20
	/**
21
	 * Instance of Publicize used to access data gathering utility methods.
22
	 *
23
	 * @since 5.9.1
24
	 * @var Publicize $publicize Instance of Jetpack Publicize class.
25
	 */
26
	private $publicize;
27
28
	/**
29
	 * Constructor for Jetpack_Publicize_Gutenberg
30
	 *
31
	 * Set up hooks to extend legacy Publicize behavior.
32
	 *
33
	 * @since 5.9.1
34
	 */
35
	public function __construct( $publicize ) {
36
		// Do edit page specific setup.
37
		// Priority 20 to make sure these scripts are enqueued after Gutenberg blocks,
38
		// which are also added to the `admin_enqueue_scripts` hook.
39
		add_action( 'admin_enqueue_scripts', array( $this, 'post_page_enqueue' ), 20 );
40
41
		add_action( 'rest_api_init', array( $this, 'add_publicize_rest_fields' ) );
42
43
		// Set up publicize flags right before post is actually published.
44
		add_filter( 'rest_pre_insert_post', array( $this, 'process_publicize_from_rest' ), 10, 2 );
45
46
		$this->publicize = $publicize;
47
	}
48
49
	/**
50
	 * Retrieve current list of connected social accounts.
51
	 *
52
	 * Gets current list of connected accounts and send them as
53
	 * JSON encoded data.
54
	 *
55
	 * @see Publicize_Base::get_publicize_conns_test_results()
56
	 *
57
	 * @since 5.9.1
58
	 *
59
	 * @param WP_REST_Request $request Request instance from REST call.
0 ignored issues
show
Bug introduced by
There is no parameter named $request. Was it maybe removed?

This check looks for PHPDoc comments describing methods or function parameters that do not exist on the corresponding method or function.

Consider the following example. The parameter $italy is not defined by the method finale(...).

/**
 * @param array $germany
 * @param array $island
 * @param array $italy
 */
function finale($germany, $island) {
    return "2:1";
}

The most likely cause is that the parameter was removed, but the annotation was not.

Loading history...
60
	 *
61
	 * @return string JSON encoded connection list data.
62
	 */
63
	public function rest_get_publicize_connections() {
64
		return wp_json_encode( $this->publicize->get_publicize_conns_test_results() );
65
	}
66
67
	/**
68
	 * Retrieve current list of connected social accounts for a given post.
69
	 *
70
	 * Gets current list of connected accounts and send them as
71
	 * JSON encoded data.
72
	 *
73
	 * @see Publicize::get_filtered_connection_data()
74
	 *
75
	 * @since 5.9.1
76
	 *
77
	 * @param WP_REST_Request $request Request instance from REST call.
78
	 *
79
	 * @return string JSON encoded connection list data.
80
	 */
81
	public function rest_get_publicize_connections_for_post( $request ) {
82
		$post_id = $request['post_id'];
83
		return wp_json_encode( $this->publicize->get_filtered_connection_data( $post_id ) );
84
	}
85
86
	/**
87
	 * Retrieve full list of available Publicize connection services
88
	 * send them as JSON encoded data.
89
	 *
90
	 * @see Publicize::get_available_service_data()
91
	 *
92
	 * @since 6.7.0
93
	 *
94
	 * @return string JSON encoded connection services data.
95
	 */
96
	public function rest_get_publicize_available_services() {
97
		/**
98
		 * We need this because Publicize::get_available_service_data() uses `Jetpack_Keyring_Service_Helper`
99
		 * and `Jetpack_Keyring_Service_Helper` relies on `menu_page_url()`.
100
		 */
101
		include_once( ABSPATH . 'wp-admin/includes/plugin.php' );
102
103
		return $this->publicize->get_available_service_data();
104
	}
105
106
	/**
107
	 * Add rest field to 'post' for Publicize support
108
	 *
109
	 * Sets up 'publicize' schema to submit publicize sharing title
110
	 * and individual connection sharing enables/disables. This schema
111
	 * is registered with the 'post' endpoint REST endpoint so publicize
112
	 * options can be saved when a post is published.
113
	 *
114
	 * @since 5.9.1
115
	 */
116
	public function add_publicize_rest_fields() {
117
		// Schema for wpas.submit[] field.
118
		$publicize_submit_schema = array(
119
			'$schema'    => 'http://json-schema.org/draft-04/schema#',
120
			'title'      => esc_html__( 'Publicize data for publishing post', 'jetpack' ),
121
			'type'       => 'object',
122
			'properties' => array(
123
				'connections' => array(
124
					'description' => esc_html__( 'List of connections to be shared to (or not).', 'jetpack' ),
125
					'type'        => 'array',
126
					'items'       => array(
127
						'type'       => 'object',
128
						'properties' => array(
129
							'unique_id'    => array(
130
								'description' => esc_html__( 'Unique identifier string for a connection', 'jetpack' ),
131
								'type'        => 'string',
132
							),
133
							'should_share' => array(
134
								'description' => esc_html__( 'Whether or not connection should be shared to.', 'jetpack' ),
135
								'type'        => 'boolean',
136
							),
137
138
						),
139
					),
140
				),
141
				'title'       => array(
142
					'description' => esc_html__( 'Optional title to share post with.', 'jetpack' ),
143
					'type'        => 'string',
144
				),
145
			),
146
		);
147
148
		// Registering the publicize field with post endpoint.
149
		register_rest_field(
150
			'post',
151
			'publicize',
152
			array(
153
				'get_callback'    => null,
154
				'update_callback' => null, // Data read/processed before publishing post by 'rest_pre_insert_post' filter.
155
				'schema'          => $publicize_submit_schema,
156
			)
157
		);
158
159
		/**
160
		 * REST endpoint to get connection list data for current user.
161
		 *
162
		 * @see Publicize::get_filtered_connection_data()
163
		 *
164
		 * @since 5.9.1
165
		 */
166
		register_rest_route( 'publicize/', '/connections', array(
167
			'methods'             => 'GET',
168
			'callback'            => array( $this, 'rest_get_publicize_connections' ),
169
			'permission_callback' => array( $this, 'rest_connections_permission_callback' ),
170
		) );
171
172
		/**
173
		 * REST endpoint to get available publicize connection services data.
174
		 *
175
		 * @see Publicize::get_available_service_data()
176
		 *
177
		 * @since 5.9.1
178
		 */
179
		register_rest_route( 'publicize/', '/services', array(
180
			'methods'             => 'GET',
181
			'callback'            => array( $this, 'rest_get_publicize_available_services' ),
182
			'permission_callback' => array( $this, 'rest_connections_permission_callback' ),
183
		) );
184
185
		/**
186
		 * REST endpoint to get connection list data for current user and post id.
187
		 *
188
		 * @see Publicize::get_filtered_connection_data()
189
		 *
190
		 * @since 5.9.1
191
		 */
192
		register_rest_route( 'publicize/', '/posts/(?P<post_id>\d+)/connections', array(
193
			'methods'             => 'GET',
194
			'callback'            => array( $this, 'rest_get_publicize_connections_for_post' ),
195
			'post_id'             => array(
196
				'validate_post_id' => array( $this, 'rest_connections_validate_post_id' ),
197
			),
198
			'permission_callback' => array( $this, 'rest_connections_permission_callback' ),
199
		) );
200
	}
201
202
	/**
203
	 * Check user capability for getting Publicize connection list from endpoint.
204
	 *
205
	 * @since 5.9.1
206
	 *
207
	 * @return boolean True if current user has 'publish_post' capability.
208
	 */
209
	public function rest_connections_permission_callback() {
210
		return current_user_can( 'publish_posts' );
211
	}
212
213
	/**
214
	 * Check post id validity for Publicize connection list REST endpoint.
215
	 *
216
	 * @since 5.9.1
217
	 *
218
	 * @param mixed $param post_id parameter from REST call.
219
	 *
220
	 * @return boolean True if post_id is valid integer
221
	 */
222
	public function rest_connections_validate_post_id( $param ) {
223
		return is_int( $param );
224
	}
225
226
	/**
227
	 * Set up Publicize meta fields for publishing post.
228
	 *
229
	 * Process 'publicize' REST field to setup Publicize for publishing
230
	 * post. Sets post meta keys to enable/disable each connection for
231
	 * the post and sets publicize title meta key if a title message
232
	 * is provided.
233
	 *
234
	 * @since 5.9.1
235
	 *
236
	 * @param stdClass        $new_post_obj Updated post object about to be inserted view REST endpoint.
237
	 * @param WP_REST_Request $request      Request object, possibly containing 'publicize' field {@see add_publicize_rest_fields()}.
238
	 *
239
	 * @return WP_Post Returns the original $new_post value unchanged.
240
	 */
241
	public function process_publicize_from_rest( $new_post_obj, $request ) {
242
		global $publicize;
243
		if ( property_exists( $new_post_obj, 'ID' ) ) {
244
			$post = get_post( $new_post_obj->ID );
245
		} else {
246
			return $new_post_obj;
247
		}
248
249
		// If 'publicize' field has been set from editor and post is about to be published.
250
		if ( isset( $request['publicize'] )
251
				&& ( property_exists( $new_post_obj, 'post_status' ) && ( 'publish' === $new_post_obj->post_status ) )
252
				&& ( 'publish' !== $post->post_status ) ) {
253
254
			$publicize_field = $request['publicize'];
255
256 View Code Duplication
			if ( empty( $publicize_field['title'] ) ) {
257
				delete_post_meta( $post->ID, $publicize->POST_MESS );
258
			} else {
259
				update_post_meta( $post->ID, $publicize->POST_MESS, trim( stripslashes( $publicize_field['title'] ) ) );
260
			}
261
			if ( isset( $publicize_field['connections'] ) ) {
262
				foreach ( (array) $publicize->get_services( 'connected' ) as $service_name => $connections ) {
263
					foreach ( $connections as $connection ) {
264 View Code Duplication
						if ( ! empty( $connection->unique_id ) ) {
265
							$unique_id = $connection->unique_id;
266
						} elseif ( ! empty( $connection['connection_data']['token_id'] ) ) {
267
							$unique_id = $connection['connection_data']['token_id'];
268
						}
269
270
						if ( $this->connection_should_share( $publicize_field['connections'], $unique_id ) ) {
271
							// Delete skip flag meta key.
272
							delete_post_meta( $post->ID, $publicize->POST_SKIP . $unique_id );
0 ignored issues
show
Bug introduced by
The variable $unique_id does not seem to be defined for all execution paths leading up to this point.

If you define a variable conditionally, it can happen that it is not defined for all execution paths.

Let’s take a look at an example:

function myFunction($a) {
    switch ($a) {
        case 'foo':
            $x = 1;
            break;

        case 'bar':
            $x = 2;
            break;
    }

    // $x is potentially undefined here.
    echo $x;
}

In the above example, the variable $x is defined if you pass “foo” or “bar” as argument for $a. However, since the switch statement has no default case statement, if you pass any other value, the variable $x would be undefined.

Available Fixes

  1. Check for existence of the variable explicitly:

    function myFunction($a) {
        switch ($a) {
            case 'foo':
                $x = 1;
                break;
    
            case 'bar':
                $x = 2;
                break;
        }
    
        if (isset($x)) { // Make sure it's always set.
            echo $x;
        }
    }
    
  2. Define a default value for the variable:

    function myFunction($a) {
        $x = ''; // Set a default which gets overridden for certain paths.
        switch ($a) {
            case 'foo':
                $x = 1;
                break;
    
            case 'bar':
                $x = 2;
                break;
        }
    
        echo $x;
    }
    
  3. Add a value for the missing path:

    function myFunction($a) {
        switch ($a) {
            case 'foo':
                $x = 1;
                break;
    
            case 'bar':
                $x = 2;
                break;
    
            // We add support for the missing case.
            default:
                $x = '';
                break;
        }
    
        echo $x;
    }
    
Loading history...
273
						} else {
274
							// Flag connection to be skipped for this post.
275
							update_post_meta( $post->ID, $publicize->POST_SKIP . $unique_id, 1 );
276
						}
277
					}
278
				}
279
			}
280
		}
281
		// Just pass post object through.
282
		return $new_post_obj;
283
	}
284
285
	/**
286
	 * Checks if a connection should be shared to.
287
	 *
288
	 * Checks $connection_id against $connections_array to see if the connection associated
289
	 * with $connection_id should be shared to. Will return true if $connection_id is in the
290
	 * array and 'should_share' property is set to true, and will default to false otherwise.
291
	 *
292
	 * @since 5.9.1
293
	 *
294
	 * @param array  $connections_array 'connections' from 'publicize' REST field {@see add_publicize_rest_fields()}.
295
	 * @param string $connection_id     Connection identifier string that is unique for each connection.
296
	 * @return boolean True if connection should be shared to, false otherwise.
297
	 */
298
	private function connection_should_share( $connections_array, $connection_id ) {
299
		foreach ( $connections_array as $connection ) {
300
			if ( isset( $connection['unique_id'] )
301
				&& ( $connection['unique_id'] === $connection_id )
302
				&& $connection['should_share'] ) {
303
				return true;
304
			}
305
		}
306
		return false;
307
	}
308
309
	/**
310
	 * Enqueue scripts when they are needed for the edit page
311
	 *
312
	 * Enqueues necessary scripts for edit page for Gutenberg
313
	 * editor only.
314
	 *
315
	 * @since 5.9.1
316
	 *
317
	 * @param string $hook Current page url.
318
	 */
319
	public function post_page_enqueue( $hook ) {
320
		if ( ( 'post-new.php' === $hook || 'post.php' === $hook ) && ! isset( $_GET['classic-editor'] ) ) { // Input var okay.
321
			wp_enqueue_style( 'social-logos', null, array( 'genericons' ) );
322
323
			wp_localize_script( 'jetpack-blocks-editor', 'gutenberg_publicize_setup',
324
				array(
325
					'staticConnectionList' => wp_json_encode( $this->publicize->get_filtered_connection_data() ),
326
					'allServices'          => wp_json_encode( $this->publicize->get_available_service_data() ),
327
					'api_nonce'            => wp_create_nonce( 'wp_rest' ),
328
				)
329
			);
330
331
		}
332
	}
333
}
334