Skip to content

Commit

Permalink
Changes to WordCamp and Meetup REST API endpoints (#926)
Browse files Browse the repository at this point in the history
* List meetups on their REST API base and hide all meetups without public post status

* Prevent getting non-public WordCamp data from REST API
  • Loading branch information
timiwahalahti committed May 20, 2024
1 parent 4fcecb6 commit e13fb5e
Show file tree
Hide file tree
Showing 3 changed files with 161 additions and 18 deletions.
Original file line number Diff line number Diff line change
@@ -0,0 +1,90 @@
<?php

/**
* Class to access Meetup CPT posts via the v2 REST API.
*
* @see WP_REST_Posts_Controller
*/
class WordCamp_REST_Meetups_Controller extends WP_REST_Posts_Controller {
/**
* Retrieves the Meetup post's schema, conforming to JSON Schema.
*
* Meetup-specific modifications to the standard post schema.
*
* @access public
*
* @return array Item schema data.
*/
public function get_item_schema() {
$schema = parent::get_item_schema();

// Since there is more than one public post status, show it in REST response.
if ( false === array_search( 'view', $schema['properties']['status']['context'] ) ) {
$schema['properties']['status']['context'][] = 'view';
}

return $this->add_additional_fields_schema( $schema );
}

/**
* Sanitizes and validates the list of post statuses, including whether the
* user can query private statuses.
*
* Based on the method in WP_REST_Posts_Controller, but takes into account that
* there are multiple public statuses for the Meetup CPT.
*
* @access public
*
* @param string|array $statuses One or more post statuses.
* @param WP_REST_Request $request Full details about the request.
* @param string $parameter Additional parameter to pass to validation.
* @return array|WP_Error A list of valid statuses, otherwise WP_Error object.
*/
public function sanitize_post_statuses( $statuses, $request, $parameter ) {
$statuses = wp_parse_slug_list( $statuses );

$public_statuses = Meetup_Loader::get_public_post_statuses();

foreach ( $statuses as $status ) {
if ( in_array( $status, $public_statuses ) ) {
continue;
}

$post_type_obj = get_post_type_object( $this->post_type );

if ( current_user_can( $post_type_obj->cap->edit_posts ) ) {
$result = rest_validate_request_arg( $status, $request, $parameter );
if ( is_wp_error( $result ) ) {
return $result;
}
} else {
return new WP_Error( 'rest_forbidden_status', __( 'Status is forbidden.' ), array( 'status' => rest_authorization_required_code() ) );
}
}

return $statuses;
}

/**
* Checks if user can read the Meetup post.
*
* First make our custom check against public Meetup statuses and
* after that fallback to default WP_REST_Posts_Controller for assurance.
*
* @access public
*
* @param object $post Post object.
* @return bool Whether the post can be read.
*/
public function check_read_permission( $post ) {
$public_statuses = Meetup_Loader::get_public_post_statuses();

// If post status is not listed as public, it cannot be read.
if ( ! in_array( $post->post_status, $public_statuses ) ) {
return false;
}

// Fallback to default read permission check.
return WP_REST_Posts_Controller::check_read_permission( $post );
}
}
63 changes: 45 additions & 18 deletions public_html/wp-content/plugins/wcpt/wcpt-meetup/meetup-loader.php
Original file line number Diff line number Diff line change
Expand Up @@ -25,6 +25,7 @@ public function __construct() {
parent::__construct();
add_action( 'init', array( $this, 'register_meetup_taxonomy' ) );
add_action( 'set_object_terms', array( $this, 'log_meetup_tags' ), 10, 6 );
add_filter( 'rest_wp_meetup_collection_params', array( $this, 'set_rest_post_status_default' ) );
}

/**
Expand Down Expand Up @@ -53,16 +54,19 @@ public function log_meetup_tags( $event_id, $terms, $tt_ids, $taxonomy, $append,
'object_ids' => $event_id,
'term_taxonomy_id' => $tt_added_ids,
'fields' => 'names',
)
);
) );

$added_terms = $added_terms_query->get_terms();

add_post_meta( $event_id, '_tags_log', array(
'timestamp' => time(),
'user_id' => get_current_user_id(),
'message' => 'Tags added: ' . join( ', ', $added_terms ),
) );
add_post_meta(
$event_id,
'_tags_log',
array(
'timestamp' => time(),
'user_id' => get_current_user_id(),
'message' => 'Tags added: ' . join( ', ', $added_terms ),
)
);
}

if ( count( $tt_removed_ids ) > 0 ) {
Expand All @@ -71,14 +75,17 @@ public function log_meetup_tags( $event_id, $terms, $tt_ids, $taxonomy, $append,
'term_taxonomy_id' => $tt_removed_ids,
'fields' => 'names',
'hide_empty' => false,
)
) )->get_terms();

add_post_meta( $event_id, '_tags_log', array(
'timestamp' => time(),
'user_id' => get_current_user_id(),
'message' => 'Tags removed: ' . join( ', ', $removed_terms ),
) );
) ) )->get_terms();

add_post_meta(
$event_id,
'_tags_log',
array(
'timestamp' => time(),
'user_id' => get_current_user_id(),
'message' => 'Tags removed: ' . join( ', ', $removed_terms ),
)
);
}

}
Expand Down Expand Up @@ -111,13 +118,14 @@ public function register_meetup_taxonomy() {
* Include files specific for meetup event
*/
public function includes() {
require_once WCPT_DIR . 'wcpt-meetup/class-wp-rest-meetups-controller.php';
}

/**
* Register meetup custom post type
*/
public function register_post_types() {
// Meetup post type labels
// Meetup post type labels.
$wcpt_labels = array(
'name' => __( 'Meetups', 'wordcamporg' ),
'singular_name' => __( 'Meetup', 'wordcamporg' ),
Expand Down Expand Up @@ -147,9 +155,10 @@ public function register_post_types() {
'author',
);

// Register WordCamp post type
// Register meetup post type.
register_post_type(
Meetup_Application::POST_TYPE, array(
Meetup_Application::POST_TYPE,
array(
'labels' => $wcpt_labels,
'rewrite' => $wcpt_rewrite,
'supports' => $wcpt_supports,
Expand Down Expand Up @@ -177,6 +186,7 @@ public function register_post_types() {
'menu_icon' => 'dashicons-wordpress',
'show_in_rest' => true,
'rest_base' => 'meetups',
'rest_controller_class' => 'WordCamp_REST_Meetups_Controller',
)
);
}
Expand All @@ -199,6 +209,23 @@ public static function get_public_post_statuses() {
return Meetup_Application::get_public_post_statuses();
}

/**
* Change the default status used for the Meetup CPT in the v2 REST API.
*
* @hooked filter rest_wp_meetup_collection_params
*
* @param array $query_params
*
* @return array
*/
public function set_rest_post_status_default( $query_params ) {
if ( isset( $query_params['status'] ) ) {
$query_params['status']['default'] = self::get_public_post_statuses();
}

return $query_params;
}

}

endif;
Original file line number Diff line number Diff line change
Expand Up @@ -81,4 +81,30 @@ public function sanitize_post_statuses( $statuses, $request, $parameter ) {

return $statuses;
}

/**
* Checks if user can read the WordCamp post.
*
* First make our custom check against public WordCamp statuses and
* after that fallback to default WP_REST_Posts_Controller for assurance.
*
* @access public
*
* @param object $post Post object.
* @return bool Whether the post can be read.
*/
public function check_read_permission( $post ) {
$public_statuses = WordCamp_Loader::get_public_post_statuses();

// Camps that are scheduled and then cancelled should still be available (though not included by default).
$public_statuses[] = 'wcpt-cancelled';

// If post status is not listed as public, it cannot be read.
if ( ! in_array( $post->post_status, $public_statuses ) ) {
return false;
}

// Fallback to default read permission check.
return WP_REST_Posts_Controller::check_read_permission( $post );
}
}

0 comments on commit e13fb5e

Please sign in to comment.