-
Notifications
You must be signed in to change notification settings - Fork 4.3k
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Patterns: fix capabilities settings for pattern categories (#55379)
Co-authored-by: Daniel Richards <daniel.richards@automattic.com>
- Loading branch information
1 parent
6a2c92b
commit 5b10d27
Showing
14 changed files
with
483 additions
and
96 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
75 changes: 75 additions & 0 deletions
75
lib/compat/wordpress-6.4/class-gutenberg-rest-blocks-controller-6-4.php
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,75 @@ | ||
<?php | ||
/** | ||
* Reusable blocks REST API: WP_REST_Blocks_Controller class | ||
* | ||
* @package WordPress | ||
* @subpackage REST_API | ||
* @since 5.0.0 | ||
*/ | ||
|
||
/** | ||
* Controller which provides a REST endpoint for the editor to read, create, | ||
* edit and delete reusable blocks. Blocks are stored as posts with the wp_block | ||
* post type. | ||
* | ||
* @since 5.0.0 | ||
* | ||
* @see WP_REST_Posts_Controller | ||
* @see WP_REST_Controller | ||
*/ | ||
class Gutenberg_REST_Blocks_Controller_6_4 extends Gutenberg_REST_Blocks_Controller { | ||
/** | ||
* Gets the link relations available for the post and current user. | ||
* | ||
* @since 6.4.0 Ensures that only users with `edit_terms` capability can add taxonomy terms. | ||
* | ||
* @param WP_Post $post Post object. | ||
* @param WP_REST_Request $request Request object. | ||
* @return array List of link relations. | ||
*/ | ||
protected function get_available_actions( $post, $request ) { | ||
if ( 'edit' !== $request['context'] ) { | ||
return array(); | ||
} | ||
|
||
$rels = array(); | ||
|
||
$post_type = get_post_type_object( $post->post_type ); | ||
|
||
if ( 'attachment' !== $this->post_type && current_user_can( $post_type->cap->publish_posts ) ) { | ||
$rels[] = 'https://api.w.org/action-publish'; | ||
} | ||
|
||
if ( current_user_can( 'unfiltered_html' ) ) { | ||
$rels[] = 'https://api.w.org/action-unfiltered-html'; | ||
} | ||
|
||
if ( 'post' === $post_type->name ) { | ||
if ( current_user_can( $post_type->cap->edit_others_posts ) && current_user_can( $post_type->cap->publish_posts ) ) { | ||
$rels[] = 'https://api.w.org/action-sticky'; | ||
} | ||
} | ||
|
||
if ( post_type_supports( $post_type->name, 'author' ) ) { | ||
if ( current_user_can( $post_type->cap->edit_others_posts ) ) { | ||
$rels[] = 'https://api.w.org/action-assign-author'; | ||
} | ||
} | ||
|
||
$taxonomies = wp_list_filter( get_object_taxonomies( $this->post_type, 'objects' ), array( 'show_in_rest' => true ) ); | ||
|
||
foreach ( $taxonomies as $tax ) { | ||
$tax_base = ! empty( $tax->rest_base ) ? $tax->rest_base : $tax->name; | ||
|
||
if ( current_user_can( $tax->cap->edit_terms ) ) { | ||
$rels[] = 'https://api.w.org/action-create-' . $tax_base; | ||
} | ||
|
||
if ( current_user_can( $tax->cap->assign_terms ) ) { | ||
$rels[] = 'https://api.w.org/action-assign-' . $tax_base; | ||
} | ||
} | ||
|
||
return $rels; | ||
} | ||
} |
45 changes: 45 additions & 0 deletions
45
lib/compat/wordpress-6.4/class-gutenberg-rest-pattern-categories-controller.php
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,45 @@ | ||
<?php | ||
/** | ||
* Gutenberg_REST_Pattern_Categories_Controller class | ||
* | ||
* Extends the WP_REST_Terms_Controller to handle permissions of pattern categories. | ||
* | ||
* @package Gutenberg | ||
* @subpackage REST_API | ||
* @since 6.4.0 | ||
*/ | ||
|
||
/** | ||
* Extends the WP_REST_Terms_Controller to handle permissions of pattern categories. | ||
* | ||
* @access public | ||
*/ | ||
class Gutenberg_REST_Pattern_Categories_Controller extends WP_REST_Terms_Controller { | ||
/** | ||
* Make pattern categories behave more like a hierarchical taxonomy in terms of permissions. | ||
* Check the edit_terms cap to see whether term creation is possible. | ||
* | ||
* @since 6.4.0 | ||
* | ||
* @param WP_REST_Request $request Request object. | ||
* @return WP_REST_Response|WP_Error Response object on success, or WP_Error object on failure. | ||
*/ | ||
public function create_item_permissions_check( $request ) { // phpcs:ignore VariableAnalysis.CodeAnalysis.VariableAnalysis.UnusedVariable | ||
if ( ! $this->check_is_taxonomy_allowed( $this->taxonomy ) ) { | ||
return false; | ||
} | ||
|
||
$taxonomy_obj = get_taxonomy( $this->taxonomy ); | ||
|
||
// Patterns categories are a flat hierarchy (like tags), but work more like post categories in terms of permissions. | ||
if ( ! current_user_can( $taxonomy_obj->cap->edit_terms ) ) { | ||
return new WP_Error( | ||
'rest_cannot_create', | ||
__( 'Sorry, you are not allowed to create terms in this taxonomy.' ), | ||
array( 'status' => rest_authorization_required_code() ) | ||
); | ||
} | ||
|
||
return true; | ||
} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
119 changes: 119 additions & 0 deletions
119
packages/editor/src/components/post-taxonomies/pattern-categories-selector.js
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,119 @@ | ||
/** | ||
* WordPress dependencies | ||
*/ | ||
import { useSelect, useDispatch } from '@wordpress/data'; | ||
import { store as coreStore } from '@wordpress/core-data'; | ||
import { addFilter } from '@wordpress/hooks'; | ||
import { privateApis as patternsPrivateApis } from '@wordpress/patterns'; | ||
|
||
/** | ||
* Internal dependencies | ||
*/ | ||
import { unlock } from '../../lock-unlock'; | ||
import { store as editorStore } from '../../store'; | ||
|
||
const { CategorySelector } = unlock( patternsPrivateApis ); | ||
|
||
const EMPTY_ARRAY = []; | ||
|
||
const DEFAULT_QUERY = { | ||
per_page: -1, | ||
orderby: 'name', | ||
order: 'asc', | ||
_fields: 'id,name,parent', | ||
context: 'view', | ||
}; | ||
|
||
/* | ||
* Pattern categories are a flat taxonomy but do not allow Author users and below to create | ||
* new categories, so this selector overrides the default flat taxonomy selector for | ||
* wp_block post types and users without 'create' capability for wp_pattern_category. | ||
*/ | ||
export function PatternCategoriesSelector( { slug } ) { | ||
const { hasAssignAction, terms, availableTerms, taxonomy, loading } = | ||
useSelect( | ||
( select ) => { | ||
const { getCurrentPost, getEditedPostAttribute } = | ||
select( editorStore ); | ||
const { getTaxonomy, getEntityRecords, isResolving } = | ||
select( coreStore ); | ||
const _taxonomy = getTaxonomy( slug ); | ||
const post = getCurrentPost(); | ||
|
||
return { | ||
hasAssignAction: _taxonomy | ||
? post._links?.[ | ||
'wp:action-assign-' + _taxonomy.rest_base | ||
] ?? false | ||
: false, | ||
terms: _taxonomy | ||
? getEditedPostAttribute( _taxonomy.rest_base ) | ||
: EMPTY_ARRAY, | ||
loading: isResolving( 'getEntityRecords', [ | ||
'taxonomy', | ||
slug, | ||
DEFAULT_QUERY, | ||
] ), | ||
availableTerms: | ||
getEntityRecords( 'taxonomy', slug, DEFAULT_QUERY ) || | ||
EMPTY_ARRAY, | ||
taxonomy: _taxonomy, | ||
}; | ||
}, | ||
[ slug ] | ||
); | ||
|
||
const { editPost } = useDispatch( editorStore ); | ||
|
||
if ( ! hasAssignAction || loading || availableTerms.length === 0 ) { | ||
return null; | ||
} | ||
|
||
const onUpdateTerms = ( termIds ) => { | ||
editPost( { [ taxonomy.rest_base ]: termIds } ); | ||
}; | ||
|
||
const onChange = ( term ) => { | ||
const hasTerm = terms.includes( term.id ); | ||
const newTerms = hasTerm | ||
? terms.filter( ( id ) => id !== term.id ) | ||
: [ ...terms, term.id ]; | ||
onUpdateTerms( newTerms ); | ||
}; | ||
|
||
const isCategorySelected = ( term ) => terms.includes( term.id ); | ||
|
||
const categoryOptions = availableTerms.map( ( term ) => ( { | ||
...term, | ||
label: term.name, | ||
} ) ); | ||
|
||
return ( | ||
<CategorySelector | ||
onChange={ onChange } | ||
categoryOptions={ categoryOptions } | ||
isCategorySelected={ isCategorySelected } | ||
showLabel={ false } | ||
/> | ||
); | ||
} | ||
|
||
export default function patternCategorySelector( OriginalComponent ) { | ||
return function ( props ) { | ||
const canAddCategories = useSelect( ( select ) => { | ||
const { canUser } = select( coreStore ); | ||
return canUser( 'create', 'wp_pattern_category' ); | ||
} ); | ||
if ( props.slug === 'wp_pattern_category' && ! canAddCategories ) { | ||
return <PatternCategoriesSelector { ...props } />; | ||
} | ||
|
||
return <OriginalComponent { ...props } />; | ||
}; | ||
} | ||
|
||
addFilter( | ||
'editor.PostTaxonomyType', | ||
'core/pattern-category-selector', | ||
patternCategorySelector | ||
); |
Oops, something went wrong.
5b10d27
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Flaky tests detected in 5b10d27.
Some tests passed with failed attempts. The failures may not be related to this commit but are still reported for visibility. See the documentation for more information.
🔍 Workflow run URL: https://github.com/WordPress/gutenberg/actions/runs/6585743306
📝 Reported issues:
specs/site-editor/multi-entity-saving.test.js
specs/editor/various/pattern-blocks.test.js
specs/editor/various/pattern-blocks.test.js
specs/editor/various/pattern-blocks.test.js
specs/editor/various/pattern-blocks.test.js