Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
6 changes: 6 additions & 0 deletions classes/admin/class-editor.php
Original file line number Diff line number Diff line change
Expand Up @@ -25,6 +25,12 @@ public function __construct() {
* @return void
*/
public function enqueue_editor_script() {
// Assigning a page-type is an editorial decision, so require the capability
// to edit others' posts. Authors editing their own posts don't get the sidebar.
if ( ! \current_user_can( 'edit_others_posts' ) ) {
return;
}

$page_types = \progress_planner()->get_page_types()->get_page_types();

// Check if the page-type is set in the URL (user is coming from the Settings page).
Expand Down
51 changes: 51 additions & 0 deletions classes/class-page-types.php
Original file line number Diff line number Diff line change
Expand Up @@ -34,6 +34,9 @@ public function __construct() {
\add_action( 'init', [ $this, 'maybe_add_terms' ] );
\add_action( 'init', [ $this, 'maybe_update_terms' ] );

// Drop the page-type from REST post writes by users who can't assign it.
\add_filter( 'rest_request_before_callbacks', [ $this, 'remove_page_type_if_not_allowed' ], 10, 3 );

// Add hook when updating the `page_on_front` option.
\add_action( 'update_option_page_on_front', [ $this, 'update_option_page_on_front' ] );

Expand Down Expand Up @@ -63,10 +66,58 @@ public function create_taxonomy() {
'rewrite' => [ 'slug' => 'site-type' ],
'show_in_rest' => true,
'show_in_menu' => false,
// Assigning a page-type says what a page is *for*, which is a site-level
// editorial decision rather than something an author does on their own
// post. Without this, assign_terms falls back to `edit_posts` and any
// author can set it through the standard REST post endpoint.
'capabilities' => [
'manage_terms' => 'manage_categories',
'edit_terms' => 'manage_categories',
'delete_terms' => 'manage_categories',
'assign_terms' => 'edit_others_posts',
],
]
);
}

/**
* Remove the page-type from a REST post write when the user can't assign it.
*
* Without this, WP rejects the whole request with `rest_cannot_assign_term`, so an
* author who resubmits the page-type an editor already set loses every other change
* in that same save (title, content). Silently dropping the field keeps their edit
* working while leaving the existing page-type untouched.
*
* Hooked on `rest_request_before_callbacks` because the taxonomy permission check
* lives in the posts controller's `*_permissions_check()`, which runs before
* `rest_pre_insert_{$post_type}` would fire.
*
* @param \WP_REST_Response|\WP_HTTP_Response|\WP_Error|mixed $response The response.
* @param array $handler The route handler.
* @param \WP_REST_Request $request The request.
*
* @return \WP_REST_Response|\WP_HTTP_Response|\WP_Error|mixed
*/
public function remove_page_type_if_not_allowed( $response, $handler, $request ) {
if ( null === $request[ self::TAXONOMY_NAME ] ) {
return $response;
}

// Only touch writes; a GET can legitimately carry the field as a query filter.
if ( ! \in_array( $request->get_method(), [ 'POST', 'PUT', 'PATCH' ], true ) ) {
return $response;
}

$taxonomy = \get_taxonomy( self::TAXONOMY_NAME );
if ( ! $taxonomy || \current_user_can( $taxonomy->cap->assign_terms ) ) {
return $response;
}

unset( $request[ self::TAXONOMY_NAME ] );

return $response;
}

/**
* Maybe add terms to the `progress_planner_page_types` taxonomy.
*
Expand Down
Loading