This project does not seem to handle request data directly as such no vulnerable execution paths were found.
include
, or for example
via PHP's auto-loading mechanism.
These results are based on our legacy PHP analysis, consider migrating to our new PHP analysis engine instead. Learn more
1 | <?php |
||
2 | /** |
||
3 | * Database interface. |
||
4 | * @package WordPress_GitHub_Sync |
||
5 | */ |
||
6 | |||
7 | /** |
||
8 | * Class WordPress_GitHub_Sync_Database |
||
9 | */ |
||
10 | class WordPress_GitHub_Sync_Database { |
||
11 | |||
12 | /** |
||
13 | * Application container. |
||
14 | * |
||
15 | * @var WordPress_GitHub_Sync |
||
16 | */ |
||
17 | protected $app; |
||
18 | |||
19 | /** |
||
20 | * Currently whitelisted post types. |
||
21 | * |
||
22 | * @var array |
||
23 | */ |
||
24 | protected $whitelisted_post_types = array( 'post', 'page' ); |
||
25 | |||
26 | /** |
||
27 | * Currently whitelisted post statuses. |
||
28 | * |
||
29 | * @var array |
||
30 | */ |
||
31 | protected $whitelisted_post_statuses = array( 'publish' ); |
||
32 | |||
33 | /** |
||
34 | * Instantiates a new Database object. |
||
35 | * |
||
36 | * @param WordPress_GitHub_Sync $app Application container. |
||
37 | */ |
||
38 | 22 | public function __construct( WordPress_GitHub_Sync $app ) { |
|
39 | 22 | $this->app = $app; |
|
40 | 22 | } |
|
41 | |||
42 | /** |
||
43 | * Queries the database for all of the supported posts. |
||
44 | * |
||
45 | * @return WordPress_GitHub_Sync_Post[]|WP_Error |
||
46 | */ |
||
47 | 3 | public function fetch_all_supported() { |
|
48 | $args = array( |
||
49 | 3 | 'post_type' => $this->get_whitelisted_post_types(), |
|
50 | 3 | 'post_status' => $this->get_whitelisted_post_statuses(), |
|
51 | 3 | 'nopaging' => true, |
|
0 ignored issues
–
show
introduced
by
![]() |
|||
52 | 3 | 'fields' => 'ids', |
|
53 | 3 | ); |
|
54 | |||
55 | 3 | $query = new WP_Query( apply_filters( 'wpghs_pre_fetch_all_supported', $args ) ); |
|
56 | |||
57 | 3 | $post_ids = $query->get_posts(); |
|
58 | |||
59 | 3 | if ( ! $post_ids ) { |
|
60 | 1 | return new WP_Error( |
|
61 | 1 | 'no_results', |
|
62 | 1 | __( 'Querying for supported posts returned no results.', 'wp-github-sync' ) |
|
63 | 1 | ); |
|
64 | } |
||
65 | |||
66 | 2 | $results = array(); |
|
67 | 2 | foreach ( $post_ids as $post_id ) { |
|
68 | 2 | $results[] = new WordPress_GitHub_Sync_Post( $post_id, $this->app->api() ); |
|
69 | 2 | } |
|
70 | |||
71 | 2 | return $results; |
|
72 | } |
||
73 | |||
74 | /** |
||
75 | * Queries a post and returns it if it's supported. |
||
76 | * |
||
77 | * @param int $post_id Post ID to fetch. |
||
78 | * |
||
79 | * @return WP_Error|WordPress_GitHub_Sync_Post |
||
80 | */ |
||
81 | 5 | public function fetch_by_id( $post_id ) { |
|
82 | 5 | $post = new WordPress_GitHub_Sync_Post( $post_id, $this->app->api() ); |
|
83 | |||
84 | 5 | if ( ! $this->is_post_supported( $post ) ) { |
|
85 | 4 | return new WP_Error( |
|
86 | 4 | 'unsupported_post', |
|
87 | 4 | sprintf( |
|
88 | 4 | __( |
|
89 | 4 | 'Post ID %s is not supported by WPGHS. See wiki to find out how to add support.', |
|
90 | 'wp-github-sync' |
||
91 | 4 | ), |
|
92 | $post_id |
||
93 | 4 | ) |
|
94 | 4 | ); |
|
95 | } |
||
96 | |||
97 | 1 | return $post; |
|
98 | } |
||
99 | |||
100 | /** |
||
101 | * Queries for a post by provided sha. |
||
102 | * |
||
103 | * @param string $sha Post sha to fetch by. |
||
104 | * |
||
105 | * @return WordPress_GitHub_Sync_Post|WP_Error |
||
106 | */ |
||
107 | 2 | public function fetch_by_sha( $sha ) { |
|
108 | 2 | $query = new WP_Query( array( |
|
109 | 2 | 'meta_key' => '_sha', |
|
0 ignored issues
–
show
|
|||
110 | 2 | 'meta_value' => $sha, |
|
0 ignored issues
–
show
|
|||
111 | 2 | 'meta_compare' => '=', |
|
112 | 2 | 'posts_per_page' => 1, |
|
113 | 2 | 'fields' => 'ids', |
|
114 | 2 | ) ); |
|
115 | |||
116 | 2 | $post_id = $query->get_posts(); |
|
117 | 2 | $post_id = array_pop( $post_id ); |
|
118 | |||
119 | 2 | if ( ! $post_id ) { |
|
120 | 1 | return new WP_Error( |
|
121 | 1 | 'sha_not_found', |
|
122 | 1 | sprintf( |
|
123 | 1 | __( |
|
124 | 1 | 'Post for sha %s not found.', |
|
125 | 'wp-github-sync' |
||
126 | 1 | ), |
|
127 | $sha |
||
128 | 1 | ) |
|
129 | 1 | ); |
|
130 | } |
||
131 | |||
132 | 1 | return new WordPress_GitHub_Sync_Post( $post_id, $this->app->api() ); |
|
133 | } |
||
134 | |||
135 | /** |
||
136 | * Saves an array of Post objects to the database |
||
137 | * and associates their author as well as their latest |
||
138 | * |
||
139 | * @param WordPress_GitHub_Sync_Post[] $posts Array of Posts to save. |
||
140 | * @param string $email Author email. |
||
141 | * |
||
142 | * @return string|WP_Error |
||
143 | */ |
||
144 | 6 | public function save_posts( array $posts, $email ) { |
|
145 | 6 | $user = $this->fetch_commit_user( $email ); |
|
146 | 6 | $user_id = ! is_wp_error( $user ) ? $user->ID : 0; |
|
147 | |||
148 | /** |
||
149 | * Whether an error has occurred. |
||
150 | * |
||
151 | * @var WP_Error|false $error |
||
152 | */ |
||
153 | 6 | $error = false; |
|
154 | |||
155 | 6 | foreach ( $posts as $post ) { |
|
156 | 6 | $args = apply_filters( 'wpghs_pre_import_args', $post->get_args(), $post ); |
|
157 | |||
158 | 6 | remove_filter('content_save_pre', 'wp_filter_post_kses'); |
|
0 ignored issues
–
show
|
|||
159 | 6 | $post_id = $post->is_new() ? |
|
160 | 6 | wp_insert_post( $args, true ) : |
|
161 | 6 | wp_update_post( $args, true ); |
|
162 | 6 | add_filter('content_save_pre', 'wp_filter_post_kses'); |
|
0 ignored issues
–
show
|
|||
163 | |||
164 | 6 | if ( is_wp_error( $post_id ) ) { |
|
165 | if ( ! $error ) { |
||
166 | $error = $post_id; |
||
167 | } else { |
||
168 | $error->add( $post_id->get_error_code(), $post_id->get_error_message() ); |
||
169 | } |
||
170 | |||
171 | // Abort saving if updating the post fails. |
||
172 | continue; |
||
173 | } |
||
174 | |||
175 | 6 | $this->set_revision_author( $post_id, $user_id ); |
|
176 | |||
177 | 6 | if ( $post->is_new() ) { |
|
178 | 3 | $this->set_post_author( $post_id, $user_id ); |
|
179 | 3 | } |
|
180 | |||
181 | 6 | $post->set_post( get_post( $post_id ) ); |
|
182 | |||
183 | 6 | $meta = apply_filters( 'wpghs_pre_import_meta', $post->get_meta(), $post ); |
|
184 | |||
185 | 6 | foreach ( $meta as $key => $value ) { |
|
186 | 6 | update_post_meta( $post_id, $key, $value ); |
|
187 | 6 | } |
|
188 | 6 | } |
|
189 | |||
190 | 6 | if ( $error ) { |
|
191 | return $error; |
||
192 | } |
||
193 | |||
194 | 6 | return __( 'Successfully saved posts.', 'wp-github-sync' ); |
|
195 | } |
||
196 | |||
197 | /** |
||
198 | * Deletes a post from the database based on its GitHub path. |
||
199 | * |
||
200 | * @param string $path Path of Post to delete. |
||
201 | * |
||
202 | * @return string|WP_Error |
||
203 | */ |
||
204 | 5 | public function delete_post_by_path( $path ) { |
|
205 | 5 | $query = new WP_Query( array( |
|
206 | 5 | 'meta_key' => '_wpghs_github_path', |
|
0 ignored issues
–
show
|
|||
207 | 5 | 'meta_value' => $path, |
|
0 ignored issues
–
show
|
|||
208 | 5 | 'meta_compare' => '=', |
|
209 | 5 | 'posts_per_page' => 1, |
|
210 | 5 | 'fields' => 'ids', |
|
211 | 5 | ) ); |
|
212 | |||
213 | 5 | $post_id = $query->get_posts(); |
|
214 | 5 | $post_id = array_pop( $post_id ); |
|
215 | |||
216 | 5 | if ( ! $post_id ) { |
|
217 | 4 | $parts = explode( '/', $path ); |
|
218 | 4 | $filename = array_pop( $parts ); |
|
219 | 4 | $directory = $parts ? array_shift( $parts ) : ''; |
|
220 | |||
221 | 4 | View Code Duplication | if ( false !== strpos( $directory, 'post' ) ) { |
0 ignored issues
–
show
This code seems to be duplicated across your project.
Duplicated code is one of the most pungent code smells. If you need to duplicate the same code in three or more different places, we strongly encourage you to look into extracting the code into a single class or operation. You can also find more detailed suggestions in the “Code” section of your repository. ![]() |
|||
222 | 2 | preg_match( '/([0-9]{4})-([0-9]{2})-([0-9]{2})-(.*)\.md/', $filename, $matches ); |
|
223 | 2 | $title = $matches[4]; |
|
224 | |||
225 | 2 | $query = new WP_Query( array( |
|
226 | 2 | 'name' => $title, |
|
227 | 2 | 'posts_per_page' => 1, |
|
228 | 2 | 'post_type' => $this->get_whitelisted_post_types(), |
|
229 | 2 | 'fields' => 'ids', |
|
230 | 2 | ) ); |
|
231 | |||
232 | 2 | $post_id = $query->get_posts(); |
|
233 | 2 | $post_id = array_pop( $post_id ); |
|
234 | 2 | } |
|
235 | |||
236 | 4 | View Code Duplication | if ( ! $post_id ) { |
0 ignored issues
–
show
This code seems to be duplicated across your project.
Duplicated code is one of the most pungent code smells. If you need to duplicate the same code in three or more different places, we strongly encourage you to look into extracting the code into a single class or operation. You can also find more detailed suggestions in the “Code” section of your repository. ![]() |
|||
237 | 3 | preg_match( '/(.*)\.md/', $filename, $matches ); |
|
238 | 3 | $title = $matches[1]; |
|
239 | |||
240 | 3 | $query = new WP_Query( array( |
|
241 | 3 | 'name' => $title, |
|
242 | 3 | 'posts_per_page' => 1, |
|
243 | 3 | 'post_type' => $this->get_whitelisted_post_types(), |
|
244 | 3 | 'fields' => 'ids', |
|
245 | 3 | ) ); |
|
246 | |||
247 | 3 | $post_id = $query->get_posts(); |
|
248 | 3 | $post_id = array_pop( $post_id ); |
|
249 | 3 | } |
|
250 | 4 | } |
|
251 | |||
252 | 5 | if ( ! $post_id ) { |
|
253 | 1 | return new WP_Error( |
|
254 | 1 | 'path_not_found', |
|
255 | 1 | sprintf( |
|
256 | 1 | __( 'Post not found for path %s.', 'wp-github-sync' ), |
|
257 | $path |
||
258 | 1 | ) |
|
259 | 1 | ); |
|
260 | } |
||
261 | |||
262 | 4 | $result = wp_delete_post( $post_id ); |
|
263 | |||
264 | // If deleting fails... |
||
265 | 4 | if ( false === $result ) { |
|
266 | $post = get_post( $post_id ); |
||
267 | |||
268 | // ...and the post both exists and isn't in the trash... |
||
269 | if ( $post && 'trash' !== $post->post_status ) { |
||
270 | // ... then something went wrong. |
||
271 | return new WP_Error( |
||
272 | 'db_error', |
||
273 | sprintf( |
||
274 | __( 'Failed to delete post ID %d.', 'wp-github-sync' ), |
||
275 | $post_id |
||
276 | ) |
||
277 | ); |
||
278 | } |
||
279 | } |
||
280 | |||
281 | 4 | return sprintf( |
|
282 | 4 | __( 'Successfully deleted post ID %d.', 'wp-github-sync' ), |
|
283 | $post_id |
||
284 | 4 | ); |
|
285 | } |
||
286 | |||
287 | /** |
||
288 | * Returns the list of post type permitted. |
||
289 | * |
||
290 | * @return array |
||
291 | */ |
||
292 | 10 | protected function get_whitelisted_post_types() { |
|
293 | 10 | return apply_filters( 'wpghs_whitelisted_post_types', $this->whitelisted_post_types ); |
|
294 | } |
||
295 | |||
296 | /** |
||
297 | * Returns the list of post status permitted. |
||
298 | * |
||
299 | * @return array |
||
300 | */ |
||
301 | 7 | protected function get_whitelisted_post_statuses() { |
|
302 | 7 | return apply_filters( 'wpghs_whitelisted_post_statuses', $this->whitelisted_post_statuses ); |
|
303 | } |
||
304 | |||
305 | /** |
||
306 | * Formats a whitelist array for a query. |
||
307 | * |
||
308 | * @param array $whitelist Whitelisted posts to format into query. |
||
309 | * |
||
310 | * @return string Whitelist formatted for query |
||
311 | */ |
||
312 | protected function format_for_query( $whitelist ) { |
||
313 | foreach ( $whitelist as $key => $value ) { |
||
314 | $whitelist[ $key ] = "'$value'"; |
||
315 | } |
||
316 | |||
317 | return implode( ', ', $whitelist ); |
||
318 | } |
||
319 | |||
320 | /** |
||
321 | * Verifies that both the post's status & type |
||
322 | * are currently whitelisted |
||
323 | * |
||
324 | * @param WordPress_GitHub_Sync_Post $post Post to verify. |
||
325 | * |
||
326 | * @return boolean True if supported, false if not. |
||
327 | */ |
||
328 | 5 | protected function is_post_supported( WordPress_GitHub_Sync_Post $post ) { |
|
329 | 5 | if ( wp_is_post_revision( $post->id ) ) { |
|
330 | 1 | return false; |
|
331 | } |
||
332 | |||
333 | // We need to allow trashed posts to be queried, but they are not whitelisted for export. |
||
334 | 4 | if ( ! in_array( $post->status(), $this->get_whitelisted_post_statuses() ) && 'trash' !== $post->status() ) { |
|
335 | 1 | return false; |
|
336 | } |
||
337 | |||
338 | 3 | if ( ! in_array( $post->type(), $this->get_whitelisted_post_types() ) ) { |
|
339 | 1 | return false; |
|
340 | } |
||
341 | |||
342 | 2 | if ( $post->has_password() ) { |
|
343 | 1 | return false; |
|
344 | } |
||
345 | |||
346 | 1 | return apply_filters( 'wpghs_is_post_supported', true, $post ); |
|
347 | } |
||
348 | |||
349 | /** |
||
350 | * Retrieves the commit user for a provided email address. |
||
351 | * |
||
352 | * Searches for a user with provided email address or returns |
||
353 | * the default user saved in the database. |
||
354 | * |
||
355 | * @param string $email User email address to search for. |
||
356 | * |
||
357 | * @return WP_Error|WP_User |
||
358 | */ |
||
359 | 6 | protected function fetch_commit_user( $email ) { |
|
360 | // If we can't find a user and a default hasn't been set, |
||
361 | // we're just going to set the revision author to 0. |
||
362 | 6 | $user = get_user_by( 'email', $email ); |
|
363 | |||
364 | 6 | if ( ! $user ) { |
|
365 | // Use the default user. |
||
366 | 4 | $user = get_user_by( 'id', (int) get_option( 'wpghs_default_user' ) ); |
|
367 | 4 | } |
|
368 | |||
369 | 6 | if ( ! $user ) { |
|
370 | 2 | return new WP_Error( |
|
371 | 2 | 'user_not_found', |
|
372 | 2 | sprintf( |
|
373 | 2 | __( 'Commit user not found for email %s', 'wp-github-sync' ), |
|
374 | |||
375 | 2 | ) |
|
376 | 2 | ); |
|
377 | } |
||
378 | |||
379 | 4 | return $user; |
|
380 | } |
||
381 | |||
382 | /** |
||
383 | * Sets the author latest revision |
||
384 | * of the provided post ID to the provided user. |
||
385 | * |
||
386 | * @param int $post_id Post ID to update revision author. |
||
387 | * @param int $user_id User ID for revision author. |
||
388 | * |
||
389 | * @return string|WP_Error |
||
390 | */ |
||
391 | 6 | protected function set_revision_author( $post_id, $user_id ) { |
|
392 | 6 | $revision = wp_get_post_revisions( $post_id ); |
|
393 | |||
394 | 6 | if ( ! $revision ) { |
|
395 | 3 | $new_revision = wp_save_post_revision( $post_id ); |
|
396 | |||
397 | 3 | if ( ! $new_revision || is_wp_error( $new_revision ) ) { |
|
398 | return new WP_Error( 'db_error', 'There was a problem saving a new revision.' ); |
||
399 | } |
||
400 | |||
401 | // `wp_save_post_revision` returns the ID, whereas `get_post_revision` returns the whole object |
||
402 | // in order to be consistent, let's make sure we have the whole object before continuing. |
||
403 | 3 | $revision = get_post( $new_revision ); |
|
404 | |||
405 | 3 | if ( ! $revision ) { |
|
406 | return new WP_Error( 'db_error', 'There was a problem retrieving the newly recreated revision.' ); |
||
407 | } |
||
408 | 3 | } else { |
|
409 | 3 | $revision = array_shift( $revision ); |
|
410 | } |
||
411 | |||
412 | 6 | return $this->set_post_author( $revision->ID, $user_id ); |
|
413 | } |
||
414 | |||
415 | /** |
||
416 | * Updates the user ID for the provided post ID. |
||
417 | * |
||
418 | * Bypassing triggering any hooks, including creating new revisions. |
||
419 | * |
||
420 | * @param int $post_id Post ID to update. |
||
421 | * @param int $user_id User ID to update to. |
||
422 | * |
||
423 | * @return string|WP_Error |
||
424 | */ |
||
425 | 6 | protected function set_post_author( $post_id, $user_id ) { |
|
426 | 6 | global $wpdb; |
|
427 | |||
428 | 6 | $result = $wpdb->update( |
|
0 ignored issues
–
show
|
|||
429 | 6 | $wpdb->posts, |
|
430 | array( |
||
431 | 6 | 'post_author' => (int) $user_id, |
|
432 | 6 | ), |
|
433 | array( |
||
434 | 6 | 'ID' => (int) $post_id, |
|
435 | 6 | ), |
|
436 | 6 | array( '%d' ), |
|
437 | 6 | array( '%d' ) |
|
438 | 6 | ); |
|
439 | |||
440 | 6 | if ( false === $result ) { |
|
441 | return new WP_Error( 'db_error', $wpdb->last_error ); |
||
442 | } |
||
443 | |||
444 | 6 | if ( 0 === $result ) { |
|
445 | 2 | return sprintf( |
|
446 | 2 | __( 'No change for post ID %d.', 'wp-github-sync' ), |
|
447 | $post_id |
||
448 | 2 | ); |
|
449 | } |
||
450 | |||
451 | 4 | clean_post_cache( $post_id ); |
|
452 | |||
453 | 4 | return sprintf( |
|
454 | 4 | __( 'Successfully updated post ID %d.', 'wp-github-sync' ), |
|
455 | $post_id |
||
456 | 4 | ); |
|
457 | } |
||
458 | |||
459 | /** |
||
460 | * Update the provided post's blob sha. |
||
461 | * |
||
462 | * @param WordPress_GitHub_Sync_Post $post Post to update. |
||
463 | * @param string $sha Sha to update to. |
||
464 | * |
||
465 | * @return bool|int |
||
466 | */ |
||
467 | 1 | public function set_post_sha( $post, $sha ) { |
|
468 | 1 | return update_post_meta( $post->id, '_sha', $sha ); |
|
469 | } |
||
470 | } |
||
471 |